dmd.escape

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

Authors

Walter Bright

Source: escape.d

  • Declaration

    struct EscapeState;

    Groups global state for escape checking together

    • Declaration

      static void reset();

      Called by initDMD / deinitializeDMD to reset global state

  • 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

  • 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

  • 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

  • Declaration

    void printScopeFailure(E)(E printFunc, VarDeclaration v, int recursionLimit);

    A scope variable was assigned to non-scope parameter v. If applicable, print why the parameter was not inferred scope.

    Parameters

    E printFunc

    error/deprecation print function to use

    VarDeclaration v

    parameter that was not inferred

    int recursionLimit

    recursion limit for printing the reason

  • Declaration

    bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId, VarDeclaration vPar, STC parStc, 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

    Identifier parId

    name of function parameter for error messages

    VarDeclaration vPar

    VarDeclaration corresponding to par

    STC parStc

    storage classes of function parameter (may have added scope from pure)

    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

  • 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

  • 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

  • Declaration

    enum ReturnParamDest: int;

    How a return parameter escapes its pointer value

    • Declaration

      returnVal

      through return statement: return x

    • Declaration

      this_

      assigned to a struct instance: this.x = x

    • Declaration

      firstArg

      assigned to first argument: firstArg = x

  • Declaration

    ReturnParamDest returnParamDest(TypeFunction tf, Type tthis);

    Find out if instead of returning a return parameter via a return statement, it is returned via assignment to either this or the first parameter.

    Discussion

    This works the same as returning the value via a return statement. Although the first argument must be ref, it is not regarded as returning by ref.

    Parameters

    TypeFunction tf

    function type

    Type tthis

    type of this parameter, or null if none

    Return Value

    What a return parameter should transfer the lifetime of the argument to

  • 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

  • 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

  • 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

  • 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

  • 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

  • Declaration

    bool inferScope(VarDeclaration va);

    Infer scope for a variable

    Parameters

    VarDeclaration va

    variable to infer scope for

    Return Value

    true if succesful or already scope

  • Declaration

    void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool retRefTransition = 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.

    bool retRefTransition

    if e is returned through a return ref scope function call

  • Declaration

    void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retRefTransition = 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.

    bool retRefTransition

    if e is returned through a return ref scope function call

  • Declaration

    struct EscapeByResults;

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

    • Declaration

      void reset();

      Reset arrays so the storage can be used again

    • Declaration

      void pushRef(VarDeclaration v, bool retRefTransition);

      Escape variable v by reference

      Parameters

      VarDeclaration v

      variable to escape

      bool retRefTransition

      v is escaped through a return ref scope function call

    • Declaration

      void pushExp(Expression e, bool retRefTransition);

      Escape a reference to expression e

      Parameters

      Expression e

      expression to escape

      bool retRefTransition

      e is escaped through a return ref scope function call

  • 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

  • Declaration

    void finishScopeParamInference(FuncDeclaration funcdecl, ref TypeFunction f);

    After semantic analysis of the function body, try to infer scope / return on the parameters

    Parameters

    FuncDeclaration funcdecl

    function declaration that was analyzed

    TypeFunction f

    final function type. funcdecl.type started as the 'premature type' before attribute inference, then its inferred attributes are copied over to final type f

  • 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

  • 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