# 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

- `oblive`

  #### Declaration

  `void `oblive`(FuncDeclaration `funcdecl`);`

  Perform ownership/borrowing checks for `funcdecl`. Does not modify the AST, just checks for errors.

- `ObState`

  #### Declaration

  `struct `ObState`;`

  Collect the state information.

  - `varStack`

    #### Declaration

    `Array!size_t `varStack`;`

    temporary storage

  - `mutableStack`

    #### Declaration

    `Array!bool `mutableStack`;`

    parallel to varStack[], is type mutable?

  - `varPool`

    #### Declaration

    `PtrVarState[] `varPool`;`

    memory pool

- `ObNode`

  #### Declaration

  `struct `ObNode`;`

  A node in the function's expression graph, and its edges to predecessors and successors.

  - `exp`

    #### Declaration

    `Expression `exp`;`

    expression for the node

  - `preds`

    #### Declaration

    `ObNodes `preds`;`

    predecessors

  - `succs`

    #### Declaration

    `ObNodes `succs`;`

    successors

  - `tryBlock`

    #### Declaration

    `ObNode* `tryBlock`;`

    try-finally block we're inside

  - `index`

    #### Declaration

    `uint `index`;`

    `index` of this in obnodes

  - `gen`

    #### Declaration

    `PtrVarState[] `gen`;`

    new states generated for this node

  - `input`

    #### Declaration

    `PtrVarState[] `input`;`

    variable states on entry to exp

  - `output`

    #### Declaration

    `PtrVarState[] `output`;`

    variable states on exit to exp

- `PtrState`

  #### Declaration

  `enum `PtrState`: ubyte;`

  Pointer variable states:

  #### Discussion

  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

- `toChars`

  #### Declaration

  `const(char)* `toChars`(PtrState `state`);`

- `PtrVarState`

  #### Declaration

  `struct `PtrVarState`;`

  Carries the state of a pointer variable.

  - `deps`

    #### Declaration

    `BitArray `deps`;`

    dependencies

  - `state`

    #### Declaration

    `PtrState `state`;`

    `state` the pointer variable is in

  - `print`

    #### Declaration

    `void `print`(VarDeclaration[] `vars`);`

  - `depsToBuf`

    #### Declaration

    `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

- `setLabelStatementExtraFields`

  #### Declaration

  `void `setLabelStatementExtraFields`(DsymbolTable `labtab`);`

  Set the `.extra` field for LabelStatements in `labtab`[].

- `toObNodes`

  #### Declaration

  `void `toObNodes`(ref ObNodes `obnodes`, Statement `s`);`

  Convert statement into ObNodes.

- `insertFinallyBlockCalls`

  #### Declaration

  `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

- `insertFinallyBlockGotos`

  #### Declaration

  `void `insertFinallyBlockGotos`(ref ObNodes `obnodes`);`

  Remove try-finally scaffolding.

  #### Parameters

  `ObNodes `obnodes`` | nodes for the function

- `numberNodes`

  #### Declaration

  `@safe void `numberNodes`(ref ObNodes `obnodes`);`

  Set the `index` field of each ObNode to its index in the ``obnodes`[]` array.

- `removeUnreachable`

  #### Declaration

  `void `removeUnreachable`(ref ObNodes `obnodes`);`

  Remove unreachable nodes and compress them out of `obnodes`[].

  #### Parameters

  `ObNodes `obnodes`` | array of nodes

- `computePreds`

  #### Declaration

  `void `computePreds`(ref ObNodes `obnodes`);`

  Compute predecessors.

- `isTrackableVar`

  #### Declaration

  `bool `isTrackableVar`(VarDeclaration `v`);`

  Are we interested in tracking variable ``v``?

- `isTrackableVarExp`

  #### Declaration

  `VarDeclaration `isTrackableVarExp`(Expression `e`);`

  Are we interested in tracking this expression?

  #### Return Value

  variable if so, `null` if not

- `collectVars`

  #### Declaration

  `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

- `allocDeps`

  #### Declaration

  `void `allocDeps`(PtrVarState[] `pvss`);`

  Allocate BitArrays in PtrVarState. Can be allocated much more efficiently by subdividing a single large array of bits

- `allocStates`

  #### Declaration

  `void `allocStates`(ref ObState `obstate`);`

  Allocate state variables foreach node.

- `isBorrowedPtr`

  #### Declaration

  `bool `isBorrowedPtr`(VarDeclaration `v`);`

  Does `v` meet the definiton of a `Borrowed` pointer?

  #### Return Value

  `true` if it does

- `isReadonlyPtr`

  #### Declaration

  `bool `isReadonlyPtr`(VarDeclaration `v`);`

  Does `v` meet the definiton of a `Readonly` pointer?

  #### Return Value

  `true` if it does

- `genKill`

  #### Declaration

  `void `genKill`(ref ObState `obstate`, ObNode* `ob`);`

  Compute the gen vector for `ob`.

- `toPtrState`

  #### Declaration

  `PtrState `toPtrState`(VarDeclaration `v`);`

  Determine the state of a variable based on its type and storage class.

- `hasPointersToMutableFields`

  #### Declaration

  `bool `hasPointersToMutableFields`(Type `t`);`

  Does type ``t`` contain any pointers to mutable?

- `hasMutableFields`

  #### Declaration

  `bool `hasMutableFields`(Type `t`);`

  Does type ``t`` have any mutable fields?

- `doDataFlowAnalysis`

  #### Declaration

  `void `doDataFlowAnalysis`(ref ObState `obstate`);`

  Do the data flow analysis (i.e. compute the input[] and output[] vectors for each ObNode).

- `checkObErrors`

  #### Declaration

  `void `checkObErrors`(ref ObState `obstate`);`

  Check for Ownership/Borrowing errors.

- `readVar`

  #### Declaration

  `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".)

- `makeChildrenUndefined`

  #### Declaration

  `void `makeChildrenUndefined`(size_t `vi`, PtrVarState[] `gen`);`

  Recursively make Undefined all who list `vi` as a dependency

- `makeUndefined`

  #### Declaration

  `void `makeUndefined`(size_t `vi`, PtrVarState[] `gen`);`

  Recursively make Undefined `vi` undefined and all who list `vi` as a dependency

- `isMutableRef`

  #### Declaration

  `bool `isMutableRef`(Type `t`);`

  Is type ``t`` a reference to a const or a reference to a mutable?