# dmd.escape

Most of the logic to implement scoped pointers and scoped references is here.

#### Authors

Walter Bright

#### License

Boost License 1.0

Source: escape.d

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

Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/escape.d

- `checkMutableArguments`

  #### Declaration

  `bool `checkMutableArguments`(Scope* `sc`, FuncDeclaration `fd`, TypeFunction `tf`, Expression `ethis`, Expressions* `arguments`, bool `gag`);`

  Checks memory objects passed to a function. Checks that if a memory object is passed by ref or by pointer, all of the refs or pointers are const, or there is only one mutable ref or pointer to it.

  References: DIP 1021

  #### Parameters

  `Scope* `sc`` | used to determine current function and module
  `FuncDeclaration `fd`` | function being called
  `TypeFunction `tf`` | `fd`'s type
  `Expression `ethis`` | if not `null`, the `this` pointer
  `Expressions* `arguments`` | actual `arguments` to function
  `bool `gag`` | do not print error messages

  #### Return Value

  `true` if error

- `checkArrayLiteralEscape`

  #### Declaration

  `bool `checkArrayLiteralEscape`(Scope* `sc`, ArrayLiteralExp `ae`, bool `gag`);`

  Array literal is going to be allocated on the GC heap. Check its elements to see if any would escape by going on the heap.

  #### Parameters

  `Scope* `sc`` | used to determine current function and module
  `ArrayLiteralExp `ae`` | array literal expression
  `bool `gag`` | do not print error messages

  #### Return Value

  `true` if any elements escaped

- `checkAssocArrayLiteralEscape`

  #### Declaration

  `bool `checkAssocArrayLiteralEscape`(Scope* `sc`, AssocArrayLiteralExp `ae`, bool `gag`);`

  Associative array literal is going to be allocated on the GC heap. Check its elements to see if any would escape by going on the heap.

  #### Parameters

  `Scope* `sc`` | used to determine current function and module
  `AssocArrayLiteralExp `ae`` | associative array literal expression
  `bool `gag`` | do not print error messages

  #### Return Value

  `true` if any elements escaped

- `checkParamArgumentEscape`

  #### Declaration

  `bool `checkParamArgumentEscape`(Scope* `sc`, FuncDeclaration `fdc`, Parameter `par`, Expression `arg`, bool `assertmsg`, bool `gag`);`

  Function parameter ``par`` is being initialized to ``arg``, and ``par`` may escape. Detect if scoped values can escape this way. Print error messages when these are detected.

  #### Parameters

  `Scope* `sc`` | used to determine current function and module
  `FuncDeclaration `fdc`` | function being called, `null` if called indirectly
  `Parameter `par`` | function parameter (`this` if `null`)
  `Expression `arg`` | initializer for param
  `bool `assertmsg`` | `true` if the parameter is the msg argument to assert(bool, msg).
  `bool `gag`` | do not print error messages

  #### Return Value

  `true` if pointers to the stack can escape via assignment

- `checkParamArgumentReturn`

  #### Declaration

  `bool `checkParamArgumentReturn`(Scope* `sc`, Expression `firstArg`, Expression `arg`, Parameter `param`, bool `gag`);`

  Function argument initializes a `return` parameter, and that parameter gets assigned to ``firstArg``. Essentially, treat as ``firstArg` = `arg`;`

  #### Parameters

  `Scope* `sc`` | used to determine current function and module
  `Expression `firstArg`` | `ref` argument through which ``arg`` may be assigned
  `Expression `arg`` | initializer for parameter
  `Parameter `param`` | parameter declaration corresponding to ``arg``
  `bool `gag`` | do not print error messages

  #### Return Value

  `true` if assignment to ``firstArg`` would cause an error

- `checkConstructorEscape`

  #### Declaration

  `bool `checkConstructorEscape`(Scope* `sc`, CallExp `ce`, bool `gag`);`

  Check struct constructor of the form `s.this(args)`, by checking each `return` parameter to see if it gets assigned to `s`.

  #### Parameters

  `Scope* `sc`` | used to determine current function and module
  `CallExp `ce`` | constructor call of the form `s.this(args)`
  `bool `gag`` | do not print error messages

  #### Return Value

  `true` if construction would cause an escaping reference error

- `checkAssignEscape`

  #### Declaration

  `bool `checkAssignEscape`(Scope* `sc`, Expression `e`, bool `gag`, bool `byRef`);`

  Given an `AssignExp`, determine if the lvalue will cause the contents of the rvalue to escape. Print error messages when these are detected. Infer `scope` attribute for the lvalue where possible, in order to eliminate the error.

  #### Parameters

  `Scope* `sc`` | used to determine current function and module
  `Expression `e`` | `AssignExp` or `CatAssignExp` to check for any pointers to the stack
  `bool `gag`` | do not print error messages
  `bool `byRef`` | set to `true` if `e1` of ``e`` gets assigned a reference to `e2`

  #### Return Value

  `true` if pointers to the stack can escape via assignment

- `checkThrowEscape`

  #### Declaration

  `bool `checkThrowEscape`(Scope* `sc`, Expression `e`, bool `gag`);`

  Detect cases where pointers to the stack can escape the lifetime of the stack frame when throwing ``e``. Print error messages when these are detected.

  #### Parameters

  `Scope* `sc`` | used to determine current function and module
  `Expression `e`` | expression to check for any pointers to the stack
  `bool `gag`` | do not print error messages

  #### Return Value

  `true` if pointers to the stack can escape

- `checkNewEscape`

  #### Declaration

  `bool `checkNewEscape`(Scope* `sc`, Expression `e`, bool `gag`);`

  Detect cases where pointers to the stack can escape the lifetime of the stack frame by being placed into a GC allocated object. Print error messages when these are detected.

  #### Parameters

  `Scope* `sc`` | used to determine current function and module
  `Expression `e`` | expression to check for any pointers to the stack
  `bool `gag`` | do not print error messages

  #### Return Value

  `true` if pointers to the stack can escape

- `checkReturnEscape`

  #### Declaration

  `bool `checkReturnEscape`(Scope* `sc`, Expression `e`, bool `gag`);`

  Detect cases where pointers to the stack can escape the lifetime of the stack frame by returning ``e`` by value. Print error messages when these are detected.

  #### Parameters

  `Scope* `sc`` | used to determine current function and module
  `Expression `e`` | expression to check for any pointers to the stack
  `bool `gag`` | do not print error messages

  #### Return Value

  `true` if pointers to the stack can escape

- `checkReturnEscapeRef`

  #### Declaration

  `bool `checkReturnEscapeRef`(Scope* `sc`, Expression `e`, bool `gag`);`

  Detect cases where returning ``e`` by `ref` can result in a reference to the stack being returned. Print error messages when these are detected.

  #### Parameters

  `Scope* `sc`` | used to determine current function and module
  `Expression `e`` | expression to check
  `bool `gag`` | do not print error messages

  #### Return Value

  `true` if references to the stack can escape

- `escapeByValue`

  #### Declaration

  `void `escapeByValue`(Expression `e`, EscapeByResults* `er`, bool `live` = false);`

  `e` is an expression to be returned by value, and that value contains pointers. Walk `e` to determine which variables are possibly being returned by value, such as: int* function(int* p) { return p; } If `e` is a form of &p, determine which variables have content which is being returned as ref, such as: int* function(int i) { return &i; } Multiple variables can be inserted, because of expressions like this: int function(bool b, int i, int* p) { return b ? &i : p; }

  #### Discussion

  No side effects.

  #### Parameters

  `Expression `e`` | expression to be returned by value
  `EscapeByResults* `er`` | where to place collected data
  `bool `live`` | if @`live` semantics apply, i.`e`. expressions `p`, `*p`, `**p`, etc., all return `p`.

- `escapeByRef`

  #### Declaration

  `void `escapeByRef`(Expression `e`, EscapeByResults* `er`, bool `live` = false);`

  `e` is an expression to be returned by 'ref'. Walk `e` to determine which variables are possibly being returned by ref, such as: ref int function(int i) { return i; } If `e` is a form of p, determine which variables have content which is being returned as ref, such as: ref int function(int) p { return p; } Multiple variables can be inserted, because of expressions like this: ref int function(bool b, int i, int) p { return b ? i : *p; }

  #### Discussion

  No side effects.

  #### Parameters

  `Expression `e`` | expression to be returned by 'ref'
  `EscapeByResults* `er`` | where to place collected data
  `bool `live`` | if @`live` semantics apply, i.`e`. expressions `p`, `*p`, `**p`, etc., all return `p`.

- `EscapeByResults`

  #### Declaration

  `struct `EscapeByResults`;`

  Aggregate the data collected by the escapeBy??() functions.

  - `reset`

    #### Declaration

    `void `reset`();`

    Reset arrays so the storage can be used again

- `findAllOuterAccessedVariables`

  #### Declaration

  `void `findAllOuterAccessedVariables`(FuncDeclaration `fd`, VarDeclarations* `vars`);`

  Find all variables accessed by this delegate that are in functions enclosing it.

  #### Parameters

  `FuncDeclaration `fd`` | function
  `VarDeclarations* `vars`` | array to append found variables to

- `notMaybeScope`

  #### Declaration

  `void `notMaybeScope`(VarDeclaration `v`);`

  Turn off `STC.maybescope` for variable ``v``.

  #### Discussion

  This exists in order to find where `STC.maybescope` is getting turned off.

  #### Parameters

  `VarDeclaration `v`` | variable

- `eliminateMaybeScopes`

  #### Declaration

  `void `eliminateMaybeScopes`(VarDeclaration[] `array`);`

  Have some variables that are maybescopes that were assigned values from other maybescope variables. Now that semantic analysis of the function is complete, we can finalize this by turning off maybescope for `array` elements that cannot be scope.

  #### Discussion

  #### Parameters

  `VarDeclaration[] `array`` | `array` of variables that were assigned to from maybescope variables

- `isReferenceToMutable`

  #### Declaration

  `bool `isReferenceToMutable`(Type `t`);`

  Is type a reference to a mutable value?

  #### Discussion

  This is used to determine if an argument that does not have a corresponding Parameter, i.e. a variadic argument, is a pointer to mutable data.

  #### Parameters

  `Type `t`` | type of the argument

  #### Return Value

  `true` if it's a pointer (or reference) to mutable data

- `isReferenceToMutable`

  #### Declaration

  `bool `isReferenceToMutable`(Parameter `p`, Type `t`);`

  Is parameter a reference to a mutable value?

  #### Discussion

  This is used if an argument has a corresponding Parameter. The argument type is necessary if the Parameter is inout.

  #### Parameters

  `Parameter `p`` | Parameter to check
  `Type `t`` | type of corresponding argument

  #### Return Value

  `true` if it's a pointer (or reference) to mutable data