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.funcsem

Does semantic analysis for functions.

Specification Functions

Authors:

Source funcsem.d

void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl);
Main semantic routine for functions.
bool functionSemantic(FuncDeclaration fd);
Resolve forward reference of function signature - parameter types, return type, and attributes.
Parameters:
FuncDeclaration fd function declaration
Returns:
false if any errors exist in the signature.
bool functionSemantic3(FuncDeclaration fd);
Resolve forward reference of function body. Returns false if any errors exist in the body.
void declareThis(FuncDeclaration fd, Scope* sc);
Creates and returns the hidden parameters for this function declaration.
Hidden parameters include the this parameter of a class, struct or nested function and the selector parameter for Objective-C methods.
bool checkForwardRef(FuncDeclaration fd, const ref Loc loc);
Check that this function type is properly resolved. If not, report "forward reference error" and return true.
int findVtblIndex(FuncDeclaration fd, Dsymbol[] vtbl);
Find index of function in vtbl[0..length] that this function overrides. Prefer an exact match to a covariant one.
Parameters:
FuncDeclaration fd function
Dsymbol[] vtbl vtable to use
Returns:
-1 didn't find one -2 can't determine because of forward references
BaseClass* overrideInterface(FuncDeclaration fd);
If function is a function in a base class, return that base class.
Parameters:
FuncDeclaration fd function
Returns:
base class if overriding, null if not
enum FuncResolveFlag: ubyte;
Flag used by resolveFuncCall.
standard
issue error messages, solve the call.
quiet
do not issue error message on no match, just return null.
overloadOnly
only resolve overloads, i.e. do not issue error on ambiguous
ufcs
matches and need explicit this.
trying to resolve UFCS call
FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, Objects* tiargs, Type tthis, ArgumentList argumentList, 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
ArgumentList argumentList arguments to function
FuncResolveFlag flags see FuncResolveFlag.
Returns:
if match is found, then function symbol, else null
Expression addInvariant(AggregateDeclaration ad, VarDeclaration vthis);
Generate Expression to call the invariant.

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

Returns:
void expression that calls the invariant
FuncDeclaration overloadExactMatch(FuncDeclaration thisfd, Type t);
Find function in overload list that exactly matches t.
int overrides(FuncDeclaration fd1, FuncDeclaration fd2);
Determine if fd1 overrides fd2. Return !=0 if it does.
MATCH leastAsSpecialized(FuncDeclaration f, FuncDeclaration g, Identifiers* names);
Determine partial specialization order of functions f vs g. This is very similar to TemplateDeclaration::leastAsSpecialized().
Parameters:
FuncDeclaration f first function
FuncDeclaration g second function
Identifiers* names names of parameters
Returns:
match 'this' is at least as specialized as g 0 g is more specialized than 'this'
FuncDeclaration overloadModMatch(FuncDeclaration thisfd, 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.
  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.
int getLevelAndCheck(FuncDeclaration fd, const ref Loc loc, Scope* sc, FuncDeclaration target, Declaration decl);
Determine lexical level difference from fd to nested function target. Issue error if fd cannot call target.
Parameters:
FuncDeclaration fd function
Loc loc location for error messages
Scope* sc context
FuncDeclaration target target of call
Declaration decl The Declaration that triggered this check. Used to provide a better error message only.
Returns:
0 same level

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

bool canInferAttributes(FuncDeclaration fd, Scope* sc);
Decide if attributes for this function can be inferred from examining the function body.
Returns:
true if can
bool checkNestedReference(FuncDeclaration fd, 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.
void buildResultVar(FuncDeclaration fd, Scope* sc, Type tret);
Declare result variable lazily.
Statement mergeFrequire(FuncDeclaration fd, 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.
Statement mergeFrequireInclusivePreview(FuncDeclaration fd, Statement sf, Expressions* params);
Merge into this function the 'in' contracts of all it overrides.
void buildEnsureRequire(FuncDeclaration thisfd);
Rewrite contracts as statements.
@safe 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
Returns:
true found an 'out' contract
Statement mergeFensure(FuncDeclaration fd, 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.
void modifyReturns(FuncLiteralDeclaration fld, Scope* sc, Type tret);
Modify all expression type of return statements to tret.
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.
bool isRootTraitsCompilesScope(Scope* sc);
When a traits(compiles) is used on a function literal call we need to take into account if the body of the function violates any attributes, however, we must not affect the attribute inference on the outer function. The attributes of the function literal still need to be inferred, therefore we need a way to check for the scope that the traits compiles introduces.
Parameters:
Scope* sc scope to be checked for
Returns:
true if the provided scope is the root of the traits compiles list of scopes.
bool setUnsafe(Scope* sc, bool gag = false, Loc loc = Loc.init, const(char)* fmt = null, RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null);
A statement / expression in this scope is not @safe, so mark the enclosing function as @system
Parameters:
Scope* sc scope that the unsafe statement / expression is in
bool gag surpress error message (used in escape.d)
Loc loc location of error
const(char)* fmt printf-style format string
RootObject arg0 (optional) argument for first %s format specifier
RootObject arg1 (optional) argument for second %s format specifier
RootObject arg2 (optional) argument for third %s format specifier
Returns:
whether there's a safe error
bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)* msg, RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null);
Like setUnsafe, but for safety errors still behind preview switches
Given a FeatureState fs, for example dip1000 / dip25 / systemVariables, the behavior changes based on the setting:
  • In case of -revert=fs, it does nothing.
  • In case of -preview=fs, it's the same as setUnsafe
  • By default, print a deprecation in @safe functions, or store an attribute violation in inferred functions.
Parameters:
Scope* sc used to find affected function/variable, and for checking whether we are in a deprecated / speculative scope
FeatureState fs feature state from the preview flag
bool gag surpress error message
Loc loc location of error
const(char)* msg printf-style format string
RootObject arg0 (optional) argument for first %s format specifier
RootObject arg1 (optional) argument for second %s format specifier
RootObject arg2 (optional) argument for third %s format specifier
Returns:
whether an actual safe error (not deprecation) occured
bool checkNRVO(FuncDeclaration fd);
Check all return statements for a function to verify that returning using NRVO is possible.
Returns:
false if the result cannot be returned by hidden reference.
bool setImpure(FuncDeclaration fd, Loc loc = Loc.init, const(char)* fmt = null, RootObject arg0 = null);
The function is doing something impure, so mark it as impure.
Parameters:
FuncDeclaration fd function declaration to mark
Loc loc location of impure action
const(char)* fmt format string for error message. Must include "%s %s" for the function kind and name.
RootObject arg0 (optional) argument to format string
Returns:
true if there's a purity error
bool traverseIndirections(Type ta, Type tb);
Performs type-based alias analysis between a newly created value and a pre- existing memory reference:
Assuming that a reference A to a value of type ta was available to the code that created a reference B to a value of type tb, it returns whether B might alias memory reachable from A based on the types involved (either directly or via any number of indirections in either A or B).
This relation is not symmetric in the two arguments. For example, a a const(int) reference can point to a pre-existing int, but not the other way round.
Examples:
ta, tb, result const(int), int, false int, const(int), true int, immutable(int), false const(immutable(int), immutable(int)), false // BUG: returns true
Parameters:
Type ta value type being referred to
Type tb referred to value type that could be constructed from ta
Returns:
true if reference to tb is isolated from reference to ta
bool isTypeIsolatedIndirect(FuncDeclaration fd, Type t);
Parameters:
FuncDeclaration fd function declaration to check
Type t type of object to test one level of indirection down
Returns:
true if an object typed t has no indirections which could have come from the function's parameters, mutable globals, or uplevel functions.
bool isReturnIsolated(FuncDeclaration fd);
See if pointers from function parameters, mutable globals, or uplevel functions could leak into return value.
Returns:
true if the function return value is isolated from any inputs to the function
bool isTypeIsolated(FuncDeclaration fd, Type t);

bool isTypeIsolated(FuncDeclaration fd, 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
Returns:
true if t is isolated from any inputs to the function