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.

dmd.ob

Flow analysis for Ownership/Borrowing
Authors:

Source ob.d

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;
predecessors
ObNodes succs;
successors
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;
Examples:
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;
dependencies
PtrState state;
state the pointer variable is in
void print(VarDeclaration[] vars);
void depsToBuf(ref OutBuffer buf, const VarDeclaration[] vars);
Produce a user-readable comma separated string of the dependencies.
Parameters:
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.
Parameters:
ObNodes obnodes graph of the function
void insertFinallyBlockGotos(ref ObNodes obnodes);
Remove try-finally scaffolding.
Parameters:
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[].
Parameters:
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?
Returns:
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.
Parameters:
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?
Returns:
true if it does
bool isReadonlyPtr(VarDeclaration v);
Does v meet the definiton of a Readonly pointer?
Returns:
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 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
bool isMutableRef(Type t);
Is type t a reference to a const or a reference to a mutable?