Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.


Flow analysis for Ownership/Borrowing

Source ob.d

References Argument Ownership and Function Calls

void oblive(FuncDeclaration funcdecl);
Perform ownership/borrowing checks for funcdecl. Does not modify the AST, just checks for errors.
struct ObState;
Collect the state information.
Array!size_t varStack;
temporary storage
Array!bool mutableStack;
parallel to varStack[], is type mutable?
PtrVarState[] varPool;
memory pool
struct ObNode;
A node in the function's expression graph, and its edges to predecessors and successors.
Expression exp;
expression for the node
ObNodes preds;
ObNodes succs;
ObNode* tryBlock;
try-finally block we're inside
uint index;
index of this in obnodes
PtrVarState[] gen;
new states generated for this node
PtrVarState[] input;
variable states on entry to exp
PtrVarState[] output;
variable states on exit to exp
enum PtrState: ubyte;
Pointer variable states:
Initial state is not known; ignore for now
Undefined not in a usable state
T* p = void;
Owner mutable pointer
T* p = initializer;
Borrowed scope mutable pointer, borrowed from [p]
T* p = initializer; scope T* b = p;
Readonly scope const pointer, copied from [p]
T* p = initializer; scope const(T)* cp = p;
T* p = initializer; // p is owner T** pp = &p; // pp borrows from p
T* p = initialize; // p is owner T* q = p; // transfer: q is owner, p is undefined
const(char)* PtrStateToChars(PtrState state);
struct PtrVarState;
Carries the state of a pointer variable.
BitArray deps;
PtrState state;
state the pointer variable is in
void print(VarDeclaration[] vars);
Print a bracketed list of all the variables that depend on 'this'
VarDeclaration[] vars variables that depend on 'this'
void depsToBuf(ref OutBuffer buf, const VarDeclaration[] vars);
Produce a user-readable comma separated string of the dependencies.
OutBuffer buf write resulting string here
VarDeclaration[] vars array from which to get the variable names
void setLabelStatementExtraFields(DsymbolTable labtab);
Set the .extra field for LabelStatements in labtab[].
void toObNodes(ref ObNodes obnodes, Statement s);
Convert statement into ObNodes.
void insertFinallyBlockCalls(ref ObNodes obnodes);
Insert finally block calls when doing a goto from inside a try block to outside. Done after blocks are generated because then we know all the edges of the graph, but before the pred's are computed.
ObNodes obnodes graph of the function
void insertFinallyBlockGotos(ref ObNodes obnodes);
Remove try-finally scaffolding.
ObNodes obnodes nodes for the function
@safe void numberNodes(ref ObNodes obnodes);
Set the index field of each ObNode to its index in the obnodes[] array.
void removeUnreachable(ref ObNodes obnodes);
Remove unreachable nodes and compress them out of obnodes[].
ObNodes obnodes array of nodes
void computePreds(ref ObNodes obnodes);
Compute predecessors.
bool isTrackableVar(VarDeclaration v);
Are we interested in tracking variable v?
VarDeclaration isTrackableVarExp(Expression e);
Are we interested in tracking this expression?
variable if so, null if not
void collectVars(FuncDeclaration funcdecl, out VarDeclarations vars);
Find the pointer variable declarations in this function, and fill vars with them.
FuncDeclaration funcdecl function we are in
VarDeclarations vars array to fill in
void allocDeps(PtrVarState[] pvss);
Allocate BitArrays in PtrVarState. Can be allocated much more efficiently by subdividing a single large array of bits
void allocStates(ref ObState obstate);
Allocate state variables foreach node.
bool isBorrowedPtr(VarDeclaration v);
Does v meet the definiton of a Borrowed pointer?
true if it does
bool isReadonlyPtr(VarDeclaration v);
Does v meet the definiton of a Readonly pointer?
true if it does
void genKill(ref ObState obstate, ObNode* ob);
Compute the gen vector for ob.
PtrState toPtrState(VarDeclaration v);
Determine the state of a variable based on its type and storage class.
bool hasPointersToMutableFields(Type t);
Does type t contain any pointers to mutable?
bool hasMutableFields(Type t);
Does type t have any mutable fields?
void doDataFlowAnalysis(ref ObState obstate);
Do the data flow analysis (i.e. compute the input[] and output[] vectors for each ObNode).
void escapeLive(Expression e, scope void delegate(VarDeclaration) onVar);
Check for escaping variables using DIP1000's escapeByValue, with live set to true
Expression e expression to check
void delegate(VarDeclaration) onVar gets called for each variable escaped through e, either by value or by ref
void checkObErrors(ref ObState obstate);
Check for Ownership/Borrowing errors.
void readVar(ObNode* ob, const size_t vi, bool mutable, PtrVarState[] gen);
Read from variable vi. The beginning of the 'scope' of a variable is when it is first read. Hence, when a read is done, instead of when assignment to the variable is done, the O/B rules are enforced. (Also called "non-lexical scoping".)
void makeChildrenUndefined(size_t vi, PtrVarState[] gen);
Recursively make Undefined all who list vi as a dependency
void makeUndefined(size_t vi, PtrVarState[] gen);
Recursively make Undefined vi undefined and all who list vi as a dependency
size_t vi variable's index
PtrVarState[] gen array of the states of variables
bool isMutableRef(Type t);
Is type t a reference to a const or a reference to a mutable?