Does semantic analysis for functions.
bool
onlyOneMain(FuncDeclaration
fd);
Only one entry point function is allowed. Print error if more than one.
Parameters:FuncDeclarationfd | a "main" function |
Returns:true if haven't seen "main" before
bool
isUnique(const FuncDeclaration
fd);
Returns:true if there are no overloads of this function
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:FuncDeclarationfd | 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 thethis parameter of a class, struct or nested function and the selector parameter for Objective-C methods.
bool
checkForwardRef(FuncDeclaration
fd, 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:FuncDeclarationfd | 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:FuncDeclarationfd | function |
Returns:base class if overriding, null if not
enum
FuncResolveFlag: ubyte;
issue error messages, solve the call.
do not issue error message on no match, just returnnull.
only resolve overloads, i.e. do not issue error on ambiguous
matches and need explicit this.
trying to resolve UFCS call
FuncDeclaration
resolveFuncCall(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:Locloc | instantiation location |
Scope*sc | instantiation scope |
Dsymbols | instantiation symbol |
Objects*tiargs | initial list of template arguments |
Typetthis | if !NULL, thethis argument type |
ArgumentListargumentList | arguments to function |
FuncResolveFlagflags | seeFuncResolveFlag. |
Returns:if match is found, then function symbol, else null
Expression
addInvariant(AggregateDeclaration
ad, VarDeclaration
vthis);
Generate Expression to call the invariant.
Inputad 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, ArgumentLabels*
names);
Determine partial specialization order of functionsf vsg. This is very similar to TemplateDeclaration::leastAsSpecialized().
Parameters:FuncDeclarationf | first function |
FuncDeclarationg | second function |
ArgumentLabels*names | argument Labels of parameters(name and location of the name) |
Returns:match 'this' is at least as specialized as g 0 g is more specialized than 'this'
FuncDeclaration
overloadModMatch(FuncDeclaration
thisfd, Loc
loc, Type
tthis, ref bool
hasOverloads);
Find function in overload list that matches to the 'this' modifier. There's four result types.
- 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.
- 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.
- 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.
- 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, Loc
loc, Scope*
sc, FuncDeclaration
target, Declaration
decl);
Determine lexical level difference fromfd to nested functiontarget. Issue error iffd cannot calltarget.
Parameters:FuncDeclarationfd | function |
Locloc | location for error messages |
Scope*sc | context |
FuncDeclarationtarget | target of call |
Declarationdecl | TheDeclaration 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
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:FuncDeclarationfd | 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.
@safe 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.
int
getLevel(FuncDeclaration
fd1, FuncDeclaration
fd2, int
intypeof);
Determine lexical level difference fromfd1 to nested functionfd2.
Parameters:FuncDeclarationfd1 | function |
FuncDeclarationfd2 | target of call |
intintypeof | !=0 if inside typeof |
Returns:0 same level
0 decrease nesting by number -1 increase nesting by 1 (fd2 is nested withinfd1) LevelError error,this cannot callfd2
bool
checkEscapingSiblings(FuncDeclaration
f, FuncDeclaration
outerFunc, void*
p = null);
Given a nested function f inside a function outerFunc, check if any sibling callers of f have escaped. If so, mark all the enclosing functions as needing closures. This is recursive: we need to check the callers of our siblings. Note that nested functions can only call lexically earlier nested functions, so loops are impossible.
Parameters:FuncDeclarationf | inner function (nested within outerFunc) |
FuncDeclarationouterFunc | outer function |
void*p | for internal recursion use |
Returns:true if any closures were needed
bool
needsClosure(FuncDeclaration
fd);
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.
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, const(char)*
fmt, RootObject[]
args...);
The function is doing something impure, so mark it as impure.
Parameters:FuncDeclarationfd | function declaration to mark |
Locloc | location of impure action |
const(char)*fmt | format string for error message |
RootObject[]args | argument to format string |
Returns:true if there's a purity error
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 typet.
Parameters:Typet | type to check if it is isolated |
Returns:true ift is isolated from any inputs to the function
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:Dsymbolfstart | 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 |
Returns:==0 continue !=0 done (and the return value from the last dg() call)
bool
checkNestedReference(VarDeclaration
vd, Scope*
sc, Loc
loc);
Check to see if this variable is actually in an enclosing function rather than the current one. Update nestedrefs[], closureVars[] and outerVars[].
Returns:true if error occurs.
bool
arrayBoundsCheck(FuncDeclaration
fd);
Check to see if array bounds checking code has to be generated
Parameters:FuncDeclarationfd | function for which code is to be generated |
Returns:true if do array bounds checking for the given function