Menu

- Learn
- Documentation
  - Language Reference
  - Library Reference
  - Command-line Reference
  - Feature Overview
  - Articles
- Downloads
- Packages
- Community
  - Blog
  - Orgs using D
  - Twitter
  - Calendar
  - Forums
  - IRC
  - Community Discord
  - Wiki
  - GitHub
  - Issues
  - Get involved
  - Contributors
  - Foundation
  - Security Team
  - Donate
  - Sponsors
- Resources
  - Tour
  - Books
  - Tutorials
  - Tools
  - Editors
  - IDEs
  - run.dlang.io
  - Visual D
  - Acknowledgments
  - D Style
  - Glossary
  - Sitemap

Search
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:
Walter Bright
License:
Boost License 1.0

Source ob.d

Documentation https://dlang.org/phobos/dmd_escape.html

Coverage https://codecov.io/gh/dlang/dmd/src/master/src/dmd/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)* `toChars`(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

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?

Copyright © 1999-2020 by the D Language Foundation | Page generated by Ddoc on Tue Jul 7 12:26:08 2020