# dmd.func

Defines a function declaration.

Includes:

- function/delegate literals
- function aliases
- (static/shared) constructors/destructors/post-blits
- `invariant`
- `unittest`

#### Authors

Walter Bright

#### License

Boost License 1.0

Source: func.d

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

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

- `ILS`

  #### Declaration

  `enum `ILS`: ubyte;`

  Inline Status

  - `uninitialized`

    #### Declaration

    ``uninitialized``

    not computed yet

  - `no`

    #### Declaration

    ``no``

    cannot inline

  - `yes`

    #### Declaration

    ``yes``

    can inline

- `Ensure`

  #### Declaration

  `struct `Ensure`;`

  Tuple of result identifier (possibly `null`) and statement. This is used to store out contracts: out(id){ ensure }

  - `arraySyntaxCopy`

    #### Declaration

    `static Ensures* `arraySyntaxCopy`(Ensures* `a`);`

    Do syntax copy of an array of Ensure's.

- `FuncDeclaration`

  #### Declaration

  `class `FuncDeclaration`: dmd.declaration.Declaration;`

  - `frequires`

    #### Declaration

    `Statements* `frequires`;`

    in contracts

  - `fensures`

    #### Declaration

    `Ensures* `fensures`;`

    out contracts

  - `frequire`

    #### Declaration

    `Statement `frequire`;`

    lowered in contract

  - `fensure`

    #### Declaration

    `Statement `fensure`;`

    lowered out contract

  - `fbody`

    #### Declaration

    `Statement `fbody`;`

    function body

  - `foverrides`

    #### Declaration

    `FuncDeclarations `foverrides`;`

    functions this function overrides

  - `fdrequire`

    #### Declaration

    `FuncDeclaration `fdrequire`;`

    function that does the in contract

  - `fdensure`

    #### Declaration

    `FuncDeclaration `fdensure`;`

    function that does the out contract

  - `fdrequireParams`

    #### Declaration

    `Expressions* `fdrequireParams`;`

    argument list for __require

  - `fdensureParams`

    #### Declaration

    `Expressions* `fdensureParams`;`

    argument list for __ensure

  - `mangleString`

    #### Declaration

    `const(char)* `mangleString`;`

    mangled symbol created from mangleExact()

  - `vresult`

    #### Declaration

    `VarDeclaration `vresult`;`

    result variable for out contracts

  - `returnLabel`

    #### Declaration

    `LabelDsymbol `returnLabel`;`

    where the return goes

  - `isTypeIsolatedCache`

    #### Declaration

    `bool[size_t] `isTypeIsolatedCache`;`

    cache for the potentially very expensive isTypeIsolated check

  - `vthis`

    #### Declaration

    `VarDeclaration `vthis`;`

    'this' parameter (member and nested)

  - `v_arguments`

    #### Declaration

    `VarDeclaration `v_arguments`;`

    'arguments' parameter

  - `v_argptr`

    #### Declaration

    `VarDeclaration `v_argptr`;`

    'argptr' variable

  - `parameters`

    #### Declaration

    `VarDeclarations* `parameters`;`

    Array of VarDeclaration's for `parameters`

  - `labtab`

    #### Declaration

    `DsymbolTable `labtab`;`

    statement label symbol table

  - `overnext`

    #### Declaration

    `Dsymbol `overnext`;`

    next in overload list

  - `overnext0`

    #### Declaration

    `FuncDeclaration `overnext0`;`

    next in overload list (only used during IFTI)

  - `endloc`

    #### Declaration

    `Loc `endloc`;`

    location of closing curly bracket

  - `vtblIndex`

    #### Declaration

    `int `vtblIndex`;`

    for member functions, index into vtbl[]

  - `inlineNest`

    #### Declaration

    `int `inlineNest`;`

    !=0 if nested inline

  - `fes`

    #### Declaration

    `ForeachStatement `fes`;`

    if foreach body, this is the foreach

  - `interfaceVirtual`

    #### Declaration

    `BaseClass* `interfaceVirtual`;`

    if virtual, but only appears in base interface vtbl[]

  - `tintro`

    #### Declaration

    `Type `tintro`;`

    if !=NULL, then this is the type of the 'introducing' function this one is overriding

  - `storage_class2`

    #### Declaration

    `StorageClass `storage_class2`;`

    storage class for template onemember's

  - `hasReturnExp`

    #### Declaration

    `int `hasReturnExp`;`

    1 if there's a return exp; statement 2 if there's a throw statement 4 if there's an assert(0) 8 if there's inline asm 16 if there are multiple return statements

  - `nrvo_var`

    #### Declaration

    `VarDeclaration `nrvo_var`;`

    variable to replace with shidden

  - `shidden`

    #### Declaration

    `Symbol* `shidden`;`

    hidden pointer passed to function

  - `gotos`

    #### Declaration

    `GotoStatements* `gotos`;`

    Gotos with forward references

  - `builtin`

    #### Declaration

    `BUILTIN `builtin`;`

    set if this is a known, `builtin` function we can evaluate at compile time

  - `tookAddressOf`

    #### Declaration

    `int `tookAddressOf`;`

    set if someone took the address of this function

  - `closureVars`

    #### Declaration

    `VarDeclarations `closureVars`;`

    local variables in this function which are referenced by nested functions (They'll get put into the "closure" for this function.)

  - `outerVars`

    #### Declaration

    `VarDeclarations `outerVars`;`

    Outer variables which are referenced by this nested function (the inverse of closureVars)

  - `siblingCallers`

    #### Declaration

    `FuncDeclarations `siblingCallers`;`

    Sibling nested functions which called this one

  - `flags`

    #### Declaration

    `uint `flags`;`

    Function `flags`: A collection of boolean packed for memory efficiency See the `FUNCFLAG` enum

  - `objc`

    #### Declaration

    `ObjcFuncDeclaration `objc`;`

    Data for a function declaration that is needed for the Objective-C integration.

  - `functionSemantic`

    #### Declaration

    `final bool `functionSemantic`();`

    Resolve forward reference of function signature - parameter types, return type, and attributes.

    #### Return Value

    `false` if any errors exist in the signature.

  - `functionSemantic3`

    #### Declaration

    `final bool `functionSemantic3`();`

    Resolve forward reference of function body. Returns `false` if any errors exist in the body.

  - `checkForwardRef`

    #### Declaration

    `final bool `checkForwardRef`(const ref Loc `loc`);`

    Check that this function type is properly resolved. If not, report "forward reference error" and return `true`.

  - `declareThis`

    #### Declaration

    `final void `declareThis`(Scope* `sc`);`

    Creates and returns the hidden parameters for this function declaration.

    #### Discussion

    Hidden parameters include the `this` parameter of a class, struct or nested function and the selector parameter for Objective-C methods.

  - `overrides`

    #### Declaration

    `final int `overrides`(FuncDeclaration `fd`);`

    Determine if 'this' `overrides` `fd`. Return !=0 if it does.

  - `findVtblIndex`

    #### Declaration

    `final int `findVtblIndex`(Dsymbols* `vtbl`, int `dim`);`

    Find index of function in `vtbl`[0..`dim`] that this function overrides. Prefer an exact match to a covariant one.

    #### Parameters

    `Dsymbols* `vtbl`` | vtable to use
    `int `dim`` | maximal vtable dimension

    #### Return Value

    -1 didn't find one -2 can't determine because of forward references

  - `overrideInterface`

    #### Declaration

    `final BaseClass* `overrideInterface`();`

    If function a function in a base class, return that base class.

    #### Return Value

    base class if overriding, `null` if not

  - `overloadInsert`

    #### Declaration

    `bool `overloadInsert`(Dsymbol `s`);`

    Overload this FuncDeclaration with the new one f. Return `true` if successful; i.e. no conflict.

  - `overloadExactMatch`

    #### Declaration

    `final FuncDeclaration `overloadExactMatch`(Type `t`);`

    Find function in overload list that exactly matches `t`.

  - `overloadModMatch`

    #### Declaration

    `final FuncDeclaration `overloadModMatch`(const ref Loc `loc`, Type `tthis`, ref bool `hasOverloads`);`

    Find function in overload list that matches to the 'this' modifier. There's four result types.

    #### Discussion

    1. If the '`tthis`' matches only one candidate, it's an "exact match". Returns the function and '`hasOverloads`' is set to `false`. eg. If '`tthis`" is mutable and there's only one mutable method.
    2. If there's two or more match candidates, but a candidate function will be a "better match". Returns the better match function but '`hasOverloads`' is set to `true`. eg. If '`tthis`' is mutable, and there's both mutable and const methods, the mutable method will be a better match.
    3. If there's two or more match candidates, but there's no better match, Returns `null` and '`hasOverloads`' is set to `true` to represent "ambiguous match". eg. If '`tthis`' is mutable, and there's two or more mutable methods.
    4. If there's no candidates, it's "no match" and returns `null` with error report. e.g. If '`tthis`' is const but there's no const methods.
  - `findTemplateDeclRoot`

    #### Declaration

    `final TemplateDeclaration `findTemplateDeclRoot`();`

    find function template root in overload list

  - `inUnittest`

    #### Declaration

    `final bool `inUnittest`();`

    Returns `true` if function was declared directly or indirectly in a unittest block

  - `leastAsSpecialized`

    #### Declaration

    `final MATCH `leastAsSpecialized`(FuncDeclaration `g`);`

    Determine partial specialization order of 'this' vs `g`. This is very similar to TemplateDeclaration::`leastAsSpecialized`().

    #### Return Value

    match 'this' is at least as specialized as `g` 0 `g` is more specialized than 'this'

  - `searchLabel`

    #### Declaration

    `final LabelDsymbol `searchLabel`(Identifier `ident`, const ref Loc `loc` = Loc.initial);`

    Searches for a label with the given identifier. This function will insert a new `LabelDsymbol` into `labtab` if it does not contain a mapping for ``ident``.

    #### Parameters

    `Identifier `ident`` | identifier of the requested label
    `Loc `loc`` | location used when creating a new `LabelDsymbol`

    #### Return Value

    the `LabelDsymbol` for ``ident``

  - `getLevel`

    #### Declaration

    `final int `getLevel`(FuncDeclaration `fd`, int `intypeof`);`

    Determine lexical level difference from `this` to nested function ``fd``.

    #### Parameters

    `FuncDeclaration `fd`` | target of call
    `int `intypeof`` | !=0 if inside typeof

    #### Return Value

    0 same level

    > 0 decrease nesting by number -1 increase nesting by 1 (``fd`` is nested within `this`) LevelError error, `this` cannot call ``fd``

  - `getLevelAndCheck`

    #### Declaration

    `final int `getLevelAndCheck`(const ref Loc `loc`, Scope* `sc`, FuncDeclaration `fd`, Declaration `decl`);`

    Determine lexical level difference from `this` to nested function ``fd``. Issue error if `this` cannot call ``fd``.

    #### Parameters

    `Loc `loc`` | location for error messages
    `Scope* `sc`` | context
    `FuncDeclaration `fd`` | target of call
    `Declaration `decl`` | The `Declaration` that triggered this check. Used to provide a better error message only.

    #### Return Value

    0 same level

    > 0 decrease nesting by number -1 increase nesting by 1 (``fd`` is nested within 'this') LevelError error

  - `toFullSignature`

    #### Declaration

    `final const(char)* `toFullSignature`();`

    for diagnostics, e.g. 'int foo(int x, int y) pure'

  - `isAbstract`

    #### Declaration

    `final bool `isAbstract`();`

    Override so it can work even if semantic() hasn't yet been run.

  - `canInferAttributes`

    #### Declaration

    `final bool `canInferAttributes`(Scope* `sc`);`

    Decide if attributes for this function can be inferred from examining the function body.

    #### Return Value

    `true` if can

  - `initInferAttributes`

    #### Declaration

    `final void `initInferAttributes`();`

    Initialize for inferring the attributes of this function.

  - `setImpure`

    #### Declaration

    `final bool `setImpure`();`

    The function is doing something impure, so mark it as impure. If there's a purity error, return `true`.

  - `setUnsafe`

    #### Declaration

    `final bool `setUnsafe`();`

    The function is doing something unsafe, so mark it as unsafe. If there's a safe error, return `true`.

  - `setGC`

    #### Declaration

    `final bool `setGC`();`

    The function is doing something that may allocate with the GC, so mark it as not nogc (not no-how).

    #### Return Value

    `true` if function is marked as @nogc, meaning a user error occurred

  - `isReturnIsolated`

    #### Declaration

    `final bool `isReturnIsolated`();`

    See if pointers from function parameters, mutable globals, or uplevel functions could leak into return value.

    #### Return Value

    `true` if the function return value is isolated from any inputs to the function

  - `isTypeIsolated`

    #### Declaration

    `final bool `isTypeIsolated`(Type `t`);
    final bool `isTypeIsolated`(Type `t`, ref StringTable!Type `parentTypes`);`

    See if pointers from function parameters, mutable globals, or uplevel functions could leak into type ``t``.

    #### Parameters

    `Type `t`` | type to check if it is isolated

    #### Return Value

    `true` if ``t`` is isolated from any inputs to the function

  - `isNested`

    #### Declaration

    `const bool `isNested`();`

    Determine if function needs a static frame pointer.

    #### Return Value

    `true` if function is really nested within other function.

    Contracts: If `isNested`() returns `true`, isThis() should return `false`, unless the function needs a dual-context pointer.

  - `isThis`

    #### Declaration

    `inout inout(AggregateDeclaration) `isThis`();`

    Determine if function is a non-static member function that has an implicit 'this' expression.

    #### Return Value

    The aggregate it is a member of, or `null`.

    Contracts: Both `isThis`() and isNested() should return `true` if function needs a dual-context pointer, otherwise if `isThis`() returns `true`, isNested() should return `false`.

  - `isUnique`

    #### Declaration

    `final const bool `isUnique`();`

    #### Return Value

    `true` if there are no overloads of this function

  - `checkNestedReference`

    #### Declaration

    `final bool `checkNestedReference`(Scope* `sc`, const ref Loc `loc`);`

    In the current function, we are calling 'this' function.

    1. Check to see if the current function can call 'this' function, issue error if not.
    2. If the current function is not the parent of 'this' function, then add the current function to the list of siblings of 'this' function.
    3. If the current function is a literal, and it's accessing an uplevel scope, then mark it as a delegate.
    Returns `true` if error occurs.
  - `needsClosure`

    #### Declaration

    `final bool `needsClosure`();`

    Look at all the variables in this function that are referenced by nested functions, and determine if a closure needs to be created for them.

  - `checkClosure`

    #### Declaration

    `final bool `checkClosure`();`

    Check that the function contains any closure. If it's @nogc, report suitable errors. This is mostly consistent with FuncDeclaration::needsClosure().

    #### Return Value

    `true` if any errors occur.

  - `hasNestedFrameRefs`

    #### Declaration

    `final bool `hasNestedFrameRefs`();`

    Determine if function's variables are referenced by a function nested within it.

  - `buildResultVar`

    #### Declaration

    `final void `buildResultVar`(Scope* `sc`, Type `tret`);`

    Declare result variable lazily.

  - `mergeFrequire`

    #### Declaration

    `final Statement `mergeFrequire`(Statement `sf`, Expressions* `params`);`

    Merge into this function the 'in' contracts of all it overrides. 'in's are OR'd together, i.e. only one of them needs to pass.

  - `mergeFrequireInclusivePreview`

    #### Declaration

    `final Statement `mergeFrequireInclusivePreview`(Statement `sf`, Expressions* `params`);`

    Merge into this function the 'in' contracts of all it overrides.

  - `needsFensure`

    #### Declaration

    `static bool `needsFensure`(FuncDeclaration `fd`);`

    Determine whether an 'out' contract is declared inside the given function or any of its overrides.

    #### Parameters

    `FuncDeclaration `fd`` | the function to search

    #### Return Value

    `true` found an 'out' contract

  - `buildEnsureRequire`

    #### Declaration

    `final void `buildEnsureRequire`();`

    Rewrite contracts as statements.

  - `mergeFensure`

    #### Declaration

    `final Statement `mergeFensure`(Statement `sf`, Identifier `oid`, Expressions* `params`);`

    Merge into this function the 'out' contracts of all it overrides. 'out's are AND'd together, i.e. all of them need to pass.

  - `getParameterList`

    #### Declaration

    `final ParameterList `getParameterList`();`

    #### Return Value

    the function's parameter list, and whether it is variadic or not.

  - `genCfunc`

    #### Declaration

    `static FuncDeclaration `genCfunc`(Parameters* `fparams`, Type `treturn`, const(char)* `name`, StorageClass `stc` = 0);`

    Generate a FuncDeclaration for a runtime library function.

  - `checkNRVO`

    #### Declaration

    `final bool `checkNRVO`();`

    Check all return statements for a function to verify that returning using NRVO is possible.

    #### Return Value

    `false` if the result cannot be returned by hidden reference.

- `addInvariant`

  #### Declaration

  `Expression `addInvariant`(AggregateDeclaration `ad`, VarDeclaration `vthis`);`

  Generate Expression to call the invariant.

  Input: `ad` aggregate with the invariant `vthis` variable with 'this'

  #### Return Value

  void expression that calls the invariant

- `overloadApply`

  #### Declaration

  `int `overloadApply`(Dsymbol `fstart`, scope int delegate(Dsymbol) `dg`, Scope* `sc` = null);`

  Visit each overloaded function/template in turn, and call `dg`(s) on it. Exit when no more, or `dg`(s) returns nonzero.

  #### Parameters

  `Dsymbol `fstart`` | symbol to start from
  `int delegate(Dsymbol) `dg`` | the delegate to be called on the overload
  `Scope* `sc`` | context used to check if symbol is accessible (and therefore visible), can be `null`

  #### Return Value

  ==0 continue !=0 done (and the return value from the last `dg`() call)

- `MODMatchToBuffer`

  #### Declaration

  `auto `MODMatchToBuffer`(OutBuffer* `buf`, ubyte `lhsMod`, ubyte `rhsMod`);`

  Checks for mismatching modifiers between ``lhsMod`` and ``rhsMod`` and prints the mismatching modifiers to ``buf``.

  #### Discussion

  The modifiers of the ``lhsMod`` mismatching the ones with the ``rhsMod`` are printed, i.e. lhs(shared) vs. rhs() prints "`shared`", wheras lhs() vs rhs(shared) prints "non-shared".

  #### Parameters

  `OutBuffer* `buf`` | output buffer to write to
  `ubyte `lhsMod`` | modifier on the left-hand side
  `ubyte `lhsMod`` | modifier on the right-hand side

  #### Return Value

  A tuple with `isMutable` and `isNotShared` set if the ``lhsMod`` is missing those modifiers (compared to rhs).

  #### Examples

  1. `OutBuffer buf; auto mismatches = MODMatchToBuffer(&buf, MODFlags.shared_, 0); assert(buf[] == "`shared` "); assert(!mismatches.isNotShared); buf.setsize(0); mismatches = MODMatchToBuffer(&buf, 0, MODFlags.shared_); assert(buf[] == "non-shared "); assert(mismatches.isNotShared); buf.setsize(0); mismatches = MODMatchToBuffer(&buf, MODFlags.const_, 0); assert(buf[] == "`const` "); assert(!mismatches.isMutable); buf.setsize(0); mismatches = MODMatchToBuffer(&buf, 0, MODFlags.const_); assert(buf[] == "mutable "); assert(mismatches.isMutable);`
- `FuncResolveFlag`

  #### Declaration

  `enum `FuncResolveFlag`: ubyte;`

  Flag used by .

  - `standard`

    #### Declaration

    ``standard``

    issue error messages, solve the call.

  - `quiet`

    #### Declaration

    ``quiet``

    do not issue error message on no match, just return `null`.

  - `overloadOnly`

    #### Declaration

    ``overloadOnly``

    only resolve overloads, i.e. do not issue error on ambiguous

- `resolveFuncCall`

  #### Declaration

  `FuncDeclaration `resolveFuncCall`(const ref Loc `loc`, Scope* `sc`, Dsymbol `s`, Objects* `tiargs`, Type `tthis`, Expressions* `fargs`, FuncResolveFlag `flags`);`

  Given a symbol that could be either a FuncDeclaration or a function template, resolve it to a function symbol.

  #### Parameters

  `Loc `loc`` | instantiation location
  `Scope* `sc`` | instantiation scope
  `Dsymbol `s`` | instantiation symbol
  `Objects* `tiargs`` | initial list of template arguments
  `Type `tthis`` | if !NULL, the `this` argument type
  `Expressions* `fargs`` | arguments to function
  `FuncResolveFlag `flags`` | see .

  #### Return Value

  if match is found, then function symbol, else `null`

- `getIndirection`

  #### Declaration

  `Type `getIndirection`(Type `t`);`

  Returns an indirect type one step from `t`.

- `FuncAliasDeclaration`

  #### Declaration

  `class `FuncAliasDeclaration`: dmd.func.FuncDeclaration;`

  Used as a way to import a set of functions from another scope into this one.

- `FuncLiteralDeclaration`

  #### Declaration

  `class `FuncLiteralDeclaration`: dmd.func.FuncDeclaration;`

  - `modifyReturns`

    #### Declaration

    `void `modifyReturns`(Scope* `sc`, Type `tret`);`

    Modify all expression type of return statements to `tret`.

    #### Discussion

    On function literals, return type may be modified based on the context type after its semantic3 is done, in FuncExp::implicitCastTo.
    A function() dg = (){ return new B(); } // OK if is(B : A) == `true`
    If B to A conversion is convariant that requires offseet adjusting, all return statements should be adjusted to return expressions typed A.

- `CtorDeclaration`

  #### Declaration

  `class `CtorDeclaration`: dmd.func.FuncDeclaration;`

- `PostBlitDeclaration`

  #### Declaration

  `class `PostBlitDeclaration`: dmd.func.FuncDeclaration;`

- `DtorDeclaration`

  #### Declaration

  `class `DtorDeclaration`: dmd.func.FuncDeclaration;`

- `StaticCtorDeclaration`

  #### Declaration

  `class `StaticCtorDeclaration`: dmd.func.FuncDeclaration;`

- `SharedStaticCtorDeclaration`

  #### Declaration

  `class `SharedStaticCtorDeclaration`: dmd.func.StaticCtorDeclaration;`

- `StaticDtorDeclaration`

  #### Declaration

  `class `StaticDtorDeclaration`: dmd.func.FuncDeclaration;`

- `SharedStaticDtorDeclaration`

  #### Declaration

  `class `SharedStaticDtorDeclaration`: dmd.func.StaticDtorDeclaration;`

- `InvariantDeclaration`

  #### Declaration

  `class `InvariantDeclaration`: dmd.func.FuncDeclaration;`

- `UnitTestDeclaration`

  #### Declaration

  `class `UnitTestDeclaration`: dmd.func.FuncDeclaration;`

- `NewDeclaration`

  #### Declaration

  `class `NewDeclaration`: dmd.func.FuncDeclaration;`