2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
4 * written by Walter Bright
5 * http://www.digitalmars.com
6 * Distributed under the Boost Software License, Version 1.0.
7 * http://www.boost.org/LICENSE_1_0.txt
8 * https://github.com/D-Programming-Language/dmd/blob/master/src/func.c
11 #include "root/dsystem.h"
15 #include "declaration.h"
17 #include "expression.h"
20 #include "aggregate.h"
21 #include "identifier.h"
24 #include "statement.h"
29 #include "root/rmem.h"
33 Expression
*addInvariant(Loc loc
, Scope
*sc
, AggregateDeclaration
*ad
, VarDeclaration
*vthis
, bool direct
);
34 bool checkReturnEscape(Scope
*sc
, Expression
*e
, bool gag
);
35 bool checkReturnEscapeRef(Scope
*sc
, Expression
*e
, bool gag
);
36 bool checkNestedRef(Dsymbol
*s
, Dsymbol
*p
);
37 Statement
*semantic(Statement
*s
, Scope
*sc
);
38 void semantic(Catch
*c
, Scope
*sc
);
39 Expression
*resolve(Loc loc
, Scope
*sc
, Dsymbol
*s
, bool hasOverloads
);
40 Expression
*semantic(Expression
*e
, Scope
*sc
);
41 int blockExit(Statement
*s
, FuncDeclaration
*func
, bool mustNotThrow
);
42 TypeIdentifier
*getThrowable();
44 RET
retStyle(TypeFunction
*tf
);
45 void MODtoBuffer(OutBuffer
*buf
, MOD mod
);
46 char *MODtoChars(MOD mod
);
47 bool MODimplicitConv(MOD modfrom
, MOD modto
);
48 MATCH
MODmethodConv(MOD modfrom
, MOD modto
);
49 void allocFieldinit(Scope
*sc
, size_t dim
);
50 void freeFieldinit(Scope
*sc
);
54 /* A visitor to walk entire statements and provides ability to replace any sub-statements.
56 class StatementRewriteWalker
: public Visitor
58 /* Point the currently visited statement.
59 * By using replaceCurrent() method, you can replace AST during walking.
63 void visitStmt(Statement
*&s
) { ps
= &s
; s
->accept(this); }
64 void replaceCurrent(Statement
*s
) { *ps
= s
; }
66 void visit(ErrorStatement
*) { }
67 void visit(PeelStatement
*s
)
72 void visit(ExpStatement
*) { }
73 void visit(DtorExpStatement
*) { }
74 void visit(CompileStatement
*) { }
75 void visit(CompoundStatement
*s
)
77 if (s
->statements
&& s
->statements
->dim
)
79 for (size_t i
= 0; i
< s
->statements
->dim
; i
++)
81 if ((*s
->statements
)[i
])
82 visitStmt((*s
->statements
)[i
]);
86 void visit(CompoundDeclarationStatement
*s
) { visit((CompoundStatement
*)s
); }
87 void visit(UnrolledLoopStatement
*s
)
89 if (s
->statements
&& s
->statements
->dim
)
91 for (size_t i
= 0; i
< s
->statements
->dim
; i
++)
93 if ((*s
->statements
)[i
])
94 visitStmt((*s
->statements
)[i
]);
98 void visit(ScopeStatement
*s
)
101 visitStmt(s
->statement
);
103 void visit(WhileStatement
*s
)
108 void visit(DoStatement
*s
)
113 void visit(ForStatement
*s
)
120 void visit(ForeachStatement
*s
)
125 void visit(ForeachRangeStatement
*s
)
130 void visit(IfStatement
*s
)
133 visitStmt(s
->ifbody
);
135 visitStmt(s
->elsebody
);
137 void visit(ConditionalStatement
*) { }
138 void visit(PragmaStatement
*) { }
139 void visit(StaticAssertStatement
*) { }
140 void visit(SwitchStatement
*s
)
145 void visit(CaseStatement
*s
)
148 visitStmt(s
->statement
);
150 void visit(CaseRangeStatement
*s
)
153 visitStmt(s
->statement
);
155 void visit(DefaultStatement
*s
)
158 visitStmt(s
->statement
);
160 void visit(GotoDefaultStatement
*) { }
161 void visit(GotoCaseStatement
*) { }
162 void visit(SwitchErrorStatement
*) { }
163 void visit(ReturnStatement
*) { }
164 void visit(BreakStatement
*) { }
165 void visit(ContinueStatement
*) { }
166 void visit(SynchronizedStatement
*s
)
171 void visit(WithStatement
*s
)
176 void visit(TryCatchStatement
*s
)
180 if (s
->catches
&& s
->catches
->dim
)
182 for (size_t i
= 0; i
< s
->catches
->dim
; i
++)
184 Catch
*c
= (*s
->catches
)[i
];
186 visitStmt(c
->handler
);
190 void visit(TryFinallyStatement
*s
)
195 visitStmt(s
->finalbody
);
197 void visit(OnScopeStatement
*) { }
198 void visit(ThrowStatement
*) { }
199 void visit(DebugStatement
*s
)
202 visitStmt(s
->statement
);
204 void visit(GotoStatement
*) { }
205 void visit(LabelStatement
*s
)
208 visitStmt(s
->statement
);
210 void visit(AsmStatement
*) { }
211 void visit(ImportStatement
*) { }
214 /* Tweak all return statements and dtor call for nrvo_var, for correct NRVO.
216 class NrvoWalker
: public StatementRewriteWalker
222 void visit(ReturnStatement
*s
)
224 // See if all returns are instead to be replaced with a goto returnLabel;
230 * vresult = exp; goto Lresult;
232 GotoStatement
*gs
= new GotoStatement(s
->loc
, Id::returnLabel
);
233 gs
->label
= fd
->returnLabel
;
237 s1
= new CompoundStatement(s
->loc
, new ExpStatement(s
->loc
, s
->exp
), gs
);
242 void visit(TryFinallyStatement
*s
)
244 DtorExpStatement
*des
;
246 s
->finalbody
&& (des
= s
->finalbody
->isDtorExpStatement()) != NULL
&&
247 fd
->nrvo_var
== des
->var
)
249 if (!(global
.params
.useExceptions
&& ClassDeclaration::throwable
))
251 /* Don't need to call destructor at all, since it is nrvo
253 replaceCurrent(s
->_body
);
254 s
->_body
->accept(this);
258 /* Normally local variable dtors are called regardless exceptions.
259 * But for nrvo_var, its dtor should be called only when exception is thrown.
262 * try { s->body; } finally { nrvo_var->edtor; }
263 * // equivalent with:
264 * // s->body; scope(exit) nrvo_var->edtor;
266 * try { s->body; } catch(Throwable __o) { nrvo_var->edtor; throw __o; }
267 * // equivalent with:
268 * // s->body; scope(failure) nrvo_var->edtor;
270 Statement
*sexception
= new DtorExpStatement(Loc(), fd
->nrvo_var
->edtor
, fd
->nrvo_var
);
271 Identifier
*id
= Identifier::generateId("__o");
273 Statement
*handler
= new PeelStatement(sexception
);
274 if (blockExit(sexception
, fd
, false) & BEfallthru
)
276 ThrowStatement
*ts
= new ThrowStatement(Loc(), new IdentifierExp(Loc(), id
));
277 ts
->internalThrow
= true;
278 handler
= new CompoundStatement(Loc(), handler
, ts
);
281 Catches
*catches
= new Catches();
282 Catch
*ctch
= new Catch(Loc(), getThrowable(), id
, handler
);
283 ctch
->internalCatch
= true;
284 ::semantic(ctch
, sc
); // Run semantic to resolve identifier '__o'
287 Statement
*s2
= new TryCatchStatement(Loc(), s
->_body
, catches
);
292 StatementRewriteWalker::visit(s
);
296 /********************************* FuncDeclaration ****************************/
298 FuncDeclaration::FuncDeclaration(Loc loc
, Loc endloc
, Identifier
*id
, StorageClass storage_class
, Type
*type
)
301 //printf("FuncDeclaration(id = '%s', type = %p)\n", id->toChars(), type);
302 //printf("storage_class = x%x\n", storage_class);
303 this->storage_class
= storage_class
;
307 // Normalize storage_class, because function-type related attributes
308 // are already set in the 'type' in parsing phase.
309 this->storage_class
&= ~(STC_TYPECTOR
| STC_FUNCATTR
);
312 this->endloc
= endloc
;
335 inlineStatusExp
= ILSuninitialized
;
336 inlineStatusStmt
= ILSuninitialized
;
337 inlining
= PINLINEdefault
;
341 semantic3Errors
= false;
343 interfaceVirtual
= NULL
;
346 /* The type given for "infer the return type" is a TypeFunction with
347 * NULL for the return type.
349 inferRetType
= (type
&& type
->nextOf() == NULL
);
355 builtin
= BUILTINunknown
;
357 requiresClosure
= false;
358 inlinedNestedCallees
= NULL
;
365 FuncDeclaration
*FuncDeclaration::create(Loc loc
, Loc endloc
, Identifier
*id
, StorageClass storage_class
, Type
*type
)
367 return new FuncDeclaration(loc
, endloc
, id
, storage_class
, type
);
370 Dsymbol
*FuncDeclaration::syntaxCopy(Dsymbol
*s
)
372 //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
374 s
? (FuncDeclaration
*)s
375 : new FuncDeclaration(loc
, endloc
, ident
, storage_class
, type
->syntaxCopy());
377 f
->frequire
= frequire
? frequire
->syntaxCopy() : NULL
;
378 f
->fensure
= fensure
? fensure
->syntaxCopy() : NULL
;
379 f
->fbody
= fbody
? fbody
->syntaxCopy() : NULL
;
380 assert(!fthrows
); // deprecated
384 /**********************************
385 * Decide if attributes for this function can be inferred from examining
390 static bool canInferAttributes(FuncDeclaration
*fd
, Scope
*sc
)
395 if (fd
->isVirtualMethod())
396 return false; // since they may be overridden
399 /********** this is for backwards compatibility for the moment ********/
400 (!fd
->isMember() || (sc
->func
->isSafeBypassingInference() && !fd
->isInstantiated())))
403 if (fd
->isFuncLiteralDeclaration() || // externs are not possible with literals
404 (fd
->storage_class
& STCinference
) || // do attribute inference
405 (fd
->inferRetType
&& !fd
->isCtorDeclaration()))
408 if (fd
->isInstantiated())
410 TemplateInstance
*ti
= fd
->parent
->isTemplateInstance();
411 if (ti
== NULL
|| ti
->isTemplateMixin() || ti
->tempdecl
->ident
== fd
->ident
)
418 /*****************************************
419 * Initialize for inferring the attributes of this function.
421 static void initInferAttributes(FuncDeclaration
*fd
)
423 //printf("initInferAttributes() for %s\n", toPrettyChars());
424 TypeFunction
*tf
= fd
->type
->toTypeFunction();
425 if (tf
->purity
== PUREimpure
) // purity not specified
426 fd
->flags
|= FUNCFLAGpurityInprocess
;
428 if (tf
->trust
== TRUSTdefault
)
429 fd
->flags
|= FUNCFLAGsafetyInprocess
;
432 fd
->flags
|= FUNCFLAGnothrowInprocess
;
435 fd
->flags
|= FUNCFLAGnogcInprocess
;
437 if (!fd
->isVirtual() || fd
->introducing
)
438 fd
->flags
|= FUNCFLAGreturnInprocess
;
440 // Initialize for inferring STCscope
441 if (global
.params
.vsafe
)
442 fd
->flags
|= FUNCFLAGinferScope
;
445 // Do the semantic analysis on the external interface to the function.
447 void FuncDeclaration::semantic(Scope
*sc
)
450 AggregateDeclaration
*ad
;
451 InterfaceDeclaration
*id
;
453 if (semanticRun
!= PASSinit
&& isFuncLiteralDeclaration())
455 /* Member functions that have return types that are
456 * forward references can have semantic() run more than
458 * See test\interface2.d, test20
463 if (semanticRun
>= PASSsemanticdone
)
465 assert(semanticRun
<= PASSsemantic
);
466 semanticRun
= PASSsemantic
;
478 Dsymbol
*parent
= toParent();
480 foverrides
.setDim(0); // reset in case semantic() is being retried for this function
482 storage_class
|= sc
->stc
& ~STCref
;
484 // Don't nest structs b/c of generated methods which should not access the outer scopes.
485 // https://issues.dlang.org/show_bug.cgi?id=16627
486 if (ad
&& !generated
)
488 storage_class
|= ad
->storage_class
& (STC_TYPECTOR
| STCsynchronized
);
492 storage_class
|= sc
->func
->storage_class
& STCdisable
;
493 // Remove prefix storage classes silently.
494 if ((storage_class
& STC_TYPECTOR
) && !(ad
|| isNested()))
495 storage_class
&= ~STC_TYPECTOR
;
497 //printf("function storage_class = x%llx, sc->stc = x%llx, %x\n", storage_class, sc->stc, Declaration::isFinal());
499 FuncLiteralDeclaration
*fld
= isFuncLiteralDeclaration();
500 if (fld
&& fld
->treq
)
502 Type
*treq
= fld
->treq
;
503 assert(treq
->nextOf()->ty
== Tfunction
);
504 if (treq
->ty
== Tdelegate
)
505 fld
->tok
= TOKdelegate
;
506 else if (treq
->ty
== Tpointer
&& treq
->nextOf()->ty
== Tfunction
)
507 fld
->tok
= TOKfunction
;
510 linkage
= treq
->nextOf()->toTypeFunction()->linkage
;
513 linkage
= sc
->linkage
;
514 inlining
= sc
->inlining
;
515 protection
= sc
->protection
;
516 userAttribDecl
= sc
->userAttribDecl
;
519 originalType
= type
->syntaxCopy();
520 if (type
->ty
!= Tfunction
)
522 if (type
->ty
!= Terror
)
524 error("%s must be a function instead of %s", toChars(), type
->toChars());
533 sc
->stc
|= storage_class
& (STCdisable
| STCdeprecated
); // forward to function type
534 TypeFunction
*tf
= type
->toTypeFunction();
538 /* If the nesting parent is pure without inference,
539 * then this function defaults to pure too.
542 * auto bar() {} // become a weak purity funciton
543 * class C { // nested class
544 * auto baz() {} // become a weak purity funciton
547 * static auto boo() {} // typed as impure
548 * // Even though, boo cannot call any impure functions.
549 * // See also Expression::checkPurity().
552 if (tf
->purity
== PUREimpure
&& (isNested() || isThis()))
554 FuncDeclaration
*fd
= NULL
;
555 for (Dsymbol
*p
= toParent2(); p
; p
= p
->toParent2())
557 if (AggregateDeclaration
*adx
= p
->isAggregateDeclaration())
563 if ((fd
= p
->isFuncDeclaration()) != NULL
)
567 /* If the parent's purity is inferred, then this function's purity needs
568 * to be inferred first.
570 if (fd
&& fd
->isPureBypassingInference() >= PUREweak
&&
573 tf
->purity
= PUREfwdref
; // default to pure
578 if (tf
->isref
) sc
->stc
|= STCref
;
579 if (tf
->isscope
) sc
->stc
|= STCscope
;
580 if (tf
->isnothrow
) sc
->stc
|= STCnothrow
;
581 if (tf
->isnogc
) sc
->stc
|= STCnogc
;
582 if (tf
->isproperty
) sc
->stc
|= STCproperty
;
583 if (tf
->purity
== PUREfwdref
) sc
->stc
|= STCpure
;
584 if (tf
->trust
!= TRUSTdefault
)
585 sc
->stc
&= ~(STCsafe
| STCsystem
| STCtrusted
);
586 if (tf
->trust
== TRUSTsafe
) sc
->stc
|= STCsafe
;
587 if (tf
->trust
== TRUSTsystem
) sc
->stc
|= STCsystem
;
588 if (tf
->trust
== TRUSTtrusted
) sc
->stc
|= STCtrusted
;
590 if (isCtorDeclaration())
592 sc
->flags
|= SCOPEctor
;
594 Type
*tret
= ad
->handleType();
596 tret
= tret
->addStorageClass(storage_class
| sc
->stc
);
597 tret
= tret
->addMod(type
->mod
);
600 if (ad
->isStructDeclaration())
604 // 'return' on a non-static class member function implies 'scope' as well
605 if (ad
&& ad
->isClassDeclaration() && (tf
->isreturn
|| sc
->stc
& STCreturn
) && !(sc
->stc
& STCstatic
))
608 // If 'this' has no pointers, remove 'scope' as it has no meaning
609 if (sc
->stc
& STCscope
&& ad
&& ad
->isStructDeclaration() && !ad
->type
->hasPointers())
611 sc
->stc
&= ~STCscope
;
615 sc
->linkage
= linkage
;
617 if (!tf
->isNaked() && !(isThis() || isNested()))
620 MODtoBuffer(&buf
, tf
->mod
);
621 error("without 'this' cannot be %s", buf
.peekString());
622 tf
->mod
= 0; // remove qualifiers
625 /* Apply const, immutable, wild and shared storage class
626 * to the function type. Do this before type semantic.
628 StorageClass stc
= storage_class
;
629 if (type
->isImmutable())
633 if (type
->isShared() || storage_class
& STCsynchronized
)
637 switch (stc
& STC_TYPECTOR
)
640 case STCimmutable
| STCconst
:
641 case STCimmutable
| STCwild
:
642 case STCimmutable
| STCwild
| STCconst
:
643 case STCimmutable
| STCshared
:
644 case STCimmutable
| STCshared
| STCconst
:
645 case STCimmutable
| STCshared
| STCwild
:
646 case STCimmutable
| STCshared
| STCwild
| STCconst
:
647 // Don't use immutableOf(), as that will do a merge()
648 type
= type
->makeImmutable();
652 type
= type
->makeConst();
656 type
= type
->makeWild();
659 case STCwild
| STCconst
:
660 type
= type
->makeWildConst();
664 type
= type
->makeShared();
667 case STCshared
| STCconst
:
668 type
= type
->makeSharedConst();
671 case STCshared
| STCwild
:
672 type
= type
->makeSharedWild();
675 case STCshared
| STCwild
| STCconst
:
676 type
= type
->makeSharedWildConst();
686 type
= type
->semantic(loc
, sc
);
689 if (type
->ty
!= Tfunction
)
691 if (type
->ty
!= Terror
)
693 error("%s must be a function instead of %s", toChars(), type
->toChars());
701 // Merge back function attributes into 'originalType'.
702 // It's used for mangling, ddoc, and json output.
703 TypeFunction
*tfo
= originalType
->toTypeFunction();
704 TypeFunction
*tfx
= type
->toTypeFunction();
706 tfo
->isscope
= tfx
->isscope
;
707 tfo
->isscopeinferred
= tfx
->isscopeinferred
;
708 tfo
->isref
= tfx
->isref
;
709 tfo
->isnothrow
= tfx
->isnothrow
;
710 tfo
->isnogc
= tfx
->isnogc
;
711 tfo
->isproperty
= tfx
->isproperty
;
712 tfo
->purity
= tfx
->purity
;
713 tfo
->trust
= tfx
->trust
;
715 storage_class
&= ~(STC_TYPECTOR
| STC_FUNCATTR
);
718 f
= (TypeFunction
*)type
;
720 if ((storage_class
& STCauto
) && !f
->isref
&& !inferRetType
)
721 error("storage class 'auto' has no effect if return type is not inferred");
722 /* Functions can only be 'scope' if they have a 'this'
724 if (f
->isscope
&& !isNested() && !ad
)
726 error("functions cannot be scope");
729 if (f
->isreturn
&& !needThis() && !isNested())
731 /* Non-static nested functions have a hidden 'this' pointer to which
732 * the 'return' applies
734 error("static member has no 'this' to which 'return' can apply");
737 if (isAbstract() && !isVirtual())
742 else if (protection
.kind
== PROTprivate
|| protection
.kind
== PROTpackage
)
743 sfunc
= protectionToChars(protection
.kind
);
745 sfunc
= "non-virtual";
746 error("%s functions cannot be abstract", sfunc
);
749 if (isOverride() && !isVirtual())
751 PROTKIND kind
= prot().kind
;
752 if ((kind
== PROTprivate
|| kind
== PROTpackage
) && isMember())
753 error("%s method is not virtual and cannot override", protectionToChars(kind
));
755 error("cannot override a non-virtual function");
758 if (isAbstract() && isFinalFunc())
759 error("cannot be both final and abstract");
761 id
= parent
->isInterfaceDeclaration();
764 storage_class
|= STCabstract
;
766 if (isCtorDeclaration() ||
767 isPostBlitDeclaration() ||
768 isDtorDeclaration() ||
769 isInvariantDeclaration() ||
770 isNewDeclaration() || isDelete())
771 error("constructors, destructors, postblits, invariants, new and delete functions are not allowed in interface %s", id
->toChars());
772 if (fbody
&& isVirtual())
773 error("function body only allowed in final functions in interface %s", id
->toChars());
776 if (UnionDeclaration
*ud
= parent
->isUnionDeclaration())
778 if (isPostBlitDeclaration() ||
779 isDtorDeclaration() ||
780 isInvariantDeclaration())
781 error("destructors, postblits and invariants are not allowed in union %s", ud
->toChars());
784 /* Contracts can only appear without a body when they are virtual interface functions
786 if (!fbody
&& (fensure
|| frequire
) && !(id
&& isVirtual()))
787 error("in and out contracts require function body");
789 if (parent
->isStructDeclaration())
791 if (isCtorDeclaration())
797 if (ClassDeclaration
*cd
= parent
->isClassDeclaration())
799 if (isCtorDeclaration())
804 if (storage_class
& STCabstract
)
805 cd
->isabstract
= ABSyes
;
807 // if static function, do not put in vtbl[]
810 //printf("\tnot virtual\n");
813 // Suppress further errors if the return type is an error
814 if (type
->nextOf() == Type::terror
)
817 bool may_override
= false;
818 for (size_t i
= 0; i
< cd
->baseclasses
->dim
; i
++)
820 BaseClass
*b
= (*cd
->baseclasses
)[i
];
821 ClassDeclaration
*cbd
= b
->type
->toBasetype()->isClassHandle();
824 for (size_t j
= 0; j
< cbd
->vtbl
.dim
; j
++)
826 FuncDeclaration
*f2
= cbd
->vtbl
[j
]->isFuncDeclaration();
827 if (!f2
|| f2
->ident
!= ident
)
829 if (cbd
->parent
&& cbd
->parent
->isTemplateInstance())
831 if (!f2
->functionSemantic())
837 if (may_override
&& type
->nextOf() == NULL
)
839 /* If same name function exists in base class but 'this' is auto return,
840 * cannot find index of base class's vtbl[] to override.
842 error("return type inference is not supported if may override base class function");
845 /* Find index of existing function in base class's vtbl[] to override
846 * (the index will be the same as in cd's current vtbl[])
848 int vi
= cd
->baseClass
? findVtblIndex((Dsymbols
*)&cd
->baseClass
->vtbl
, (int)cd
->baseClass
->vtbl
.dim
)
851 bool doesoverride
= false;
856 /* Didn't find one, so
857 * This is an 'introducing' function which gets a new
858 * slot in the vtbl[].
861 // Verify this doesn't override previous final function
864 Dsymbol
*s
= cd
->baseClass
->search(loc
, ident
);
867 FuncDeclaration
*f2
= s
->isFuncDeclaration();
870 f2
= f2
->overloadExactMatch(type
);
871 if (f2
&& f2
->isFinalFunc() && f2
->prot().kind
!= PROTprivate
)
872 error("cannot override final function %s", f2
->toPrettyChars());
877 /* These quirky conditions mimic what VC++ appears to do
879 if (global
.params
.mscoff
&& cd
->isCPPclass() &&
880 cd
->baseClass
&& cd
->baseClass
->vtbl
.dim
)
882 /* if overriding an interface function, then this is not
883 * introducing and don't put it in the class vtbl[]
885 interfaceVirtual
= overrideInterface();
886 if (interfaceVirtual
)
888 //printf("\tinterface function %s\n", toChars());
889 cd
->vtblFinal
.push(this);
896 // Don't check here, as it may override an interface function
898 //error("is marked as override, but does not override any function");
899 cd
->vtblFinal
.push(this);
903 //printf("\tintroducing function %s\n", toChars());
905 if (cd
->isCPPclass() && Target::reverseCppOverloads
)
907 // with dmc, overloaded functions are grouped and in reverse order
908 vtblIndex
= (int)cd
->vtbl
.dim
;
909 for (int i
= 0; i
< (int)cd
->vtbl
.dim
; i
++)
911 if (cd
->vtbl
[i
]->ident
== ident
&& cd
->vtbl
[i
]->parent
== parent
)
917 // shift all existing functions back
918 for (int i
= (int)cd
->vtbl
.dim
; i
> vtblIndex
; i
--)
920 FuncDeclaration
*fd
= cd
->vtbl
[i
-1]->isFuncDeclaration();
924 cd
->vtbl
.insert(vtblIndex
, this);
928 // Append to end of vtbl[]
929 vi
= (int)cd
->vtbl
.dim
;
937 // can't determine because of forward references
943 FuncDeclaration
*fdv
= cd
->baseClass
->vtbl
[vi
]->isFuncDeclaration();
944 FuncDeclaration
*fdc
= cd
->vtbl
[vi
]->isFuncDeclaration();
945 // This function is covariant with fdv
953 if (fdc
->toParent() == parent
)
955 //printf("vi = %d,\tthis = %p %s %s @ [%s]\n\tfdc = %p %s %s @ [%s]\n\tfdv = %p %s %s @ [%s]\n",
956 // vi, this, this->toChars(), this->type->toChars(), this->loc.toChars(),
957 // fdc, fdc ->toChars(), fdc ->type->toChars(), fdc ->loc.toChars(),
958 // fdv, fdv ->toChars(), fdv ->type->toChars(), fdv ->loc.toChars());
960 // fdc overrides fdv exactly, then this introduces new function.
961 if (fdc
->type
->mod
== fdv
->type
->mod
&& this->type
->mod
!= fdv
->type
->mod
)
965 // This function overrides fdv
966 if (fdv
->isFinalFunc())
967 error("cannot override final function %s", fdv
->toPrettyChars());
973 ::deprecation(loc
, "@future base class method %s is being overridden by %s; rename the latter",
974 fdv
->toPrettyChars(), toPrettyChars());
975 // Treat 'this' as an introducing function, giving it a separate hierarchy in the vtbl[]
980 int vi2
= findVtblIndex(&cd
->baseClass
->vtbl
, (int)cd
->baseClass
->vtbl
.dim
, false);
982 // https://issues.dlang.org/show_bug.cgi?id=17349
983 ::deprecation(loc
, "cannot implicitly override base class method `%s` with `%s`; add `override` attribute",
984 fdv
->toPrettyChars(), toPrettyChars());
986 ::error(loc
, "implicitly overriding base class method %s with %s deprecated; add 'override' attribute",
987 fdv
->toPrettyChars(), toPrettyChars());
992 if (fdc
->toParent() == parent
)
994 // If both are mixins, or both are not, then error.
995 // If either is not, the one that is not overrides the other.
996 bool thismixin
= this->parent
->isClassDeclaration() != NULL
;
997 bool fdcmixin
= fdc
->parent
->isClassDeclaration() != NULL
;
998 if (thismixin
== fdcmixin
)
1000 error("multiple overrides of same function");
1002 else if (!thismixin
) // fdc overrides fdv
1004 // this doesn't override any function
1008 cd
->vtbl
[vi
] = this;
1011 /* Remember which functions this overrides
1013 foverrides
.push(fdv
);
1015 /* This works by whenever this function is called,
1016 * it actually returns tintro, which gets dynamically
1017 * cast to type. But we know that tintro is a base
1018 * of type, so we could optimize it by not doing a
1019 * dynamic cast, but just subtracting the isBaseOf()
1020 * offset if the value is != null.
1024 tintro
= fdv
->tintro
;
1025 else if (!type
->equals(fdv
->type
))
1027 /* Only need to have a tintro if the vptr
1031 if (fdv
->type
->nextOf()->isBaseOf(type
->nextOf(), &offset
))
1040 /* Go through all the interface bases.
1041 * If this function is covariant with any members of those interface
1042 * functions, set the tintro.
1045 for (size_t i
= 0; i
< cd
->interfaces
.length
; i
++)
1047 BaseClass
*b
= cd
->interfaces
.ptr
[i
];
1048 vi
= findVtblIndex((Dsymbols
*)&b
->sym
->vtbl
, (int)b
->sym
->vtbl
.dim
);
1055 // can't determine because of forward references
1061 FuncDeclaration
*fdv
= (FuncDeclaration
*)b
->sym
->vtbl
[vi
];
1064 /* Remember which functions this overrides
1066 foverrides
.push(fdv
);
1068 /* Should we really require 'override' when implementing
1069 * an interface function?
1071 //if (!isOverride())
1072 //warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
1076 else if (!type
->equals(fdv
->type
))
1078 /* Only need to have a tintro if the vptr
1082 if (fdv
->type
->nextOf()->isBaseOf(type
->nextOf(), &offset
))
1091 if (!tintro
->nextOf()->equals(ti
->nextOf()) &&
1092 !tintro
->nextOf()->isBaseOf(ti
->nextOf(), NULL
) &&
1093 !ti
->nextOf()->isBaseOf(tintro
->nextOf(), NULL
))
1095 error("incompatible covariant types %s and %s", tintro
->toChars(), ti
->toChars());
1105 if (!doesoverride
&& isOverride() && (type
->nextOf() || !may_override
))
1107 BaseClass
*bc
= NULL
;
1109 for (size_t i
= 0; i
< cd
->baseclasses
->dim
; i
++)
1111 bc
= (*cd
->baseclasses
)[i
];
1112 s
= bc
->sym
->search_correct(ident
);
1117 error("does not override any function, did you mean to override '%s%s'?",
1118 bc
->sym
->isCPPclass() ? "extern (C++) " : "", s
->toPrettyChars());
1120 error("does not override any function");
1125 /* Go through all the interface bases.
1126 * Disallow overriding any final functions in the interface(s).
1128 for (size_t i
= 0; i
< cd
->interfaces
.length
; i
++)
1130 BaseClass
*b
= cd
->interfaces
.ptr
[i
];
1133 Dsymbol
*s
= search_function(b
->sym
, ident
);
1136 FuncDeclaration
*f2
= s
->isFuncDeclaration();
1139 f2
= f2
->overloadExactMatch(type
);
1140 if (f2
&& f2
->isFinalFunc() && f2
->prot().kind
!= PROTprivate
)
1141 error("cannot override final function %s.%s", b
->sym
->toChars(), f2
->toPrettyChars());
1149 if (storage_class
& STCdisable
)
1150 deprecation("overridden functions cannot be annotated @disable");
1152 deprecation("deprecated functions cannot be annotated @disable");
1155 else if (isOverride() && !parent
->isTemplateInstance())
1156 error("override only applies to class member functions");
1158 // Reflect this->type to f because it could be changed by findVtblIndex
1159 f
= type
->toTypeFunction();
1161 /* Do not allow template instances to add virtual functions
1166 TemplateInstance
*ti
= parent
->isTemplateInstance();
1169 // Take care of nested templates
1172 TemplateInstance
*ti2
= ti
->tempdecl
->parent
->isTemplateInstance();
1178 // If it's a member template
1179 ClassDeclaration
*cd
= ti
->tempdecl
->isClassMember();
1182 error("cannot use template to add virtual function to class '%s'", cd
->toChars());
1188 checkDmain(); // Check main() parameters and return type
1191 /* Purity and safety can be inferred for some functions by examining
1192 * the function body.
1194 if (canInferAttributes(this, sc
))
1195 initInferAttributes(this);
1197 Module::dprogress
++;
1198 semanticRun
= PASSsemanticdone
;
1200 /* Save scope for possible later use (if we need the
1201 * function internals)
1203 _scope
= sc
->copy();
1204 _scope
->setNoFree();
1206 static bool printedMain
= false; // semantic might run more than once
1207 if (global
.params
.verbose
&& !printedMain
)
1209 const char *type
= isMain() ? "main" : isWinMain() ? "winmain" : isDllMain() ? "dllmain" : (const char *)NULL
;
1210 Module
*mod
= sc
->_module
;
1215 const char *name
= FileName::searchPath(global
.path
, mod
->srcfile
->toChars(), true);
1216 message("entry %-10s\t%s", type
, name
);
1220 if (fbody
&& isMain() && sc
->_module
->isRoot())
1221 Compiler::genCmain(sc
);
1223 assert(type
->ty
!= Terror
|| errors
);
1226 void FuncDeclaration::semantic2(Scope
*sc
)
1228 if (semanticRun
>= PASSsemantic2done
)
1230 assert(semanticRun
<= PASSsemantic2
);
1231 semanticRun
= PASSsemantic2
;
1233 objc()->setSelector(this, sc
);
1234 objc()->validateSelector(this);
1236 if (parent
->isClassDeclaration())
1238 objc()->checkLinkage(this);
1242 /****************************************************
1243 * Determine whether an 'out' contract is declared inside
1244 * the given function or any of its overrides.
1246 * fd = the function to search
1248 * true found an 'out' contract
1249 * false didn't find one
1251 static bool needsFensure(FuncDeclaration
*fd
)
1256 for (size_t i
= 0; i
< fd
->foverrides
.dim
; i
++)
1258 FuncDeclaration
*fdv
= fd
->foverrides
[i
];
1263 if (needsFensure(fdv
))
1269 /****************************************************
1270 * Rewrite contracts as nested functions, then call them. Doing it as nested
1271 * functions means that overriding functions can call them.
1273 * fd = the function to rewrite contracts for
1275 static void buildEnsureRequire(FuncDeclaration
*fdx
)
1277 if (!fdx
->isVirtual())
1280 TypeFunction
*f
= (TypeFunction
*)fdx
->type
;
1286 * void __require() { ... }
1289 Loc loc
= fdx
->frequire
->loc
;
1290 TypeFunction
*tf
= new TypeFunction(NULL
, Type::tvoid
, 0, LINKd
);
1291 tf
->isnothrow
= f
->isnothrow
;
1292 tf
->isnogc
= f
->isnogc
;
1293 tf
->purity
= f
->purity
;
1294 tf
->trust
= f
->trust
;
1295 FuncDeclaration
*fd
= new FuncDeclaration(loc
, loc
,
1296 Id::require
, STCundefined
, tf
);
1297 fd
->fbody
= fdx
->frequire
;
1298 Statement
*s1
= new ExpStatement(loc
, fd
);
1299 Expression
*e
= new CallExp(loc
, new VarExp(loc
, fd
, false), (Expressions
*)NULL
);
1300 Statement
*s2
= new ExpStatement(loc
, e
);
1301 fdx
->frequire
= new CompoundStatement(loc
, s1
, s2
);
1302 fdx
->fdrequire
= fd
;
1305 if (!fdx
->outId
&& f
->nextOf() && f
->nextOf()->toBasetype()->ty
!= Tvoid
)
1306 fdx
->outId
= Id::result
; // provide a default
1310 /* out (result) { ... }
1312 * void __ensure(ref tret result) { ... }
1315 Loc loc
= fdx
->fensure
->loc
;
1316 Parameters
*fparams
= new Parameters();
1317 Parameter
*p
= NULL
;
1320 p
= new Parameter(STCref
| STCconst
, f
->nextOf(), fdx
->outId
, NULL
);
1323 TypeFunction
*tf
= new TypeFunction(fparams
, Type::tvoid
, 0, LINKd
);
1324 tf
->isnothrow
= f
->isnothrow
;
1325 tf
->isnogc
= f
->isnogc
;
1326 tf
->purity
= f
->purity
;
1327 tf
->trust
= f
->trust
;
1328 FuncDeclaration
*fd
= new FuncDeclaration(loc
, loc
,
1329 Id::ensure
, STCundefined
, tf
);
1330 fd
->fbody
= fdx
->fensure
;
1331 Statement
*s1
= new ExpStatement(loc
, fd
);
1332 Expression
*eresult
= NULL
;
1334 eresult
= new IdentifierExp(loc
, fdx
->outId
);
1335 Expression
*e
= new CallExp(loc
, new VarExp(loc
, fd
, false), eresult
);
1336 Statement
*s2
= new ExpStatement(loc
, e
);
1337 fdx
->fensure
= new CompoundStatement(loc
, s1
, s2
);
1342 /* Determine if function should add `return 0;`
1344 static bool addReturn0(FuncDeclaration
*funcdecl
)
1346 TypeFunction
*f
= (TypeFunction
*)funcdecl
->type
;
1348 return f
->next
->ty
== Tvoid
&&
1349 (funcdecl
->isMain() || (global
.params
.betterC
&& funcdecl
->isCMain()));
1352 // Do the semantic analysis on the internals of the function.
1354 void FuncDeclaration::semantic3(Scope
*sc
)
1356 VarDeclaration
*_arguments
= NULL
;
1362 //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
1365 if (errors
|| isError(parent
))
1370 //printf("FuncDeclaration::semantic3('%s.%s', %p, sc = %p, loc = %s)\n", parent->toChars(), toChars(), this, sc, loc.toChars());
1372 //printf("storage class = x%x %x\n", sc->stc, storage_class);
1373 //{ static int x; if (++x == 2) *(char*)0=0; }
1374 //printf("\tlinkage = %d\n", sc->linkage);
1376 if (ident
== Id::assign
&& !inuse
)
1378 if (storage_class
& STCinference
)
1380 /* Bugzilla 15044: For generated opAssign function, any errors
1381 * from its body need to be gagged.
1383 unsigned oldErrors
= global
.startGagging();
1387 if (global
.endGagging(oldErrors
)) // if errors happened
1389 // Disable generated opAssign, because some members forbid identity assignment.
1390 storage_class
|= STCdisable
;
1391 fbody
= NULL
; // remove fbody which contains the error
1392 semantic3Errors
= false;
1398 //printf(" sc->incontract = %d\n", (sc->flags & SCOPEcontract));
1399 if (semanticRun
>= PASSsemantic3
)
1401 semanticRun
= PASSsemantic3
;
1402 semantic3Errors
= false;
1404 if (!type
|| type
->ty
!= Tfunction
)
1406 TypeFunction
*f
= (TypeFunction
*)type
;
1407 if (!inferRetType
&& f
->next
->ty
== Terror
)
1410 if (!fbody
&& inferRetType
&& !f
->next
)
1412 error("has no function body with return type inference");
1416 unsigned oldErrors
= global
.errors
;
1420 for (size_t i
= 0; i
< foverrides
.dim
; i
++)
1422 FuncDeclaration
*fdv
= foverrides
[i
];
1424 if (fdv
->fbody
&& !fdv
->frequire
)
1426 error("cannot have an in contract when overriden function %s does not have an in contract", fdv
->toPrettyChars());
1432 // Remember whether we need to generate an 'out' contract.
1433 bool needEnsure
= needsFensure(this);
1435 if (fbody
|| frequire
|| needEnsure
)
1437 /* Symbol table into which we place parameters and nested functions,
1438 * solely to diagnose name collisions.
1440 localsymtab
= new DsymbolTable();
1442 // Establish function scope
1443 ScopeDsymbol
*ss
= new ScopeDsymbol();
1444 // find enclosing scope symbol, might skip symbol-less CTFE and/or FuncExp scopes
1445 for (Scope
*scx
= sc
; ; scx
= scx
->enclosing
)
1449 ss
->parent
= scx
->scopesym
;
1454 ss
->endlinnum
= endloc
.linnum
;
1455 Scope
*sc2
= sc
->push(ss
);
1460 sc2
->scontinue
= NULL
;
1463 sc2
->linkage
= LINKd
;
1464 sc2
->stc
&= ~(STCauto
| STCscope
| STCstatic
| STCextern
| STCabstract
|
1465 STCdeprecated
| STCoverride
|
1466 STC_TYPECTOR
| STCfinal
| STCtls
| STCgshared
| STCref
| STCreturn
|
1467 STCproperty
| STCnothrow
| STCpure
| STCsafe
| STCtrusted
| STCsystem
);
1468 sc2
->protection
= Prot(PROTpublic
);
1469 sc2
->explicitProtection
= 0;
1470 sc2
->aligndecl
= NULL
;
1471 if (this->ident
!= Id::require
&& this->ident
!= Id::ensure
)
1472 sc2
->flags
= sc
->flags
& ~SCOPEcontract
;
1473 sc2
->flags
&= ~SCOPEcompile
;
1477 sc2
->userAttribDecl
= NULL
;
1478 if (sc2
->intypeof
== 1) sc2
->intypeof
= 2;
1479 sc2
->fieldinit
= NULL
;
1480 sc2
->fieldinit_dim
= 0;
1482 /* Note: When a lambda is defined immediately under aggregate member
1483 * scope, it should be contextless due to prevent interior pointers.
1485 * // dg points 'this' - it's interior pointer
1486 * class C { int x; void delegate() dg = (){ this.x = 1; }; }
1488 * However, lambdas could be used inside typeof, in order to check
1489 * some expressions varidity at compile time. For such case the lambda
1490 * body can access aggregate instance members.
1492 * class C { int x; static assert(is(typeof({ this.x = 1; }))); }
1494 * To properly accept it, mark these lambdas as member functions.
1496 if (FuncLiteralDeclaration
*fld
= isFuncLiteralDeclaration())
1498 if (AggregateDeclaration
*ad
= isMember2())
1502 if (fld
->tok
== TOKdelegate
)
1503 error("cannot be %s members", ad
->kind());
1505 fld
->tok
= TOKfunction
;
1509 if (fld
->tok
!= TOKfunction
)
1510 fld
->tok
= TOKdelegate
;
1516 AggregateDeclaration
*ad
= isThis();
1517 vthis
= declareThis(sc2
, ad
);
1518 //printf("[%s] ad = %p vthis = %p\n", loc.toChars(), ad, vthis);
1519 //if (vthis) printf("\tvthis->type = %s\n", vthis->type->toChars());
1521 // Declare hidden variable _arguments[] and _argptr
1522 if (f
->varargs
== 1)
1524 if (f
->linkage
== LINKd
)
1526 // Variadic arguments depend on Typeinfo being defined
1527 if (!global
.params
.useTypeInfo
|| !Type::dtypeinfo
|| !Type::typeinfotypelist
)
1529 if (!global
.params
.useTypeInfo
)
1530 error("D-style variadic functions cannot be used with -betterC");
1531 else if (!Type::typeinfotypelist
)
1532 error("`object.TypeInfo_Tuple` could not be found, but is implicitly used in D-style variadic functions");
1534 error("`object.TypeInfo` could not be found, but is implicitly used in D-style variadic functions");
1538 // Declare _arguments[]
1539 v_arguments
= new VarDeclaration(Loc(), Type::typeinfotypelist
->type
, Id::_arguments_typeinfo
, NULL
);
1540 v_arguments
->storage_class
|= STCtemp
| STCparameter
;
1541 v_arguments
->semantic(sc2
);
1542 sc2
->insert(v_arguments
);
1543 v_arguments
->parent
= this;
1545 //Type *t = Type::typeinfo->type->constOf()->arrayOf();
1546 Type
*t
= Type::dtypeinfo
->type
->arrayOf();
1547 _arguments
= new VarDeclaration(Loc(), t
, Id::_arguments
, NULL
);
1548 _arguments
->storage_class
|= STCtemp
;
1549 _arguments
->semantic(sc2
);
1550 sc2
->insert(_arguments
);
1551 _arguments
->parent
= this;
1553 if (f
->linkage
== LINKd
|| (f
->parameters
&& Parameter::dim(f
->parameters
)))
1556 Type
*t
= Type::tvalist
;
1557 v_argptr
= new VarDeclaration(Loc(), t
, Id::_argptr
, NULL
);
1558 v_argptr
->storage_class
|= STCtemp
;
1559 v_argptr
->semantic(sc2
);
1560 sc2
->insert(v_argptr
);
1561 v_argptr
->parent
= this;
1565 /* Declare all the function parameters as variables
1566 * and install them in parameters[]
1568 size_t nparams
= Parameter::dim(f
->parameters
);
1571 /* parameters[] has all the tuples removed, as the back end
1572 * doesn't know about tuples
1574 parameters
= new VarDeclarations();
1575 parameters
->reserve(nparams
);
1576 for (size_t i
= 0; i
< nparams
; i
++)
1578 Parameter
*fparam
= Parameter::getNth(f
->parameters
, i
);
1579 Identifier
*id
= fparam
->ident
;
1580 StorageClass stc
= 0;
1583 /* Generate identifier for un-named parameter,
1584 * because we need it later on.
1586 fparam
->ident
= id
= Identifier::generateId("_param_", i
);
1589 Type
*vtype
= fparam
->type
;
1590 VarDeclaration
*v
= new VarDeclaration(loc
, vtype
, id
, NULL
);
1591 //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
1592 stc
|= STCparameter
;
1593 if (f
->varargs
== 2 && i
+ 1 == nparams
)
1595 if (flags
& FUNCFLAGinferScope
&& !(fparam
->storageClass
& STCscope
))
1596 stc
|= STCmaybescope
;
1597 stc
|= fparam
->storageClass
& (STCin
| STCout
| STCref
| STCreturn
| STCscope
| STClazy
| STCfinal
| STC_TYPECTOR
| STCnodtor
);
1598 v
->storage_class
= stc
;
1600 if (!sc2
->insert(v
))
1601 error("parameter %s.%s is already defined", toChars(), v
->toChars());
1603 parameters
->push(v
);
1604 localsymtab
->insert(v
);
1609 // Declare the tuple symbols and put them in the symbol table,
1610 // but not in parameters[].
1613 for (size_t i
= 0; i
< f
->parameters
->dim
; i
++)
1615 Parameter
*fparam
= (*f
->parameters
)[i
];
1618 continue; // never used, so ignore
1619 if (fparam
->type
->ty
== Ttuple
)
1621 TypeTuple
*t
= (TypeTuple
*)fparam
->type
;
1622 size_t dim
= Parameter::dim(t
->arguments
);
1623 Objects
*exps
= new Objects();
1625 for (size_t j
= 0; j
< dim
; j
++)
1627 Parameter
*narg
= Parameter::getNth(t
->arguments
, j
);
1628 assert(narg
->ident
);
1629 VarDeclaration
*v
= sc2
->search(Loc(), narg
->ident
, NULL
)->isVarDeclaration();
1631 Expression
*e
= new VarExp(v
->loc
, v
);
1634 assert(fparam
->ident
);
1635 TupleDeclaration
*v
= new TupleDeclaration(loc
, fparam
->ident
, exps
);
1636 //printf("declaring tuple %s\n", v->toChars());
1638 if (!sc2
->insert(v
))
1639 error("parameter %s.%s is already defined", toChars(), v
->toChars());
1640 localsymtab
->insert(v
);
1646 // Precondition invariant
1647 Statement
*fpreinv
= NULL
;
1648 if (addPreInvariant())
1650 Expression
*e
= addInvariant(loc
, sc
, ad
, vthis
, isDtorDeclaration() != NULL
);
1652 fpreinv
= new ExpStatement(Loc(), e
);
1655 // Postcondition invariant
1656 Statement
*fpostinv
= NULL
;
1657 if (addPostInvariant())
1659 Expression
*e
= addInvariant(loc
, sc
, ad
, vthis
, isCtorDeclaration() != NULL
);
1661 fpostinv
= new ExpStatement(Loc(), e
);
1664 // Pre/Postcondition contract
1666 buildEnsureRequire(this);
1668 Scope
*scout
= NULL
;
1669 if (needEnsure
|| addPostInvariant())
1671 if ((needEnsure
&& global
.params
.useOut
) || fpostinv
)
1673 returnLabel
= new LabelDsymbol(Id::returnLabel
);
1676 // scope of out contract (need for vresult->semantic)
1677 ScopeDsymbol
*sym
= new ScopeDsymbol();
1678 sym
->parent
= sc2
->scopesym
;
1680 sym
->endlinnum
= endloc
.linnum
;
1681 scout
= sc2
->push(sym
);
1686 ScopeDsymbol
*sym
= new ScopeDsymbol();
1687 sym
->parent
= sc2
->scopesym
;
1689 sym
->endlinnum
= endloc
.linnum
;
1690 sc2
= sc2
->push(sym
);
1692 AggregateDeclaration
*ad2
= isMember2();
1694 /* If this is a class constructor
1696 if (ad2
&& isCtorDeclaration())
1698 allocFieldinit(sc2
, ad2
->fields
.dim
);
1699 for (size_t i
= 0; i
< ad2
->fields
.dim
; i
++)
1701 VarDeclaration
*v
= ad2
->fields
[i
];
1706 if (!inferRetType
&& retStyle(f
) != RETstack
)
1709 bool inferRef
= (f
->isref
&& (storage_class
& STCauto
));
1711 fbody
= ::semantic(fbody
, sc2
);
1713 fbody
= new CompoundStatement(Loc(), new Statements());
1717 fpreinv
= NULL
; // can't accommodate with no stack frame
1722 (type
->ty
== Tfunction
&&
1723 f
->purity
== PUREimpure
&&
1724 ((TypeFunction
*)type
)->purity
>= PUREfwdref
));
1725 f
= (TypeFunction
*)type
;
1729 // If no return type inferred yet, then infer a void
1731 f
->next
= Type::tvoid
;
1732 if (f
->checkRetType(loc
))
1733 fbody
= new ErrorStatement();
1735 if (global
.params
.vcomplex
&& f
->next
!= NULL
)
1736 f
->next
->checkComplexTransition(loc
);
1738 if (returns
&& !fbody
->isErrorStatement())
1740 for (size_t i
= 0; i
< returns
->dim
; )
1742 Expression
*exp
= (*returns
)[i
]->exp
;
1743 if (exp
->op
== TOKvar
&& ((VarExp
*)exp
)->var
== vresult
)
1745 if (addReturn0(this))
1746 exp
->type
= Type::tint32
;
1748 exp
->type
= f
->next
;
1749 // Remove `return vresult;` from returns
1753 if (inferRef
&& f
->isref
&& !exp
->type
->constConv(f
->next
)) // Bugzilla 13336
1758 if (f
->isref
) // Function returns a reference
1760 if (storage_class
& STCauto
)
1761 storage_class
&= ~STCauto
;
1763 if (retStyle(f
) != RETstack
)
1766 if (fbody
->isErrorStatement())
1768 else if (isStaticCtorDeclaration())
1770 /* It's a static constructor. Ensure that all
1771 * ctor consts were initialized.
1773 ScopeDsymbol
*pd
= toParent()->isScopeDsymbol();
1774 for (size_t i
= 0; i
< pd
->members
->dim
; i
++)
1776 Dsymbol
*s
= (*pd
->members
)[i
];
1777 s
->checkCtorConstInit();
1780 else if (ad2
&& isCtorDeclaration())
1782 ClassDeclaration
*cd
= ad2
->isClassDeclaration();
1784 // Verify that all the ctorinit fields got initialized
1785 if (!(sc2
->callSuper
& CSXthis_ctor
))
1787 for (size_t i
= 0; i
< ad2
->fields
.dim
; i
++)
1789 VarDeclaration
*v
= ad2
->fields
[i
];
1790 if (v
->isThisDeclaration())
1792 if (v
->ctorinit
== 0)
1794 /* Current bugs in the flow analysis:
1795 * 1. union members should not produce error messages even if
1797 * 2. structs should recognize delegating opAssign calls as well
1798 * as delegating calls to other constructors
1800 if (v
->isCtorinit() && !v
->type
->isMutable() && cd
)
1801 error("missing initializer for %s field %s", MODtoChars(v
->type
->mod
), v
->toChars());
1802 else if (v
->storage_class
& STCnodefaultctor
)
1803 ::error(loc
, "field %s must be initialized in constructor", v
->toChars());
1804 else if (v
->type
->needsNested())
1805 ::error(loc
, "field %s must be initialized in constructor, because it is nested struct", v
->toChars());
1809 bool mustInit
= (v
->storage_class
& STCnodefaultctor
||
1810 v
->type
->needsNested());
1811 if (mustInit
&& !(sc2
->fieldinit
[i
] & CSXthis_ctor
))
1813 error("field %s must be initialized but skipped", v
->toChars());
1821 !(sc2
->callSuper
& CSXany_ctor
) &&
1822 cd
->baseClass
&& cd
->baseClass
->ctor
)
1826 // Insert implicit super() at start of fbody
1827 FuncDeclaration
*fd
= resolveFuncCall(Loc(), sc2
, cd
->baseClass
->ctor
, NULL
, vthis
->type
, NULL
, 1);
1830 error("no match for implicit super() call in constructor");
1832 else if (fd
->storage_class
& STCdisable
)
1834 error("cannot call super() implicitly because it is annotated with @disable");
1838 Expression
*e1
= new SuperExp(Loc());
1839 Expression
*e
= new CallExp(Loc(), e1
);
1840 e
= ::semantic(e
, sc2
);
1842 Statement
*s
= new ExpStatement(Loc(), e
);
1843 fbody
= new CompoundStatement(Loc(), s
, fbody
);
1846 //printf("callSuper = x%x\n", sc2->callSuper);
1849 /* https://issues.dlang.org/show_bug.cgi?id=17502
1850 * Wait until after the return type has been inferred before
1851 * generating the contracts for this function, and merging contracts
1854 * https://issues.dlang.org/show_bug.cgi?id=17893
1855 * However should take care to generate this before inferered
1856 * function attributes are applied, such as 'nothrow'.
1858 * This was originally at the end of the first semantic pass, but
1859 * required a fix-up to be done here for the '__result' variable
1860 * type of __ensure() inside auto functions, but this didn't work
1861 * if the out parameter was implicit.
1863 buildEnsureRequire(this);
1865 int blockexit
= BEnone
;
1866 if (!fbody
->isErrorStatement())
1868 // Check for errors related to 'nothrow'.
1869 unsigned int nothrowErrors
= global
.errors
;
1870 blockexit
= blockExit(fbody
, this, f
->isnothrow
);
1871 if (f
->isnothrow
&& (global
.errors
!= nothrowErrors
))
1872 ::error(loc
, "nothrow %s '%s' may throw", kind(), toPrettyChars());
1873 if (flags
& FUNCFLAGnothrowInprocess
)
1875 if (type
== f
) f
= (TypeFunction
*)f
->copy();
1876 f
->isnothrow
= !(blockexit
& BEthrow
);
1880 if (fbody
->isErrorStatement())
1882 else if (ad2
&& isCtorDeclaration())
1888 if (blockexit
& BEfallthru
)
1890 Statement
*s
= new ReturnStatement(loc
, NULL
);
1891 s
= ::semantic(s
, sc2
);
1892 fbody
= new CompoundStatement(loc
, fbody
, s
);
1893 hasReturnExp
|= (hasReturnExp
& 1 ? 16 : 1);
1898 // For foreach(){} body, append a return 0;
1899 if (blockexit
& BEfallthru
)
1901 Expression
*e
= new IntegerExp(0);
1902 Statement
*s
= new ReturnStatement(Loc(), e
);
1903 fbody
= new CompoundStatement(Loc(), fbody
, s
);
1904 hasReturnExp
|= (hasReturnExp
& 1 ? 16 : 1);
1906 assert(!returnLabel
);
1910 const bool inlineAsm
= (hasReturnExp
& 8) != 0;
1911 if ((blockexit
& BEfallthru
) && f
->next
->ty
!= Tvoid
&& !inlineAsm
)
1915 error("has no return statement, but is expected to return a value of type %s", f
->next
->toChars());
1917 error("no return exp; or assert(0); at end of function");
1918 if (global
.params
.useAssert
&&
1919 !global
.params
.useInline
)
1921 /* Add an assert(0, msg); where the missing return
1927 new StringExp(loc
, const_cast<char *>("missing return expression"))
1931 e
= new HaltExp(endloc
);
1932 e
= new CommaExp(Loc(), e
, f
->next
->defaultInit());
1933 e
= ::semantic(e
, sc2
);
1934 Statement
*s
= new ExpStatement(Loc(), e
);
1935 fbody
= new CompoundStatement(Loc(), fbody
, s
);
1941 bool implicit0
= addReturn0(this);
1942 Type
*tret
= implicit0
? Type::tint32
: f
->next
;
1943 assert(tret
->ty
!= Tvoid
);
1944 if (vresult
|| returnLabel
)
1945 buildResultVar(scout
? scout
: sc2
, tret
);
1947 /* Cannot move this loop into NrvoWalker, because
1948 * returns[i] may be in the nested delegate for foreach-body.
1950 for (size_t i
= 0; i
< returns
->dim
; i
++)
1952 ReturnStatement
*rs
= (*returns
)[i
];
1953 Expression
*exp
= rs
->exp
;
1954 if (exp
->op
== TOKerror
)
1956 if (tret
->ty
== Terror
)
1959 exp
= checkGC(sc2
, exp
);
1963 if (!exp
->implicitConvTo(tret
) &&
1964 parametersIntersect(exp
->type
))
1966 if (exp
->type
->immutableOf()->implicitConvTo(tret
))
1967 exp
= exp
->castTo(sc2
, exp
->type
->immutableOf());
1968 else if (exp
->type
->wildOf()->implicitConvTo(tret
))
1969 exp
= exp
->castTo(sc2
, exp
->type
->wildOf());
1971 exp
= exp
->implicitCastTo(sc2
, tret
);
1975 // Function returns a reference
1976 exp
= exp
->toLvalue(sc2
, exp
);
1977 checkReturnEscapeRef(sc2
, exp
, false);
1981 exp
= exp
->optimize(WANTvalue
);
1984 * If NRVO is not possible, all returned lvalues should call their postblits.
1987 exp
= doCopyOrMove(sc2
, exp
);
1989 if (tret
->hasPointers())
1990 checkReturnEscape(sc2
, exp
, false);
1993 exp
= checkGC(sc2
, exp
);
1997 // Create: return vresult = exp;
1998 exp
= new BlitExp(rs
->loc
, vresult
, exp
);
1999 exp
->type
= vresult
->type
;
2002 exp
= Expression::combine(exp
, new IntegerExp(rs
->caseDim
));
2004 else if (tintro
&& !tret
->equals(tintro
->nextOf()))
2006 exp
= exp
->implicitCastTo(sc2
, tintro
->nextOf());
2011 if (nrvo_var
|| returnLabel
)
2016 nw
.visitStmt(fbody
);
2022 frequire
= mergeFrequire(frequire
);
2023 fensure
= mergeFensure(fensure
, outId
);
2025 Statement
*freq
= frequire
;
2026 Statement
*fens
= fensure
;
2028 /* Do the semantic analysis on the [in] preconditions and
2029 * [out] postconditions.
2033 /* frequire is composed of the [in] contracts
2035 ScopeDsymbol
*sym
= new ScopeDsymbol();
2036 sym
->parent
= sc2
->scopesym
;
2038 sym
->endlinnum
= endloc
.linnum
;
2039 sc2
= sc2
->push(sym
);
2040 sc2
->flags
= (sc2
->flags
& ~SCOPEcontract
) | SCOPErequire
;
2042 // BUG: need to error if accessing out parameters
2043 // BUG: need to treat parameters as const
2044 // BUG: need to disallow returns and throws
2045 // BUG: verify that all in and ref parameters are read
2046 freq
= ::semantic(freq
, sc2
);
2047 blockExit(freq
, this, false);
2051 if (!global
.params
.useIn
)
2057 /* fensure is composed of the [out] contracts
2059 if (f
->next
->ty
== Tvoid
&& outId
)
2060 error("void functions have no result");
2063 sc2
->flags
= (sc2
->flags
& ~SCOPEcontract
) | SCOPEensure
;
2065 // BUG: need to treat parameters as const
2066 // BUG: need to disallow returns and throws
2067 if (fensure
&& f
->next
->ty
!= Tvoid
)
2068 buildResultVar(scout
, f
->next
);
2070 fens
= ::semantic(fens
, sc2
);
2071 blockExit(fens
, this, false);
2075 if (!global
.params
.useOut
)
2079 if (fbody
&& fbody
->isErrorStatement())
2083 Statements
*a
= new Statements();
2085 // Merge in initialization of 'out' parameters
2088 for (size_t i
= 0; i
< parameters
->dim
; i
++)
2090 VarDeclaration
*v
= (*parameters
)[i
];
2091 if (v
->storage_class
& STCout
)
2094 ExpInitializer
*ie
= v
->_init
->isExpInitializer();
2096 if (ie
->exp
->op
== TOKconstruct
)
2097 ie
->exp
->op
= TOKassign
; // construction occured in parameter processing
2098 a
->push(new ExpStatement(Loc(), ie
->exp
));
2105 // Handled in FuncDeclaration::toObjFile
2106 v_argptr
->_init
= new VoidInitializer(loc
);
2111 /* Advance to elements[] member of TypeInfo_Tuple with:
2112 * _arguments = v_arguments.elements;
2114 Expression
*e
= new VarExp(Loc(), v_arguments
);
2115 e
= new DotIdExp(Loc(), e
, Id::elements
);
2116 e
= new ConstructExp(Loc(), _arguments
, e
);
2117 e
= ::semantic(e
, sc2
);
2119 _arguments
->_init
= new ExpInitializer(Loc(), e
);
2120 DeclarationExp
*de
= new DeclarationExp(Loc(), _arguments
);
2121 a
->push(new ExpStatement(Loc(), de
));
2124 // Merge contracts together with body into one compound statement
2126 if (freq
|| fpreinv
)
2131 freq
= new CompoundStatement(Loc(), freq
, fpreinv
);
2139 if (fens
|| fpostinv
)
2144 fens
= new CompoundStatement(Loc(), fpostinv
, fens
);
2146 LabelStatement
*ls
= new LabelStatement(Loc(), Id::returnLabel
, fens
);
2147 returnLabel
->statement
= ls
;
2148 a
->push(returnLabel
->statement
);
2150 if (f
->next
->ty
!= Tvoid
&& vresult
)
2152 // Create: return vresult;
2153 Expression
*e
= new VarExp(Loc(), vresult
);
2156 e
= e
->implicitCastTo(sc
, tintro
->nextOf());
2157 e
= ::semantic(e
, sc
);
2159 ReturnStatement
*s
= new ReturnStatement(Loc(), e
);
2163 if (addReturn0(this))
2165 // Add a return 0; statement
2166 Statement
*s
= new ReturnStatement(Loc(), new IntegerExp(0));
2170 Statement
*sbody
= new CompoundStatement(Loc(), a
);
2171 /* Append destructor calls for parameters as finally blocks.
2175 for (size_t i
= 0; i
< parameters
->dim
; i
++)
2177 VarDeclaration
*v
= (*parameters
)[i
];
2179 if (v
->storage_class
& (STCref
| STCout
| STClazy
))
2182 if (v
->needsScopeDtor())
2184 // same with ExpStatement.scopeCode()
2185 Statement
*s
= new DtorExpStatement(Loc(), v
->edtor
, v
);
2186 v
->storage_class
|= STCnodtor
;
2188 s
= ::semantic(s
, sc2
);
2190 bool isnothrow
= f
->isnothrow
& !(flags
& FUNCFLAGnothrowInprocess
);
2191 int blockexit
= blockExit(s
, this, isnothrow
);
2192 if (f
->isnothrow
&& isnothrow
&& blockexit
& BEthrow
)
2193 ::error(loc
, "nothrow %s '%s' may throw", kind(), toPrettyChars());
2194 if (flags
& FUNCFLAGnothrowInprocess
&& blockexit
& BEthrow
)
2195 f
->isnothrow
= false;
2196 if (blockExit(sbody
, this, f
->isnothrow
) == BEfallthru
)
2197 sbody
= new CompoundStatement(Loc(), sbody
, s
);
2199 sbody
= new TryFinallyStatement(Loc(), sbody
, s
);
2203 // from this point on all possible 'throwers' are checked
2204 flags
&= ~FUNCFLAGnothrowInprocess
;
2206 if (isSynchronized())
2208 /* Wrap the entire function body in a synchronized statement
2210 ClassDeclaration
*cd
= isThis() ? isThis()->isClassDeclaration() : parent
->isClassDeclaration();
2214 if (!global
.params
.is64bit
&&
2215 global
.params
.isWindows
&&
2216 !isStatic() && !sbody
->usesEH() && !global
.params
.trace
)
2218 /* The back end uses the "jmonitor" hack for syncing;
2219 * no need to do the sync at this level.
2227 // The monitor is in the ClassInfo
2228 vsync
= new DotIdExp(loc
, resolve(loc
, sc2
, cd
, false), Id::classinfo
);
2232 // 'this' is the monitor
2233 vsync
= new VarExp(loc
, vthis
);
2235 sbody
= new PeelStatement(sbody
); // don't redo semantic()
2236 sbody
= new SynchronizedStatement(loc
, vsync
, sbody
);
2237 sbody
= ::semantic(sbody
, sc2
);
2242 error("synchronized function %s must be a member of a class", toChars());
2246 // If declaration has no body, don't set sbody to prevent incorrect codegen.
2247 InterfaceDeclaration
*id
= parent
->isInterfaceDeclaration();
2248 if (fbody
|| (id
&& (fdensure
|| fdrequire
) && isVirtual()))
2252 // Fix up forward-referenced gotos
2255 for (size_t i
= 0; i
< gotos
->dim
; ++i
)
2257 (*gotos
)[i
]->checkLabel();
2261 if (naked
&& (fensure
|| frequire
))
2262 error("naked assembly functions with contracts are not supported");
2270 // We should be setting errors here instead of relying on the global error count.
2274 /* If function survived being marked as impure, then it is pure
2276 if (flags
& FUNCFLAGpurityInprocess
)
2278 flags
&= ~FUNCFLAGpurityInprocess
;
2280 f
= (TypeFunction
*)f
->copy();
2281 f
->purity
= PUREfwdref
;
2284 if (flags
& FUNCFLAGsafetyInprocess
)
2286 flags
&= ~FUNCFLAGsafetyInprocess
;
2288 f
= (TypeFunction
*)f
->copy();
2289 f
->trust
= TRUSTsafe
;
2292 if (flags
& FUNCFLAGnogcInprocess
)
2294 flags
&= ~FUNCFLAGnogcInprocess
;
2296 f
= (TypeFunction
*)f
->copy();
2300 if (flags
& FUNCFLAGreturnInprocess
)
2302 flags
&= ~FUNCFLAGreturnInprocess
;
2303 if (storage_class
& STCreturn
)
2306 f
= (TypeFunction
*)f
->copy();
2311 flags
&= ~FUNCFLAGinferScope
;
2316 size_t nfparams
= Parameter::dim(f
->parameters
);
2317 assert(nfparams
== parameters
->dim
);
2318 for (size_t u
= 0; u
< parameters
->dim
; u
++)
2320 VarDeclaration
*v
= (*parameters
)[u
];
2321 if (v
->storage_class
& STCmaybescope
)
2323 //printf("Inferring scope for %s\n", v->toChars());
2324 Parameter
*p
= Parameter::getNth(f
->parameters
, u
);
2325 v
->storage_class
&= ~STCmaybescope
;
2326 v
->storage_class
|= STCscope
| STCscopeinferred
;
2327 p
->storageClass
|= STCscope
| STCscopeinferred
;
2328 assert(!(p
->storageClass
& STCmaybescope
));
2333 if (vthis
&& vthis
->storage_class
& STCmaybescope
)
2335 vthis
->storage_class
&= ~STCmaybescope
;
2336 vthis
->storage_class
|= STCscope
| STCscopeinferred
;
2338 f
->isscopeinferred
= true;
2341 // reset deco to apply inference result to mangled name
2345 // Do semantic type AFTER pure/nothrow inference.
2346 if (!f
->deco
&& ident
!= Id::xopEquals
&& ident
!= Id::xopCmp
)
2349 if (isCtorDeclaration()) // Bugzilla #15665
2350 sc
->flags
|= SCOPEctor
;
2352 sc
->linkage
= linkage
; // Bugzilla 8496
2353 type
= f
->semantic(loc
, sc
);
2357 /* If this function had instantiated with gagging, error reproduction will be
2358 * done by TemplateInstance::semantic.
2359 * Otherwise, error gagging should be temporarily ungagged by functionSemantic3.
2361 semanticRun
= PASSsemantic3done
;
2362 semantic3Errors
= (global
.errors
!= oldErrors
) || (fbody
&& fbody
->isErrorStatement());
2363 if (type
->ty
== Terror
)
2365 //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
2369 /****************************************************
2370 * Resolve forward reference of function signature -
2371 * parameter types, return type, and attributes.
2372 * Returns false if any errors exist in the signature.
2374 bool FuncDeclaration::functionSemantic()
2379 if (!originalType
) // semantic not yet run
2381 TemplateInstance
*spec
= isSpeculative();
2382 unsigned olderrs
= global
.errors
;
2383 unsigned oldgag
= global
.gag
;
2384 if (global
.gag
&& !spec
)
2387 global
.gag
= oldgag
;
2388 if (spec
&& global
.errors
!= olderrs
)
2389 spec
->errors
= (global
.errors
- olderrs
!= 0);
2390 if (olderrs
!= global
.errors
) // if errors compiling this function
2394 // if inferring return type, sematic3 needs to be run
2395 // - When the function body contains any errors, we cannot assume
2396 // the inferred return type is valid.
2397 // So, the body errors should become the function signature error.
2398 if (inferRetType
&& type
&& !type
->nextOf())
2399 return functionSemantic3();
2401 TemplateInstance
*ti
;
2402 if (isInstantiated() && !isVirtualMethod() &&
2403 ((ti
= parent
->isTemplateInstance()) == NULL
|| ti
->isTemplateMixin() || ti
->tempdecl
->ident
== ident
))
2405 AggregateDeclaration
*ad
= isMember2();
2406 if (ad
&& ad
->sizeok
!= SIZEOKdone
)
2408 /* Currently dmd cannot resolve forward references per methods,
2409 * then setting SIZOKfwd is too conservative and would break existing code.
2410 * So, just stop method attributes inference until ad->semantic() done.
2412 //ad->sizeok = SIZEOKfwd;
2415 return functionSemantic3() || !errors
;
2418 if (storage_class
& STCinference
)
2419 return functionSemantic3() || !errors
;
2424 /****************************************************
2425 * Resolve forward reference of function body.
2426 * Returns false if any errors exist in the body.
2428 bool FuncDeclaration::functionSemantic3()
2430 if (semanticRun
< PASSsemantic3
&& _scope
)
2432 /* Forward reference - we need to run semantic3 on this function.
2433 * If errors are gagged, and it's not part of a template instance,
2434 * we need to temporarily ungag errors.
2436 TemplateInstance
*spec
= isSpeculative();
2437 unsigned olderrs
= global
.errors
;
2438 unsigned oldgag
= global
.gag
;
2439 if (global
.gag
&& !spec
)
2442 global
.gag
= oldgag
;
2444 // If it is a speculatively-instantiated template, and errors occur,
2445 // we need to mark the template as having errors.
2446 if (spec
&& global
.errors
!= olderrs
)
2447 spec
->errors
= (global
.errors
- olderrs
!= 0);
2448 if (olderrs
!= global
.errors
) // if errors compiling this function
2452 return !errors
&& !semantic3Errors
;
2455 /****************************************************
2456 * Check that this function type is properly resolved.
2457 * If not, report "forward reference error" and return true.
2459 bool FuncDeclaration::checkForwardRef(Loc loc
)
2461 if (!functionSemantic())
2464 /* No deco means the functionSemantic() call could not resolve
2465 * forward referenes in the type of this function.
2469 bool inSemantic3
= (inferRetType
&& semanticRun
>= PASSsemantic3
);
2470 ::error(loc
, "forward reference to %s'%s'",
2471 (inSemantic3
? "inferred return type of function " : ""),
2478 VarDeclaration
*FuncDeclaration::declareThis(Scope
*sc
, AggregateDeclaration
*ad
)
2484 //printf("declareThis() %s\n", toChars());
2485 Type
*thandle
= ad
->handleType();
2487 thandle
= thandle
->addMod(type
->mod
);
2488 thandle
= thandle
->addStorageClass(storage_class
);
2489 v
= new ThisDeclaration(loc
, thandle
);
2490 v
->storage_class
|= STCparameter
;
2491 if (thandle
->ty
== Tstruct
)
2493 v
->storage_class
|= STCref
;
2495 // if member function is marked 'inout', then 'this' is 'return ref'
2496 if (type
->ty
== Tfunction
&& ((TypeFunction
*)type
)->iswild
& 2)
2497 v
->storage_class
|= STCreturn
;
2499 if (type
->ty
== Tfunction
)
2501 TypeFunction
*tf
= (TypeFunction
*)type
;
2503 v
->storage_class
|= STCreturn
;
2505 v
->storage_class
|= STCscope
;
2507 if (flags
& FUNCFLAGinferScope
&& !(v
->storage_class
& STCscope
))
2508 v
->storage_class
|= STCmaybescope
;
2517 else if (isNested())
2519 /* The 'this' for a nested function is the link to the
2520 * enclosing function's stack frame.
2521 * Note that nested functions and member functions are disjoint.
2523 VarDeclaration
*v
= new ThisDeclaration(loc
, Type::tvoid
->pointerTo());
2524 v
->storage_class
|= STCparameter
;
2525 if (type
->ty
== Tfunction
)
2527 TypeFunction
*tf
= (TypeFunction
*)type
;
2529 v
->storage_class
|= STCreturn
;
2531 v
->storage_class
|= STCscope
;
2533 if (flags
& FUNCFLAGinferScope
&& !(v
->storage_class
& STCscope
))
2534 v
->storage_class
|= STCmaybescope
;
2546 bool FuncDeclaration::equals(RootObject
*o
)
2551 Dsymbol
*s
= isDsymbol(o
);
2554 FuncDeclaration
*fd1
= this;
2555 FuncDeclaration
*fd2
= s
->isFuncDeclaration();
2559 FuncAliasDeclaration
*fa1
= fd1
->isFuncAliasDeclaration();
2560 FuncAliasDeclaration
*fa2
= fd2
->isFuncAliasDeclaration();
2563 return fa1
->toAliasFunc()->equals(fa2
->toAliasFunc()) &&
2564 fa1
->hasOverloads
== fa2
->hasOverloads
;
2567 if (fa1
&& (fd1
= fa1
->toAliasFunc())->isUnique() && !fa1
->hasOverloads
)
2569 if (fa2
&& (fd2
= fa2
->toAliasFunc())->isUnique() && !fa2
->hasOverloads
)
2571 if ((fa1
!= NULL
) != (fa2
!= NULL
))
2574 return fd1
->toParent()->equals(fd2
->toParent()) &&
2575 fd1
->ident
->equals(fd2
->ident
) && fd1
->type
->equals(fd2
->type
);
2580 /****************************************************
2581 * Declare result variable lazily.
2584 void FuncDeclaration::buildResultVar(Scope
*sc
, Type
*tret
)
2588 Loc loc
= fensure
? fensure
->loc
: this->loc
;
2590 /* If inferRetType is true, tret may not be a correct return type yet.
2591 * So, in here it may be a temporary type for vresult, and after
2592 * fbody->semantic() running, vresult->type might be modified.
2594 vresult
= new VarDeclaration(loc
, tret
, outId
? outId
: Id::result
, NULL
);
2595 vresult
->storage_class
|= STCnodtor
;
2597 if (outId
== Id::result
)
2598 vresult
->storage_class
|= STCtemp
;
2600 vresult
->storage_class
|= STCconst
;
2601 vresult
->storage_class
|= STCresult
;
2603 // set before the semantic() for checkNestedReference()
2604 vresult
->parent
= this;
2607 if (sc
&& vresult
->semanticRun
== PASSinit
)
2609 TypeFunction
*tf
= type
->toTypeFunction();
2611 vresult
->storage_class
|= STCref
;
2612 vresult
->type
= tret
;
2614 vresult
->semantic(sc
);
2616 if (!sc
->insert(vresult
))
2617 error("out result %s is already defined", vresult
->toChars());
2618 assert(vresult
->parent
== this);
2622 /****************************************************
2623 * Merge into this function the 'in' contracts of all it overrides.
2624 * 'in's are OR'd together, i.e. only one of them needs to pass.
2627 Statement
*FuncDeclaration::mergeFrequire(Statement
*sf
)
2629 /* If a base function and its override both have an IN contract, then
2630 * only one of them needs to succeed. This is done by generating:
2632 * void derived.in() {
2637 * ... body of derived.in() ...
2641 * So if base.in() doesn't throw, derived.in() need not be executed, and the contract is valid.
2642 * If base.in() throws, then derived.in()'s body is executed.
2645 /* Implementing this is done by having the overriding function call
2646 * nested functions (the fdrequire functions) nested inside the overridden
2647 * function. This requires that the stack layout of the calling function's
2648 * parameters and 'this' pointer be in the same place (as the nested
2649 * function refers to them).
2650 * This is easy for the parameters, as they are all on the stack in the same
2651 * place by definition, since it's an overriding function. The problem is
2652 * getting the 'this' pointer in the same place, since it is a local variable.
2653 * We did some hacks in the code generator to make this happen:
2654 * 1. always generate exception handler frame, or at least leave space for it
2655 * in the frame (Windows 32 SEH only)
2656 * 2. always generate an EBP style frame
2657 * 3. since 'this' is passed in a register that is subsequently copied into
2658 * a stack local, allocate that local immediately following the exception
2659 * handler block, so it is always at the same offset from EBP.
2661 for (size_t i
= 0; i
< foverrides
.dim
; i
++)
2663 FuncDeclaration
*fdv
= foverrides
[i
];
2665 /* The semantic pass on the contracts of the overridden functions must
2666 * be completed before code generation occurs.
2667 * https://issues.dlang.org/show_bug.cgi?id=3602
2669 if (fdv
->frequire
&& fdv
->semanticRun
!= PASSsemantic3done
)
2671 assert(fdv
->_scope
);
2672 Scope
*sc
= fdv
->_scope
->push();
2673 sc
->stc
&= ~STCoverride
;
2678 sf
= fdv
->mergeFrequire(sf
);
2679 if (sf
&& fdv
->fdrequire
)
2681 //printf("fdv->frequire: %s\n", fdv->frequire->toChars());
2683 * try { __require(); }
2684 * catch (Throwable) { frequire; }
2686 Expression
*eresult
= NULL
;
2687 Expression
*e
= new CallExp(loc
, new VarExp(loc
, fdv
->fdrequire
, false), eresult
);
2688 Statement
*s2
= new ExpStatement(loc
, e
);
2690 Catch
*c
= new Catch(loc
, getThrowable(), NULL
, sf
);
2691 c
->internalCatch
= true;
2692 Catches
*catches
= new Catches();
2694 sf
= new TryCatchStatement(loc
, s2
, catches
);
2702 /****************************************************
2703 * Merge into this function the 'out' contracts of all it overrides.
2704 * 'out's are AND'd together, i.e. all of them need to pass.
2707 Statement
*FuncDeclaration::mergeFensure(Statement
*sf
, Identifier
*oid
)
2709 /* Same comments as for mergeFrequire(), except that we take care
2710 * of generating a consistent reference to the 'result' local by
2711 * explicitly passing 'result' to the nested function as a reference
2713 * This won't work for the 'this' parameter as it would require changing
2714 * the semantic code for the nested function so that it looks on the parameter
2715 * list for the 'this' pointer, something that would need an unknown amount
2716 * of tweaking of various parts of the compiler that I'd rather leave alone.
2718 for (size_t i
= 0; i
< foverrides
.dim
; i
++)
2720 FuncDeclaration
*fdv
= foverrides
[i
];
2722 /* The semantic pass on the contracts of the overridden functions must
2723 * be completed before code generation occurs.
2724 * https://issues.dlang.org/show_bug.cgi?id=3602 and
2725 * https://issues.dlang.org/show_bug.cgi?id=5230
2727 if (needsFensure(fdv
) && fdv
->semanticRun
!= PASSsemantic3done
)
2729 assert(fdv
->_scope
);
2730 Scope
*sc
= fdv
->_scope
->push();
2731 sc
->stc
&= ~STCoverride
;
2736 sf
= fdv
->mergeFensure(sf
, oid
);
2739 //printf("fdv->fensure: %s\n", fdv->fensure->toChars());
2740 // Make the call: __ensure(result)
2741 Expression
*eresult
= NULL
;
2744 eresult
= new IdentifierExp(loc
, oid
);
2746 Type
*t1
= fdv
->type
->nextOf()->toBasetype();
2747 Type
*t2
= this->type
->nextOf()->toBasetype();
2748 if (t1
->isBaseOf(t2
, NULL
))
2750 /* Making temporary reference variable is necessary
2751 * in covariant return.
2752 * See bugzilla 5204 and 10479.
2754 ExpInitializer
*ei
= new ExpInitializer(Loc(), eresult
);
2755 VarDeclaration
*v
= new VarDeclaration(Loc(), t1
, Identifier::generateId("__covres"), ei
);
2756 v
->storage_class
|= STCtemp
;
2757 DeclarationExp
*de
= new DeclarationExp(Loc(), v
);
2758 VarExp
*ve
= new VarExp(Loc(), v
);
2759 eresult
= new CommaExp(Loc(), de
, ve
);
2762 Expression
*e
= new CallExp(loc
, new VarExp(loc
, fdv
->fdensure
, false), eresult
);
2763 Statement
*s2
= new ExpStatement(loc
, e
);
2767 sf
= new CompoundStatement(sf
->loc
, s2
, sf
);
2776 /****************************************************
2777 * Determine if 'this' overrides fd.
2778 * Return !=0 if it does.
2781 int FuncDeclaration::overrides(FuncDeclaration
*fd
)
2784 if (fd
->ident
== ident
)
2786 int cov
= type
->covariant(fd
->type
);
2788 { ClassDeclaration
*cd1
= toParent()->isClassDeclaration();
2789 ClassDeclaration
*cd2
= fd
->toParent()->isClassDeclaration();
2791 if (cd1
&& cd2
&& cd2
->isBaseOf(cd1
, NULL
))
2798 /*************************************************
2799 * Find index of function in vtbl[0..dim] that
2800 * this function overrides.
2801 * Prefer an exact match to a covariant one.
2803 * fix17349 = enable fix https://issues.dlang.org/show_bug.cgi?id=17349
2805 * -1 didn't find one
2806 * -2 can't determine because of forward references
2809 int FuncDeclaration::findVtblIndex(Dsymbols
*vtbl
, int dim
, bool fix17349
)
2811 //printf("findVtblIndex() %s\n", toChars());
2812 FuncDeclaration
*mismatch
= NULL
;
2813 StorageClass mismatchstc
= 0;
2814 int mismatchvi
= -1;
2817 for (int vi
= 0; vi
< dim
; vi
++)
2819 FuncDeclaration
*fdv
= (*vtbl
)[vi
]->isFuncDeclaration();
2820 if (fdv
&& fdv
->ident
== ident
)
2822 if (type
->equals(fdv
->type
)) // if exact match
2824 if (fdv
->parent
->isClassDeclaration())
2826 if (fdv
->isFuture())
2829 continue; // keep looking
2831 return vi
; // no need to look further
2836 error("cannot determine overridden function");
2845 StorageClass stc
= 0;
2846 int cov
= type
->covariant(fdv
->type
, &stc
, fix17349
);
2847 //printf("\tbaseclass cov = %d\n", cov);
2850 case 0: // types are distinct
2854 bestvi
= vi
; // covariant, but not identical
2855 break; // keep looking for an exact match
2860 mismatch
= fdv
; // overrides, but is not covariant
2861 break; // keep looking for an exact match
2864 return -2; // forward references
2871 if (bestvi
== -1 && mismatch
)
2874 //mismatch->type->print();
2875 //printf("%s %s\n", type->deco, mismatch->type->deco);
2876 //printf("stc = %llx\n", mismatchstc);
2878 { // Fix it by modifying the type to add the storage classes
2879 type
= type
->addStorageClass(mismatchstc
);
2880 bestvi
= mismatchvi
;
2886 /*********************************
2887 * If function a function in a base class,
2888 * return that base class.
2890 * cd = class that function is in
2892 * base class if overriding, NULL if not
2894 BaseClass
*FuncDeclaration::overrideInterface()
2896 ClassDeclaration
*cd
= parent
->isClassDeclaration();
2897 for (size_t i
= 0; i
< cd
->interfaces
.length
; i
++)
2899 BaseClass
*b
= cd
->interfaces
.ptr
[i
];
2900 int v
= findVtblIndex((Dsymbols
*)&b
->sym
->vtbl
, (int)b
->sym
->vtbl
.dim
);
2907 /****************************************************
2908 * Overload this FuncDeclaration with the new one f.
2909 * Return true if successful; i.e. no conflict.
2912 bool FuncDeclaration::overloadInsert(Dsymbol
*s
)
2914 //printf("FuncDeclaration::overloadInsert(s = %s) this = %s\n", s->toChars(), toChars());
2917 AliasDeclaration
*ad
= s
->isAliasDeclaration();
2921 return overnext
->overloadInsert(ad
);
2922 if (!ad
->aliassym
&& ad
->type
->ty
!= Tident
&& ad
->type
->ty
!= Tinstance
)
2924 //printf("\tad = '%s'\n", ad->type->toChars());
2928 //printf("\ttrue: no conflict\n");
2931 TemplateDeclaration
*td
= s
->isTemplateDeclaration();
2935 td
->funcroot
= this;
2937 return overnext
->overloadInsert(td
);
2941 FuncDeclaration
*fd
= s
->isFuncDeclaration();
2947 td
= overnext
->isTemplateDeclaration();
2949 fd
->overloadInsert(td
);
2951 return overnext
->overloadInsert(fd
);
2954 //printf("\ttrue: no conflict\n");
2958 /***************************************************
2959 * Visit each overloaded function/template in turn, and call
2960 * (*fp)(param, s) on it.
2961 * Exit when no more, or (*fp)(param, f) returns nonzero.
2967 int overloadApply(Dsymbol
*fstart
, void *param
, int (*fp
)(void *, Dsymbol
*))
2971 for (d
= fstart
; d
; d
= next
)
2973 if (OverDeclaration
*od
= d
->isOverDeclaration())
2975 if (od
->hasOverloads
)
2977 if (int r
= overloadApply(od
->aliassym
, param
, fp
))
2982 if (int r
= (*fp
)(param
, od
->aliassym
))
2985 next
= od
->overnext
;
2987 else if (FuncAliasDeclaration
*fa
= d
->isFuncAliasDeclaration())
2989 if (fa
->hasOverloads
)
2991 if (int r
= overloadApply(fa
->funcalias
, param
, fp
))
2996 FuncDeclaration
*fd
= fa
->toAliasFunc();
2999 d
->error("is aliased to a function");
3002 if (int r
= (*fp
)(param
, fd
))
3005 next
= fa
->overnext
;
3007 else if (AliasDeclaration
*ad
= d
->isAliasDeclaration())
3009 next
= ad
->toAlias();
3015 else if (TemplateDeclaration
*td
= d
->isTemplateDeclaration())
3017 if (int r
= (*fp
)(param
, td
))
3019 next
= td
->overnext
;
3023 FuncDeclaration
*fd
= d
->isFuncDeclaration();
3026 d
->error("is aliased to a function");
3027 break; // BUG: should print error message?
3029 if (int r
= (*fp
)(param
, fd
))
3031 next
= fd
->overnext
;
3037 /********************************************
3038 * If there are no overloads of function f, return that function,
3039 * otherwise return NULL.
3042 FuncDeclaration
*FuncDeclaration::isUnique()
3046 static int fp(void *param
, Dsymbol
*s
)
3048 FuncDeclaration
*f
= s
->isFuncDeclaration();
3051 FuncDeclaration
**pf
= (FuncDeclaration
**)param
;
3056 return 1; // ambiguous, done
3065 FuncDeclaration
*result
= NULL
;
3066 overloadApply(this, &result
, &ParamUnique::fp
);
3070 /********************************************
3071 * Find function in overload list that exactly matches t.
3074 FuncDeclaration
*FuncDeclaration::overloadExactMatch(Type
*t
)
3078 Type
*t
; // type to match
3079 FuncDeclaration
*f
; // return value
3081 static int fp(void *param
, Dsymbol
*s
)
3083 FuncDeclaration
*f
= s
->isFuncDeclaration();
3086 ParamExact
*p
= (ParamExact
*)param
;
3089 if (t
->equals(f
->type
))
3095 /* Allow covariant matches, as long as the return type
3096 * is just a const conversion.
3097 * This allows things like pure functions to match with an impure function type.
3099 if (t
->ty
== Tfunction
)
3100 { TypeFunction
*tf
= (TypeFunction
*)f
->type
;
3101 if (tf
->covariant(t
) == 1 &&
3102 tf
->nextOf()->implicitConvTo(t
->nextOf()) >= MATCHconst
)
3114 overloadApply(this, &p
, &ParamExact::fp
);
3118 void MODMatchToBuffer(OutBuffer
*buf
, unsigned char lhsMod
, unsigned char rhsMod
)
3120 bool bothMutable
= ((lhsMod
& rhsMod
) == 0);
3121 bool sharedMismatch
= ((lhsMod
^ rhsMod
) & MODshared
) != 0;
3122 bool sharedMismatchOnly
= ((lhsMod
^ rhsMod
) == MODshared
);
3124 if (lhsMod
& MODshared
)
3125 buf
->writestring("shared ");
3126 else if (sharedMismatch
&& !(lhsMod
& MODimmutable
))
3127 buf
->writestring("non-shared ");
3129 if (bothMutable
&& sharedMismatchOnly
)
3131 else if (lhsMod
& MODimmutable
)
3132 buf
->writestring("immutable ");
3133 else if (lhsMod
& MODconst
)
3134 buf
->writestring("const ");
3135 else if (lhsMod
& MODwild
)
3136 buf
->writestring("inout ");
3138 buf
->writestring("mutable ");
3141 /********************************************
3142 * Find function in overload list that matches to the 'this' modifier.
3143 * There's four result types.
3145 * 1. If the 'tthis' matches only one candidate, it's an "exact match".
3146 * Returns the function and 'hasOverloads' is set to false.
3147 * eg. If 'tthis" is mutable and there's only one mutable method.
3148 * 2. If there's two or more match candidates, but a candidate function will be
3150 * Returns the better match function but 'hasOverloads' is set to true.
3151 * eg. If 'tthis' is mutable, and there's both mutable and const methods,
3152 * the mutable method will be a better match.
3153 * 3. If there's two or more match candidates, but there's no better match,
3154 * Returns NULL and 'hasOverloads' is set to true to represent "ambiguous match".
3155 * eg. If 'tthis' is mutable, and there's two or more mutable methods.
3156 * 4. If there's no candidates, it's "no match" and returns NULL with error report.
3157 * e.g. If 'tthis' is const but there's no const methods.
3159 FuncDeclaration
*FuncDeclaration::overloadModMatch(Loc loc
, Type
*tthis
, bool &hasOverloads
)
3161 //printf("FuncDeclaration::overloadModMatch('%s')\n", toChars());
3163 memset(&m
, 0, sizeof(m
));
3164 m
.last
= MATCHnomatch
;
3171 static int fp(void *param
, Dsymbol
*s
)
3173 if (FuncDeclaration
*fd
= s
->isFuncDeclaration())
3174 return ((ParamMod
*)param
)->fp(fd
);
3177 int fp(FuncDeclaration
*f
)
3179 if (f
== m
->lastf
) // skip duplicates
3183 TypeFunction
*tf
= f
->type
->toTypeFunction();
3184 //printf("tf = %s\n", tf->toChars());
3187 if (tthis
) // non-static functions are preferred than static ones
3190 match
= f
->isCtorDeclaration() ? MATCHexact
: MODmethodConv(tthis
->mod
, tf
->mod
);
3192 match
= MATCHconst
; // keep static funciton in overload candidates
3194 else // static functions are preferred than non-static ones
3197 match
= MATCHconvert
;
3201 if (match
!= MATCHnomatch
)
3203 if (match
> m
->last
) goto LfIsBetter
;
3204 if (match
< m
->last
) goto LlastIsBetter
;
3206 /* See if one of the matches overrides the other.
3208 if (m
->lastf
->overrides(f
)) goto LlastIsBetter
;
3209 if (f
->overrides(m
->lastf
)) goto LfIsBetter
;
3211 //printf("\tambiguous\n");
3217 //printf("\tlastbetter\n");
3218 m
->count
++; // count up
3222 //printf("\tisbetter\n");
3223 if (m
->last
<= MATCHconvert
)
3225 // clear last secondary matching
3231 m
->count
++; // count up
3240 overloadApply(this, &p
, &ParamMod::fp
);
3242 if (m
.count
== 1) // exact match
3244 hasOverloads
= false;
3246 else if (m
.count
> 1) // better or ambiguous match
3248 hasOverloads
= true;
3252 hasOverloads
= true;
3253 TypeFunction
*tf
= this->type
->toTypeFunction();
3255 assert(!MODimplicitConv(tthis
->mod
, tf
->mod
)); // modifier mismatch
3257 OutBuffer thisBuf
, funcBuf
;
3258 MODMatchToBuffer(&thisBuf
, tthis
->mod
, tf
->mod
);
3259 MODMatchToBuffer(&funcBuf
, tf
->mod
, tthis
->mod
);
3260 ::error(loc
, "%smethod %s is not callable using a %sobject",
3261 funcBuf
.peekString(), this->toPrettyChars(), thisBuf
.peekString());
3268 /********************************************
3269 * Returns true if function was declared
3270 * directly or indirectly in a unittest block
3272 bool FuncDeclaration::inUnittest()
3277 if (f
->isUnitTestDeclaration())
3285 /********************************************
3286 * find function template root in overload list
3289 TemplateDeclaration
*FuncDeclaration::findTemplateDeclRoot()
3291 FuncDeclaration
*f
= this;
3292 while (f
&& f
->overnext
)
3294 //printf("f->overnext = %p %s\n", f->overnext, f->overnext->toChars());
3295 TemplateDeclaration
*td
= f
->overnext
->isTemplateDeclaration();
3298 f
= f
->overnext
->isFuncDeclaration();
3303 /*************************************
3304 * Determine partial specialization order of 'this' vs g.
3305 * This is very similar to TemplateDeclaration::leastAsSpecialized().
3307 * match 'this' is at least as specialized as g
3308 * 0 g is more specialized than 'this'
3311 MATCH
FuncDeclaration::leastAsSpecialized(FuncDeclaration
*g
)
3313 /* This works by calling g() with f()'s parameters, and
3314 * if that is possible, then f() is at least as specialized
3318 TypeFunction
*tf
= type
->toTypeFunction();
3319 TypeFunction
*tg
= g
->type
->toTypeFunction();
3320 size_t nfparams
= Parameter::dim(tf
->parameters
);
3322 /* If both functions have a 'this' pointer, and the mods are not
3323 * the same and g's is not const, then this is less specialized.
3325 if (needThis() && g
->needThis() && tf
->mod
!= tg
->mod
)
3327 if (isCtorDeclaration())
3329 if (!MODimplicitConv(tg
->mod
, tf
->mod
))
3330 return MATCHnomatch
;
3334 if (!MODimplicitConv(tf
->mod
, tg
->mod
))
3335 return MATCHnomatch
;
3339 /* Create a dummy array of arguments out of the parameters to f()
3342 args
.setDim(nfparams
);
3343 for (size_t u
= 0; u
< nfparams
; u
++)
3345 Parameter
*p
= Parameter::getNth(tf
->parameters
, u
);
3347 if (p
->storageClass
& (STCref
| STCout
))
3349 e
= new IdentifierExp(Loc(), p
->ident
);
3353 e
= p
->type
->defaultInitLiteral(Loc());
3357 MATCH m
= (MATCH
) tg
->callMatch(NULL
, &args
, 1);
3358 if (m
> MATCHnomatch
)
3360 /* A variadic parameter list is less specialized than a
3363 if (tf
->varargs
&& !tg
->varargs
)
3364 goto L1
; // less specialized
3369 return MATCHnomatch
;
3372 /// Walk through candidate template overloads and print them in the diagnostics.
3373 struct TemplateCandidateWalker
3376 int numToDisplay
; // max num of overloads to print (-v overrides this).
3378 /// Count template overloads.
3383 static int fp(void *param
, Dsymbol
*)
3385 CountWalker
*p
= (CountWalker
*)param
;
3386 ++(p
->numOverloads
);
3391 static int fp(void *param
, Dsymbol
*s
)
3393 TemplateDeclaration
*t
= s
->isTemplateDeclaration();
3396 TemplateCandidateWalker
*p
= (TemplateCandidateWalker
*)param
;
3398 ::errorSupplemental(t
->loc
, "%s", t
->toPrettyChars());
3400 if (!global
.params
.verbose
&& --(p
->numToDisplay
) == 0 && t
->overnext
)
3402 // Too many overloads to sensibly display.
3403 // Just show count of remaining overloads.
3405 cw
.numOverloads
= 0;
3406 overloadApply(t
->overnext
, &cw
, &CountWalker::fp
);
3408 if (cw
.numOverloads
> 0)
3409 ::errorSupplemental(p
->loc
, "... (%d more, -v to show) ...", cw
.numOverloads
);
3411 return 1; // stop iterating
3418 /// Walk through candidate template overloads and print them in the diagnostics.
3419 struct FuncCandidateWalker
3422 int numToDisplay
; // max num of overloads to print (-v overrides this).
3424 /// Count function overloads.
3429 static int fp(void *param
, Dsymbol
*)
3431 CountWalker
*p
= (CountWalker
*)param
;
3432 ++(p
->numOverloads
);
3437 static int fp(void *param
, Dsymbol
*s
)
3439 FuncDeclaration
*fd
= s
->isFuncDeclaration();
3440 TemplateDeclaration
*td
= s
->isTemplateDeclaration();
3443 if (fd
->errors
|| fd
->type
->ty
== Terror
)
3446 TypeFunction
*tf
= (TypeFunction
*)fd
->type
;
3448 ::errorSupplemental(fd
->loc
, "%s%s", fd
->toPrettyChars(),
3449 parametersTypeToChars(tf
->parameters
, tf
->varargs
));
3453 ::errorSupplemental(td
->loc
, "%s", td
->toPrettyChars());
3456 FuncCandidateWalker
*p
= (FuncCandidateWalker
*)param
;
3457 if (global
.params
.verbose
|| --(p
->numToDisplay
) != 0 || !fd
)
3460 // Too many overloads to sensibly display.
3462 cw
.numOverloads
= 0;
3463 overloadApply(fd
->overnext
, &cw
, &CountWalker::fp
);
3465 if (cw
.numOverloads
> 0)
3466 ::errorSupplemental(p
->loc
, "... (%d more, -v to show) ...", cw
.numOverloads
);
3468 return 1; // stop iterating
3472 /*******************************************
3473 * Given a symbol that could be either a FuncDeclaration or
3474 * a function template, resolve it to a function symbol.
3475 * loc instantiation location
3476 * sc instantiation scope
3477 * tiargs initial list of template arguments
3478 * tthis if !NULL, the 'this' pointer argument
3479 * fargs arguments to function
3480 * flags 1: do not issue error message on no match, just return NULL
3481 * 2: overloadResolve only
3484 FuncDeclaration
*resolveFuncCall(Loc loc
, Scope
*sc
, Dsymbol
*s
,
3485 Objects
*tiargs
, Type
*tthis
, Expressions
*fargs
, int flags
)
3488 return NULL
; // no match
3490 if ((tiargs
&& arrayObjectIsError(tiargs
)) ||
3491 (fargs
&& arrayObjectIsError((Objects
*)fargs
)))
3497 memset(&m
, 0, sizeof(m
));
3498 m
.last
= MATCHnomatch
;
3500 functionResolve(&m
, s
, loc
, sc
, tiargs
, tthis
, fargs
);
3502 if (m
.last
> MATCHnomatch
&& m
.lastf
)
3504 if (m
.count
== 1) // exactly one match
3507 m
.lastf
->functionSemantic();
3510 if ((flags
& 2) && !tthis
&& m
.lastf
->needThis())
3516 /* Failed to find a best match.
3517 * Do nothing or print error.
3519 if (m
.last
<= MATCHnomatch
)
3521 // error was caused on matched function
3525 // if do not print error messages
3527 return NULL
; // no match
3530 FuncDeclaration
*fd
= s
->isFuncDeclaration();
3531 OverDeclaration
*od
= s
->isOverDeclaration();
3532 TemplateDeclaration
*td
= s
->isTemplateDeclaration();
3533 if (td
&& td
->funcroot
)
3534 s
= fd
= td
->funcroot
;
3536 OutBuffer tiargsBuf
;
3537 arrayObjectsToBuffer(&tiargsBuf
, tiargs
);
3540 fargsBuf
.writeByte('(');
3541 argExpTypesToCBuffer(&fargsBuf
, fargs
);
3542 fargsBuf
.writeByte(')');
3544 tthis
->modToBuffer(&fargsBuf
);
3546 const int numOverloadsDisplay
= 5; // sensible number to display
3548 if (!m
.lastf
&& !(flags
& 1)) // no match
3550 if (td
&& !fd
) // all of overloads are templates
3552 ::error(loc
, "%s %s.%s cannot deduce function from argument types !(%s)%s, candidates are:",
3553 td
->kind(), td
->parent
->toPrettyChars(), td
->ident
->toChars(),
3554 tiargsBuf
.peekString(), fargsBuf
.peekString());
3556 // Display candidate templates (even if there are no multiple overloads)
3557 TemplateCandidateWalker tcw
;
3559 tcw
.numToDisplay
= numOverloadsDisplay
;
3560 overloadApply(td
, &tcw
, &TemplateCandidateWalker::fp
);
3564 ::error(loc
, "none of the overloads of '%s' are callable using argument types !(%s)%s",
3565 od
->ident
->toChars(), tiargsBuf
.peekString(), fargsBuf
.peekString());
3571 bool hasOverloads
= fd
->overnext
!= NULL
;
3572 TypeFunction
*tf
= fd
->type
->toTypeFunction();
3573 if (tthis
&& !MODimplicitConv(tthis
->mod
, tf
->mod
)) // modifier mismatch
3575 OutBuffer thisBuf
, funcBuf
;
3576 MODMatchToBuffer(&thisBuf
, tthis
->mod
, tf
->mod
);
3577 MODMatchToBuffer(&funcBuf
, tf
->mod
, tthis
->mod
);
3579 ::error(loc
, "none of the overloads of '%s' are callable using a %sobject, candidates are:",
3580 fd
->ident
->toChars(), thisBuf
.peekString());
3582 ::error(loc
, "%smethod %s is not callable using a %sobject",
3583 funcBuf
.peekString(), fd
->toPrettyChars(), thisBuf
.peekString());
3587 //printf("tf = %s, args = %s\n", tf->deco, (*fargs)[0]->type->deco);
3589 ::error(loc
, "none of the overloads of '%s' are callable using argument types %s, candidates are:",
3590 fd
->ident
->toChars(), fargsBuf
.peekString());
3592 fd
->error(loc
, "%s%s is not callable using argument types %s",
3593 parametersTypeToChars(tf
->parameters
, tf
->varargs
),
3595 fargsBuf
.peekString());
3598 // Display candidate functions
3601 FuncCandidateWalker fcw
;
3603 fcw
.numToDisplay
= numOverloadsDisplay
;
3604 overloadApply(fd
, &fcw
, &FuncCandidateWalker::fp
);
3610 TypeFunction
*tf1
= m
.lastf
->type
->toTypeFunction();
3611 TypeFunction
*tf2
= m
.nextf
->type
->toTypeFunction();
3612 const char *lastprms
= parametersTypeToChars(tf1
->parameters
, tf1
->varargs
);
3613 const char *nextprms
= parametersTypeToChars(tf2
->parameters
, tf2
->varargs
);
3614 ::error(loc
, "%s.%s called with argument types %s matches both:\n"
3615 "%s: %s%s\nand:\n%s: %s%s",
3616 s
->parent
->toPrettyChars(), s
->ident
->toChars(),
3617 fargsBuf
.peekString(),
3618 m
.lastf
->loc
.toChars(), m
.lastf
->toPrettyChars(), lastprms
,
3619 m
.nextf
->loc
.toChars(), m
.nextf
->toPrettyChars(), nextprms
);
3624 /********************************
3625 * Labels are in a separate scope, one per function.
3628 LabelDsymbol
*FuncDeclaration::searchLabel(Identifier
*ident
)
3632 labtab
= new DsymbolTable(); // guess we need one
3634 s
= labtab
->lookup(ident
);
3637 s
= new LabelDsymbol(ident
);
3640 return (LabelDsymbol
*)s
;
3643 /*****************************************
3644 * Determine lexical level difference from 'this' to nested function 'fd'.
3645 * Error if this cannot call fd.
3648 * >0 decrease nesting by number
3649 * -1 increase nesting by 1 (fd is nested within 'this')
3653 int FuncDeclaration::getLevel(Loc loc
, Scope
*sc
, FuncDeclaration
*fd
)
3659 //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
3660 fdparent
= fd
->toParent2();
3661 if (fdparent
== this)
3665 while (fd
!= s
&& fdparent
!= s
->toParent2())
3667 //printf("\ts = %s, '%s'\n", s->kind(), s->toChars());
3668 FuncDeclaration
*thisfd
= s
->isFuncDeclaration();
3671 if (!thisfd
->isNested() && !thisfd
->vthis
&& !sc
->intypeof
)
3676 AggregateDeclaration
*thiscd
= s
->isAggregateDeclaration();
3679 /* AggregateDeclaration::isNested returns true only when
3680 * it has a hidden pointer.
3681 * But, calling the function belongs unrelated lexical scope
3682 * is still allowed inside typeof.
3684 * struct Map(alias fun) {
3685 * typeof({ return fun(); }) RetType;
3686 * // No member function makes Map struct 'not nested'.
3689 if (!thiscd
->isNested() && !sc
->intypeof
)
3703 // Don't give error if in template constraint
3704 if (!(sc
->flags
& SCOPEconstraint
))
3706 const char *xstatic
= isStatic() ? "static " : "";
3707 // better diagnostics for static functions
3708 ::error(loc
, "%s%s %s cannot access frame of function %s",
3709 xstatic
, kind(), toPrettyChars(), fd
->toPrettyChars());
3715 const char *FuncDeclaration::toPrettyChars(bool QualifyTypes
)
3720 return Dsymbol::toPrettyChars(QualifyTypes
);
3723 /** for diagnostics, e.g. 'int foo(int x, int y) pure' */
3724 const char *FuncDeclaration::toFullSignature()
3727 functionToBufferWithIdent(type
->toTypeFunction(), &buf
, toChars());
3728 return buf
.extractString();
3731 bool FuncDeclaration::isMain()
3733 return ident
== Id::main
&&
3734 linkage
!= LINKc
&& !isMember() && !isNested();
3737 bool FuncDeclaration::isCMain()
3739 return ident
== Id::main
&&
3740 linkage
== LINKc
&& !isMember() && !isNested();
3743 bool FuncDeclaration::isWinMain()
3745 //printf("FuncDeclaration::isWinMain() %s\n", toChars());
3746 return ident
== Id::WinMain
&&
3747 linkage
!= LINKc
&& !isMember();
3750 bool FuncDeclaration::isDllMain()
3752 return ident
== Id::DllMain
&&
3753 linkage
!= LINKc
&& !isMember();
3756 bool FuncDeclaration::isExport() const
3758 return protection
.kind
== PROTexport
;
3761 bool FuncDeclaration::isImportedSymbol() const
3763 //printf("isImportedSymbol()\n");
3764 //printf("protection = %d\n", protection);
3765 return (protection
.kind
== PROTexport
) && !fbody
;
3768 // Determine if function goes into virtual function pointer table
3770 bool FuncDeclaration::isVirtual()
3772 if (toAliasFunc() != this)
3773 return toAliasFunc()->isVirtual();
3775 Dsymbol
*p
= toParent();
3776 return isMember() &&
3777 !(isStatic() || protection
.kind
== PROTprivate
|| protection
.kind
== PROTpackage
) &&
3778 p
->isClassDeclaration() &&
3779 !(p
->isInterfaceDeclaration() && isFinalFunc());
3782 // Determine if a function is pedantically virtual
3784 bool FuncDeclaration::isVirtualMethod()
3786 if (toAliasFunc() != this)
3787 return toAliasFunc()->isVirtualMethod();
3789 //printf("FuncDeclaration::isVirtualMethod() %s\n", toChars());
3792 // If it's a final method, and does not override anything, then it is not virtual
3793 if (isFinalFunc() && foverrides
.dim
== 0)
3800 bool FuncDeclaration::isFinalFunc()
3802 if (toAliasFunc() != this)
3803 return toAliasFunc()->isFinalFunc();
3805 ClassDeclaration
*cd
;
3806 return isMember() &&
3807 (Declaration::isFinal() ||
3808 ((cd
= toParent()->isClassDeclaration()) != NULL
&& cd
->storage_class
& STCfinal
));
3811 bool FuncDeclaration::isCodeseg() const
3813 return true; // functions are always in the code segment
3816 bool FuncDeclaration::isOverloadable()
3818 return true; // functions can be overloaded
3821 PURE
FuncDeclaration::isPure()
3823 //printf("FuncDeclaration::isPure() '%s'\n", toChars());
3824 TypeFunction
*tf
= type
->toTypeFunction();
3825 if (flags
& FUNCFLAGpurityInprocess
)
3827 if (tf
->purity
== PUREfwdref
)
3829 PURE purity
= tf
->purity
;
3830 if (purity
> PUREweak
&& isNested())
3832 if (purity
> PUREweak
&& needThis())
3834 // The attribute of the 'this' reference affects purity strength
3835 if (type
->mod
& MODimmutable
)
3837 else if (type
->mod
& (MODconst
| MODwild
) && purity
>= PUREconst
)
3842 tf
->purity
= purity
;
3843 // ^ This rely on the current situation that every FuncDeclaration has a
3844 // unique TypeFunction.
3848 PURE
FuncDeclaration::isPureBypassingInference()
3850 if (flags
& FUNCFLAGpurityInprocess
)
3856 /**************************************
3857 * The function is doing something impure,
3858 * so mark it as impure.
3859 * If there's a purity error, return true.
3861 bool FuncDeclaration::setImpure()
3863 if (flags
& FUNCFLAGpurityInprocess
)
3865 flags
&= ~FUNCFLAGpurityInprocess
;
3867 fes
->func
->setImpure();
3874 bool FuncDeclaration::isSafe()
3876 if (flags
& FUNCFLAGsafetyInprocess
)
3878 return type
->toTypeFunction()->trust
== TRUSTsafe
;
3881 bool FuncDeclaration::isSafeBypassingInference()
3883 return !(flags
& FUNCFLAGsafetyInprocess
) && isSafe();
3886 bool FuncDeclaration::isTrusted()
3888 if (flags
& FUNCFLAGsafetyInprocess
)
3890 return type
->toTypeFunction()->trust
== TRUSTtrusted
;
3893 /**************************************
3894 * The function is doing something unsave,
3895 * so mark it as unsafe.
3896 * If there's a safe error, return true.
3898 bool FuncDeclaration::setUnsafe()
3900 if (flags
& FUNCFLAGsafetyInprocess
)
3902 flags
&= ~FUNCFLAGsafetyInprocess
;
3903 type
->toTypeFunction()->trust
= TRUSTsystem
;
3905 fes
->func
->setUnsafe();
3912 bool FuncDeclaration::isNogc()
3914 if (flags
& FUNCFLAGnogcInprocess
)
3916 return type
->toTypeFunction()->isnogc
;
3919 bool FuncDeclaration::isNogcBypassingInference()
3921 return !(flags
& FUNCFLAGnogcInprocess
) && isNogc();
3924 /**************************************
3925 * The function is doing something that may allocate with the GC,
3926 * so mark it as not nogc (not no-how).
3928 * true if function is marked as @nogc, meaning a user error occurred
3930 bool FuncDeclaration::setGC()
3932 if (flags
& FUNCFLAGnogcInprocess
)
3934 flags
&= ~FUNCFLAGnogcInprocess
;
3935 type
->toTypeFunction()->isnogc
= false;
3944 /**************************************
3945 * Returns an indirect type one step from t.
3948 Type
*getIndirection(Type
*t
)
3950 t
= t
->baseElemOf();
3951 if (t
->ty
== Tarray
|| t
->ty
== Tpointer
)
3952 return t
->nextOf()->toBasetype();
3953 if (t
->ty
== Taarray
|| t
->ty
== Tclass
)
3955 if (t
->ty
== Tstruct
)
3956 return t
->hasPointers() ? t
: NULL
; // TODO
3958 // should consider TypeDelegate?
3962 /**************************************
3963 * Returns true if memory reachable through a reference B to a value of type tb,
3964 * which has been constructed with a reference A to a value of type ta
3965 * available, can alias memory reachable from A based on the types involved
3966 * (either directly or via any number of indirections).
3968 * Note that this relation is not symmetric in the two arguments. For example,
3969 * a const(int) reference can point to a pre-existing int, but not the other
3972 bool traverseIndirections(Type
*ta
, Type
*tb
, void *p
= NULL
, bool reversePass
= false)
3982 if (source
->constConv(target
))
3984 else if (target
->ty
== Tvoid
&& MODimplicitConv(source
->mod
, target
->mod
))
3987 // No direct match, so try breaking up one of the types (starting with tb).
3988 Type
*tbb
= tb
->toBasetype()->baseElemOf();
3990 return traverseIndirections(ta
, tbb
, p
, reversePass
);
3992 // context date to detect circular look up
3998 Ctxt
*ctxt
= (Ctxt
*)p
;
4000 if (tb
->ty
== Tclass
|| tb
->ty
== Tstruct
)
4002 for (Ctxt
*c
= ctxt
; c
; c
= c
->prev
)
4003 if (tb
== c
->type
) return false;
4008 AggregateDeclaration
*sym
= tb
->toDsymbol(NULL
)->isAggregateDeclaration();
4009 for (size_t i
= 0; i
< sym
->fields
.dim
; i
++)
4011 VarDeclaration
*v
= sym
->fields
[i
];
4012 Type
*tprmi
= v
->type
->addMod(tb
->mod
);
4013 //printf("\ttb = %s, tprmi = %s\n", tb->toChars(), tprmi->toChars());
4014 if (traverseIndirections(ta
, tprmi
, &c
, reversePass
))
4018 else if (tb
->ty
== Tarray
|| tb
->ty
== Taarray
|| tb
->ty
== Tpointer
)
4020 Type
*tind
= tb
->nextOf();
4021 if (traverseIndirections(ta
, tind
, ctxt
, reversePass
))
4024 else if (tb
->hasPointers())
4026 // FIXME: function pointer/delegate types should be considered.
4030 // Still no match, so try breaking up ta if we have note done so yet.
4032 return traverseIndirections(tb
, ta
, ctxt
, true);
4037 /********************************************
4038 * Returns true if the function return value has no indirection
4039 * which comes from the parameters.
4042 bool FuncDeclaration::isolateReturn()
4044 TypeFunction
*tf
= type
->toTypeFunction();
4047 Type
*treti
= tf
->next
;
4048 treti
= tf
->isref
? treti
: getIndirection(treti
);
4050 return true; // target has no mutable indirection
4051 return parametersIntersect(treti
);
4054 /********************************************
4055 * Returns true if an object typed t can have indirections
4056 * which come from the parameters.
4059 bool FuncDeclaration::parametersIntersect(Type
*t
)
4062 if (!isPureBypassingInference() || isNested())
4065 TypeFunction
*tf
= type
->toTypeFunction();
4067 //printf("parametersIntersect(%s) t = %s\n", tf->toChars(), t->toChars());
4069 size_t dim
= Parameter::dim(tf
->parameters
);
4070 for (size_t i
= 0; i
< dim
; i
++)
4072 Parameter
*fparam
= Parameter::getNth(tf
->parameters
, i
);
4075 Type
*tprmi
= (fparam
->storageClass
& (STClazy
| STCout
| STCref
))
4076 ? fparam
->type
: getIndirection(fparam
->type
);
4078 continue; // there is no mutable indirection
4080 //printf("\t[%d] tprmi = %d %s\n", i, tprmi->ty, tprmi->toChars());
4081 if (traverseIndirections(tprmi
, t
))
4084 if (AggregateDeclaration
*ad
= isCtorDeclaration() ? NULL
: isThis())
4086 Type
*tthis
= ad
->getType()->addMod(tf
->mod
);
4087 //printf("\ttthis = %s\n", tthis->toChars());
4088 if (traverseIndirections(tthis
, t
))
4095 /****************************************
4096 * Determine if function needs a static frame pointer.
4098 * `true` if function is really nested within other function.
4100 * If isNested() returns true, isThis() should return false.
4102 bool FuncDeclaration::isNested()
4104 FuncDeclaration
*f
= toAliasFunc();
4105 //printf("\ttoParent2() = '%s'\n", f->toParent2()->toChars());
4106 return ((f
->storage_class
& STCstatic
) == 0) &&
4107 (f
->linkage
== LINKd
) &&
4108 (f
->toParent2()->isFuncDeclaration() != NULL
);
4111 /****************************************
4112 * Determine if function is a non-static member function
4113 * that has an implicit 'this' expression.
4115 * The aggregate it is a member of, or null.
4117 * If isThis() returns true, isNested() should return false.
4119 AggregateDeclaration
*FuncDeclaration::isThis()
4121 //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
4122 AggregateDeclaration
*ad
= (storage_class
& STCstatic
) ? NULL
: isMember2();
4123 //printf("-FuncDeclaration::isThis() %p\n", ad);
4127 bool FuncDeclaration::needThis()
4129 //printf("FuncDeclaration::needThis() '%s'\n", toChars());
4130 return toAliasFunc()->isThis() != NULL
;
4133 bool FuncDeclaration::addPreInvariant()
4135 AggregateDeclaration
*ad
= isThis();
4136 ClassDeclaration
*cd
= ad
? ad
->isClassDeclaration() : NULL
;
4137 return (ad
&& !(cd
&& cd
->isCPPclass()) &&
4138 global
.params
.useInvariants
&&
4139 (protection
.kind
== PROTprotected
|| protection
.kind
== PROTpublic
|| protection
.kind
== PROTexport
) &&
4143 bool FuncDeclaration::addPostInvariant()
4145 AggregateDeclaration
*ad
= isThis();
4146 ClassDeclaration
*cd
= ad
? ad
->isClassDeclaration() : NULL
;
4147 return (ad
&& !(cd
&& cd
->isCPPclass()) &&
4149 global
.params
.useInvariants
&&
4150 (protection
.kind
== PROTprotected
|| protection
.kind
== PROTpublic
|| protection
.kind
== PROTexport
) &&
4154 /********************************************************
4155 * Generate Expression to call the invariant.
4157 * ad aggregate with the invariant
4158 * vthis variable with 'this'
4159 * direct call invariant directly
4161 * void expression that calls the invariant
4163 Expression
*addInvariant(Loc loc
, Scope
*sc
, AggregateDeclaration
*ad
, VarDeclaration
*vthis
, bool direct
)
4165 Expression
*e
= NULL
;
4168 // Call invariant directly only if it exists
4169 FuncDeclaration
*inv
= ad
->inv
;
4170 ClassDeclaration
*cd
= ad
->isClassDeclaration();
4182 // Workaround for bugzilla 13394: For the correct mangling,
4183 // run attribute inference on inv if needed.
4184 inv
->functionSemantic();
4187 //e = new DsymbolExp(Loc(), inv);
4188 //e = new CallExp(Loc(), e);
4189 //e = e->semantic(sc2);
4191 /* Bugzilla 13113: Currently virtual invariant calls completely
4192 * bypass attribute enforcement.
4193 * Change the behavior of pre-invariant call by following it.
4195 e
= new ThisExp(Loc());
4196 e
->type
= vthis
->type
;
4197 e
= new DotVarExp(Loc(), e
, inv
, false);
4198 e
->type
= inv
->type
;
4199 e
= new CallExp(Loc(), e
);
4200 e
->type
= Type::tvoid
;
4206 // Workaround for bugzilla 13394: For the correct mangling,
4207 // run attribute inference on inv if needed.
4208 if (ad
->isStructDeclaration() && ad
->inv
)
4209 ad
->inv
->functionSemantic();
4212 // Call invariant virtually
4213 Expression
*v
= new ThisExp(Loc());
4214 v
->type
= vthis
->type
;
4215 if (ad
->isStructDeclaration())
4217 e
= new StringExp(Loc(), const_cast<char *>("null this"));
4218 e
= new AssertExp(loc
, v
, e
);
4219 e
= semantic(e
, sc
);
4224 /**********************************
4225 * Generate a FuncDeclaration for a runtime library function.
4228 FuncDeclaration
*FuncDeclaration::genCfunc(Parameters
*fparams
, Type
*treturn
, const char *name
, StorageClass stc
)
4230 return genCfunc(fparams
, treturn
, Identifier::idPool(name
), stc
);
4233 FuncDeclaration
*FuncDeclaration::genCfunc(Parameters
*fparams
, Type
*treturn
, Identifier
*id
, StorageClass stc
)
4235 FuncDeclaration
*fd
;
4238 static DsymbolTable
*st
= NULL
;
4240 //printf("genCfunc(name = '%s')\n", id->toChars());
4241 //printf("treturn\n\t"); treturn->print();
4243 // See if already in table
4245 st
= new DsymbolTable();
4249 fd
= s
->isFuncDeclaration();
4251 assert(fd
->type
->nextOf()->equals(treturn
));
4255 tf
= new TypeFunction(fparams
, treturn
, 0, LINKc
, stc
);
4256 fd
= new FuncDeclaration(Loc(), Loc(), id
, STCstatic
, tf
);
4257 fd
->protection
= Prot(PROTpublic
);
4258 fd
->linkage
= LINKc
;
4266 * Check parameters and return type of D main() function.
4267 * Issue error messages.
4269 void FuncDeclaration::checkDmain()
4271 TypeFunction
*tf
= type
->toTypeFunction();
4272 const size_t nparams
= Parameter::dim(tf
->parameters
);
4273 bool argerr
= false;
4276 Parameter
*fparam0
= Parameter::getNth(tf
->parameters
, 0);
4277 Type
*t
= fparam0
->type
->toBasetype();
4278 if (t
->ty
!= Tarray
||
4279 t
->nextOf()->ty
!= Tarray
||
4280 t
->nextOf()->nextOf()->ty
!= Tchar
||
4281 fparam0
->storageClass
& (STCout
| STCref
| STClazy
))
4288 error("must return int or void");
4289 else if (tf
->nextOf()->ty
!= Tint32
&& tf
->nextOf()->ty
!= Tvoid
)
4290 error("must return int or void, not %s", tf
->nextOf()->toChars());
4291 else if (tf
->varargs
|| nparams
>= 2 || argerr
)
4292 error("parameters must be main() or main(string[] args)");
4295 const char *FuncDeclaration::kind() const
4297 return generated
? "generated function" : "function";
4300 /*********************************************
4301 * In the current function, we are calling 'this' function.
4302 * 1. Check to see if the current function can call 'this' function, issue error if not.
4303 * 2. If the current function is not the parent of 'this' function, then add
4304 * the current function to the list of siblings of 'this' function.
4305 * 3. If the current function is a literal, and it's accessing an uplevel scope,
4306 * then mark it as a delegate.
4307 * Returns true if error occurs.
4309 bool FuncDeclaration::checkNestedReference(Scope
*sc
, Loc loc
)
4311 //printf("FuncDeclaration::checkNestedReference() %s\n", toPrettyChars());
4313 if (FuncLiteralDeclaration
*fld
= this->isFuncLiteralDeclaration())
4315 if (fld
->tok
== TOKreserved
)
4317 fld
->tok
= TOKfunction
;
4322 if (!parent
|| parent
== sc
->parent
)
4324 if (ident
== Id::require
|| ident
== Id::ensure
)
4326 if (!isThis() && !isNested())
4329 // The current function
4330 FuncDeclaration
*fdthis
= sc
->parent
->isFuncDeclaration();
4332 return false; // out of function scope
4334 Dsymbol
*p
= toParent2();
4336 // Function literals from fdthis to p must be delegates
4337 checkNestedRef(fdthis
, p
);
4341 // The function that this function is in
4342 FuncDeclaration
*fdv
= p
->isFuncDeclaration();
4348 //printf("this = %s in [%s]\n", this->toChars(), this->loc.toChars());
4349 //printf("fdv = %s in [%s]\n", fdv->toChars(), fdv->loc.toChars());
4350 //printf("fdthis = %s in [%s]\n", fdthis->toChars(), fdthis->loc.toChars());
4352 // Add this function to the list of those which called us
4356 for (size_t i
= 0; i
< siblingCallers
.dim
; ++i
)
4358 if (siblingCallers
[i
] == fdthis
)
4363 //printf("\tadding sibling %s\n", fdthis->toPrettyChars());
4364 if (!sc
->intypeof
&& !(sc
->flags
& SCOPEcompile
))
4365 siblingCallers
.push(fdthis
);
4369 int lv
= fdthis
->getLevel(loc
, sc
, fdv
);
4371 return true; // error
4373 return false; // downlevel call
4375 return false; // same level call
4381 /* For all functions between outerFunc and f, mark them as needing
4384 void markAsNeedingClosure(Dsymbol
*f
, FuncDeclaration
*outerFunc
)
4386 for (Dsymbol
*sx
= f
; sx
&& sx
!= outerFunc
; sx
= sx
->parent
)
4388 FuncDeclaration
*fy
= sx
->isFuncDeclaration();
4389 if (fy
&& fy
->closureVars
.dim
)
4391 /* fy needs a closure if it has closureVars[],
4392 * because the frame pointer in the closure will be accessed.
4394 fy
->requiresClosure
= true;
4400 /* Given a nested function f inside a function outerFunc, check
4401 * if any sibling callers of f have escaped. If so, mark
4402 * all the enclosing functions as needing closures.
4403 * Return true if any closures were detected.
4404 * This is recursive: we need to check the callers of our siblings.
4405 * Note that nested functions can only call lexically earlier nested
4406 * functions, so loops are impossible.
4408 bool checkEscapingSiblings(FuncDeclaration
*f
, FuncDeclaration
*outerFunc
, void *p
= NULL
)
4417 ps
.p
= (PrevSibling
*)p
;
4420 //printf("checkEscapingSiblings(f = %s, outerfunc = %s)\n", f->toChars(), outerFunc->toChars());
4421 bool bAnyClosures
= false;
4422 for (size_t i
= 0; i
< f
->siblingCallers
.dim
; ++i
)
4424 FuncDeclaration
*g
= f
->siblingCallers
[i
];
4425 if (g
->isThis() || g
->tookAddressOf
)
4427 markAsNeedingClosure(g
, outerFunc
);
4428 bAnyClosures
= true;
4431 PrevSibling
*prev
= (PrevSibling
*)p
;
4436 bAnyClosures
|= checkEscapingSiblings(g
, outerFunc
, &ps
);
4444 //printf("\t%d\n", bAnyClosures);
4445 return bAnyClosures
;
4449 /*******************************
4450 * Look at all the variables in this function that are referenced
4451 * by nested functions, and determine if a closure needs to be
4455 bool FuncDeclaration::needsClosure()
4457 /* Need a closure for all the closureVars[] if any of the
4458 * closureVars[] are accessed by a
4459 * function that escapes the scope of this function.
4460 * We take the conservative approach and decide that a function needs
4462 * 1) is a virtual function
4463 * 2) has its address taken
4464 * 3) has a parent that escapes
4465 * 4) calls another nested function that needs a closure
4467 * Note that since a non-virtual function can be called by
4468 * a virtual one, if that non-virtual function accesses a closure
4469 * var, the closure still has to be taken. Hence, we check for isThis()
4470 * instead of isVirtual(). (thanks to David Friedman)
4472 * When the function returns a local struct or class, `requiresClosure`
4473 * is already set to `true` upon entering this function when the
4474 * struct/class refers to a local variable and a closure is needed.
4477 //printf("FuncDeclaration::needsClosure() %s\n", toChars());
4479 if (requiresClosure
)
4482 for (size_t i
= 0; i
< closureVars
.dim
; i
++)
4484 VarDeclaration
*v
= closureVars
[i
];
4485 //printf("\tv = %s\n", v->toChars());
4487 for (size_t j
= 0; j
< v
->nestedrefs
.dim
; j
++)
4489 FuncDeclaration
*f
= v
->nestedrefs
[j
];
4492 //printf("\t\tf = %s, isVirtual=%d, isThis=%p, tookAddressOf=%d\n", f->toChars(), f->isVirtual(), f->isThis(), f->tookAddressOf);
4494 /* Look to see if f escapes. We consider all parents of f within
4495 * this, and also all siblings which call f; if any of them escape,
4497 * Mark all affected functions as requiring closures.
4499 for (Dsymbol
*s
= f
; s
&& s
!= this; s
= s
->parent
)
4501 FuncDeclaration
*fx
= s
->isFuncDeclaration();
4504 if (fx
->isThis() || fx
->tookAddressOf
)
4506 //printf("\t\tfx = %s, isVirtual=%d, isThis=%p, tookAddressOf=%d\n", fx->toChars(), fx->isVirtual(), fx->isThis(), fx->tookAddressOf);
4508 /* Mark as needing closure any functions between this and f
4510 markAsNeedingClosure( (fx
== f
) ? fx
->parent
: fx
, this);
4512 requiresClosure
= true;
4515 /* We also need to check if any sibling functions that
4516 * called us, have escaped. This is recursive: we need
4517 * to check the callers of our siblings.
4519 if (checkEscapingSiblings(fx
, this))
4520 requiresClosure
= true;
4522 /* Bugzilla 12406: Iterate all closureVars to mark all descendant
4523 * nested functions that access to the closing context of this funciton.
4528 if (requiresClosure
)
4534 //printf("\tneeds closure\n");
4538 /***********************************************
4539 * Check that the function contains any closure.
4540 * If it's @nogc, report suitable errors.
4541 * This is mostly consistent with FuncDeclaration::needsClosure().
4544 * true if any errors occur.
4546 bool FuncDeclaration::checkClosure()
4548 if (!needsClosure())
4553 error("is @nogc yet allocates closures with the GC");
4554 if (global
.gag
) // need not report supplemental errors
4559 printGCUsage(loc
, "using closure causes GC allocation");
4564 for (size_t i
= 0; i
< closureVars
.dim
; i
++)
4566 VarDeclaration
*v
= closureVars
[i
];
4568 for (size_t j
= 0; j
< v
->nestedrefs
.dim
; j
++)
4570 FuncDeclaration
*f
= v
->nestedrefs
[j
];
4573 for (Dsymbol
*s
= f
; s
&& s
!= this; s
= s
->parent
)
4575 FuncDeclaration
*fx
= s
->isFuncDeclaration();
4578 if (fx
->isThis() || fx
->tookAddressOf
)
4580 if (checkEscapingSiblings(fx
, this))
4586 for (size_t k
= 0; ; k
++)
4591 ::errorSupplemental(f
->loc
, "%s closes over variable %s at %s",
4592 f
->toPrettyChars(), v
->toChars(), v
->loc
.toChars());
4605 /***********************************************
4606 * Determine if function's variables are referenced by a function
4610 bool FuncDeclaration::hasNestedFrameRefs()
4612 if (closureVars
.dim
)
4615 /* If a virtual function has contracts, assume its variables are referenced
4616 * by those contracts, even if they aren't. Because they might be referenced
4617 * by the overridden or overriding function's contracts.
4618 * This can happen because frequire and fensure are implemented as nested functions,
4619 * and they can be called directly by an overriding function and the overriding function's
4620 * context had better match, or Bugzilla 7335 will bite.
4622 if (fdrequire
|| fdensure
)
4625 if (foverrides
.dim
&& isVirtualMethod())
4627 for (size_t i
= 0; i
< foverrides
.dim
; i
++)
4629 FuncDeclaration
*fdv
= foverrides
[i
];
4630 if (fdv
->hasNestedFrameRefs())
4638 /*********************************************
4639 * Return the function's parameter list, and whether
4640 * it is variadic or not.
4643 Parameters
*FuncDeclaration::getParameters(int *pvarargs
)
4645 Parameters
*fparameters
= NULL
;
4650 TypeFunction
*fdtype
= type
->toTypeFunction();
4651 fparameters
= fdtype
->parameters
;
4652 fvarargs
= fdtype
->varargs
;
4655 *pvarargs
= fvarargs
;
4660 /****************************** FuncAliasDeclaration ************************/
4662 // Used as a way to import a set of functions from another scope into this one.
4664 FuncAliasDeclaration::FuncAliasDeclaration(Identifier
*ident
, FuncDeclaration
*funcalias
, bool hasOverloads
)
4665 : FuncDeclaration(funcalias
->loc
, funcalias
->endloc
, ident
,
4666 funcalias
->storage_class
, funcalias
->type
)
4668 assert(funcalias
!= this);
4669 this->funcalias
= funcalias
;
4671 this->hasOverloads
= hasOverloads
;
4674 if (FuncAliasDeclaration
*fad
= funcalias
->isFuncAliasDeclaration())
4675 this->hasOverloads
= fad
->hasOverloads
;
4678 { // for internal use
4679 assert(!funcalias
->isFuncAliasDeclaration());
4680 this->hasOverloads
= false;
4682 userAttribDecl
= funcalias
->userAttribDecl
;
4685 const char *FuncAliasDeclaration::kind() const
4687 return "function alias";
4690 FuncDeclaration
*FuncAliasDeclaration::toAliasFunc()
4692 return funcalias
->toAliasFunc();
4696 /****************************** FuncLiteralDeclaration ************************/
4698 FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc
, Loc endloc
, Type
*type
,
4699 TOK tok
, ForeachStatement
*fes
, Identifier
*id
)
4700 : FuncDeclaration(loc
, endloc
, NULL
, STCundefined
, type
)
4702 this->ident
= id
? id
: Id::empty
;
4706 this->deferToObj
= false;
4707 //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
4710 Dsymbol
*FuncLiteralDeclaration::syntaxCopy(Dsymbol
*s
)
4712 //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
4714 FuncLiteralDeclaration
*f
= new FuncLiteralDeclaration(loc
, endloc
,
4715 type
->syntaxCopy(), tok
, fes
, ident
);
4716 f
->treq
= treq
; // don't need to copy
4717 return FuncDeclaration::syntaxCopy(f
);
4720 bool FuncLiteralDeclaration::isNested()
4722 //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
4723 return (tok
!= TOKfunction
) && !isThis();
4726 AggregateDeclaration
*FuncLiteralDeclaration::isThis()
4728 //printf("FuncLiteralDeclaration::isThis() '%s'\n", toChars());
4729 return tok
== TOKdelegate
? FuncDeclaration::isThis() : NULL
;
4732 bool FuncLiteralDeclaration::isVirtual()
4737 bool FuncLiteralDeclaration::addPreInvariant()
4742 bool FuncLiteralDeclaration::addPostInvariant()
4747 /*******************************
4748 * Modify all expression type of return statements to tret.
4750 * On function literals, return type may be modified based on the context type
4751 * after its semantic3 is done, in FuncExp::implicitCastTo.
4753 * A function() dg = (){ return new B(); } // OK if is(B : A) == true
4755 * If B to A conversion is convariant that requires offseet adjusting,
4756 * all return statements should be adjusted to return expressions typed A.
4758 void FuncLiteralDeclaration::modifyReturns(Scope
*sc
, Type
*tret
)
4760 class RetWalker
: public StatementRewriteWalker
4765 FuncLiteralDeclaration
*fld
;
4767 void visit(ReturnStatement
*s
)
4769 Expression
*exp
= s
->exp
;
4770 if (exp
&& !exp
->type
->equals(tret
))
4772 s
->exp
= exp
->castTo(sc
, tret
);
4777 if (semanticRun
< PASSsemantic3done
)
4789 // Also update the inferred function type to match the new return type.
4790 // This is required so the code generator does not try to cast the
4791 // modified returns back to the original type.
4792 if (inferRetType
&& type
->nextOf() != tret
)
4793 type
->toTypeFunction()->next
= tret
;
4796 const char *FuncLiteralDeclaration::kind() const
4798 return (tok
!= TOKfunction
) ? "delegate" : "function";
4801 const char *FuncLiteralDeclaration::toPrettyChars(bool QualifyTypes
)
4805 TemplateInstance
*ti
= parent
->isTemplateInstance();
4807 return ti
->tempdecl
->toPrettyChars(QualifyTypes
);
4809 return Dsymbol::toPrettyChars(QualifyTypes
);
4812 /********************************* CtorDeclaration ****************************/
4814 CtorDeclaration::CtorDeclaration(Loc loc
, Loc endloc
, StorageClass stc
, Type
*type
)
4815 : FuncDeclaration(loc
, endloc
, Id::ctor
, stc
, type
)
4817 //printf("CtorDeclaration(loc = %s) %s\n", loc.toChars(), toChars());
4820 Dsymbol
*CtorDeclaration::syntaxCopy(Dsymbol
*s
)
4823 CtorDeclaration
*f
= new CtorDeclaration(loc
, endloc
, storage_class
, type
->syntaxCopy());
4824 return FuncDeclaration::syntaxCopy(f
);
4827 void CtorDeclaration::semantic(Scope
*sc
)
4829 //printf("CtorDeclaration::semantic() %s\n", toChars());
4830 if (semanticRun
>= PASSsemanticdone
)
4838 parent
= sc
->parent
;
4839 Dsymbol
*p
= toParent2();
4840 AggregateDeclaration
*ad
= p
->isAggregateDeclaration();
4843 ::error(loc
, "constructor can only be a member of aggregate, not %s %s",
4844 p
->kind(), p
->toChars());
4845 type
= Type::terror
;
4851 sc
->stc
&= ~STCstatic
; // not a static constructor
4852 sc
->flags
|= SCOPEctor
;
4854 FuncDeclaration::semantic(sc
);
4861 TypeFunction
*tf
= type
->toTypeFunction();
4863 /* See if it's the default constructor
4864 * But, template constructor should not become a default constructor.
4866 if (ad
&& (!parent
->isTemplateInstance() || parent
->isTemplateMixin()))
4868 const size_t dim
= Parameter::dim(tf
->parameters
);
4870 if (StructDeclaration
*sd
= ad
->isStructDeclaration())
4872 if (dim
== 0 && tf
->varargs
== 0) // empty default ctor w/o any varargs
4874 if (fbody
|| !(storage_class
& STCdisable
) || dim
)
4876 error("default constructor for structs only allowed "
4877 "with @disable, no body, and no parameters");
4878 storage_class
|= STCdisable
;
4881 sd
->noDefaultCtor
= true;
4883 else if (dim
== 0 && tf
->varargs
) // allow varargs only ctor
4886 else if (dim
&& Parameter::getNth(tf
->parameters
, 0)->defaultArg
)
4888 // if the first parameter has a default argument, then the rest does as well
4889 if (storage_class
& STCdisable
)
4891 deprecation("@disable'd constructor cannot have default "
4892 "arguments for all parameters.");
4893 deprecationSupplemental(loc
, "Use @disable this(); if you want to disable default initialization.");
4896 deprecation("all parameters have default arguments, "
4897 "but structs cannot have default constructors.");
4901 else if (dim
== 0 && tf
->varargs
== 0)
4903 ad
->defaultCtor
= this;
4908 const char *CtorDeclaration::kind() const
4910 return "constructor";
4913 const char *CtorDeclaration::toChars()
4918 bool CtorDeclaration::isVirtual()
4923 bool CtorDeclaration::addPreInvariant()
4928 bool CtorDeclaration::addPostInvariant()
4930 return (isThis() && vthis
&& global
.params
.useInvariants
);
4934 /********************************* PostBlitDeclaration ****************************/
4936 PostBlitDeclaration::PostBlitDeclaration(Loc loc
, Loc endloc
, StorageClass stc
, Identifier
*id
)
4937 : FuncDeclaration(loc
, endloc
, id
, stc
, NULL
)
4941 Dsymbol
*PostBlitDeclaration::syntaxCopy(Dsymbol
*s
)
4944 PostBlitDeclaration
*dd
= new PostBlitDeclaration(loc
, endloc
, storage_class
, ident
);
4945 return FuncDeclaration::syntaxCopy(dd
);
4948 void PostBlitDeclaration::semantic(Scope
*sc
)
4950 //printf("PostBlitDeclaration::semantic() %s\n", toChars());
4951 //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
4952 //printf("stc = x%llx\n", sc->stc);
4953 if (semanticRun
>= PASSsemanticdone
)
4961 parent
= sc
->parent
;
4962 Dsymbol
*p
= toParent2();
4963 StructDeclaration
*ad
= p
->isStructDeclaration();
4966 ::error(loc
, "postblit can only be a member of struct/union, not %s %s",
4967 p
->kind(), p
->toChars());
4968 type
= Type::terror
;
4972 if (ident
== Id::postblit
&& semanticRun
< PASSsemantic
)
4973 ad
->postblits
.push(this);
4975 type
= new TypeFunction(NULL
, Type::tvoid
, false, LINKd
, storage_class
);
4978 sc
->stc
&= ~STCstatic
; // not static
4979 sc
->linkage
= LINKd
;
4981 FuncDeclaration::semantic(sc
);
4986 bool PostBlitDeclaration::overloadInsert(Dsymbol
*)
4988 return false; // cannot overload postblits
4991 bool PostBlitDeclaration::addPreInvariant()
4996 bool PostBlitDeclaration::addPostInvariant()
4998 return (isThis() && vthis
&& global
.params
.useInvariants
);
5001 bool PostBlitDeclaration::isVirtual()
5006 /********************************* DtorDeclaration ****************************/
5008 DtorDeclaration::DtorDeclaration(Loc loc
, Loc endloc
)
5009 : FuncDeclaration(loc
, endloc
, Id::dtor
, STCundefined
, NULL
)
5013 DtorDeclaration::DtorDeclaration(Loc loc
, Loc endloc
, StorageClass stc
, Identifier
*id
)
5014 : FuncDeclaration(loc
, endloc
, id
, stc
, NULL
)
5018 Dsymbol
*DtorDeclaration::syntaxCopy(Dsymbol
*s
)
5021 DtorDeclaration
*dd
= new DtorDeclaration(loc
, endloc
, storage_class
, ident
);
5022 return FuncDeclaration::syntaxCopy(dd
);
5025 void DtorDeclaration::semantic(Scope
*sc
)
5027 //printf("DtorDeclaration::semantic() %s\n", toChars());
5028 //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
5029 if (semanticRun
>= PASSsemanticdone
)
5037 parent
= sc
->parent
;
5038 Dsymbol
*p
= toParent2();
5039 AggregateDeclaration
*ad
= p
->isAggregateDeclaration();
5042 ::error(loc
, "destructor can only be a member of aggregate, not %s %s",
5043 p
->kind(), p
->toChars());
5044 type
= Type::terror
;
5048 if (ident
== Id::dtor
&& semanticRun
< PASSsemantic
)
5049 ad
->dtors
.push(this);
5051 type
= new TypeFunction(NULL
, Type::tvoid
, false, LINKd
, storage_class
);
5054 sc
->stc
&= ~STCstatic
; // not a static destructor
5055 if (sc
->linkage
!= LINKcpp
)
5056 sc
->linkage
= LINKd
;
5058 FuncDeclaration::semantic(sc
);
5063 bool DtorDeclaration::overloadInsert(Dsymbol
*)
5065 return false; // cannot overload destructors
5068 bool DtorDeclaration::addPreInvariant()
5070 return (isThis() && vthis
&& global
.params
.useInvariants
);
5073 bool DtorDeclaration::addPostInvariant()
5078 const char *DtorDeclaration::kind() const
5080 return "destructor";
5083 const char *DtorDeclaration::toChars()
5088 bool DtorDeclaration::isVirtual()
5090 // false so that dtor's don't get put into the vtbl[]
5094 /********************************* StaticCtorDeclaration ****************************/
5096 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc
, Loc endloc
, StorageClass stc
)
5097 : FuncDeclaration(loc
, endloc
,
5098 Identifier::generateId("_staticCtor"), STCstatic
| stc
, NULL
)
5102 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc
, Loc endloc
, const char *name
, StorageClass stc
)
5103 : FuncDeclaration(loc
, endloc
,
5104 Identifier::generateId(name
), STCstatic
| stc
, NULL
)
5108 Dsymbol
*StaticCtorDeclaration::syntaxCopy(Dsymbol
*s
)
5111 StaticCtorDeclaration
*scd
= new StaticCtorDeclaration(loc
, endloc
, storage_class
);
5112 return FuncDeclaration::syntaxCopy(scd
);
5115 void StaticCtorDeclaration::semantic(Scope
*sc
)
5117 //printf("StaticCtorDeclaration::semantic()\n");
5118 if (semanticRun
>= PASSsemanticdone
)
5126 parent
= sc
->parent
;
5127 Dsymbol
*p
= parent
->pastMixin();
5128 if (!p
->isScopeDsymbol())
5130 const char *s
= (isSharedStaticCtorDeclaration() ? "shared " : "");
5131 ::error(loc
, "%sstatic constructor can only be member of module/aggregate/template, not %s %s",
5132 s
, p
->kind(), p
->toChars());
5133 type
= Type::terror
;
5138 type
= new TypeFunction(NULL
, Type::tvoid
, false, LINKd
, storage_class
);
5140 /* If the static ctor appears within a template instantiation,
5141 * it could get called multiple times by the module constructors
5142 * for different modules. Thus, protect it with a gate.
5144 if (isInstantiated() && semanticRun
< PASSsemantic
)
5146 /* Add this prefix to the function:
5148 * if (++gate != 1) return;
5149 * Note that this is not thread safe; should not have threads
5150 * during static construction.
5152 VarDeclaration
*v
= new VarDeclaration(Loc(), Type::tint32
, Id::gate
, NULL
);
5153 v
->storage_class
= STCtemp
| (isSharedStaticCtorDeclaration() ? STCstatic
: STCtls
);
5154 Statements
*sa
= new Statements();
5155 Statement
*s
= new ExpStatement(Loc(), v
);
5157 Expression
*e
= new IdentifierExp(Loc(), v
->ident
);
5158 e
= new AddAssignExp(Loc(), e
, new IntegerExp(1));
5159 e
= new EqualExp(TOKnotequal
, Loc(), e
, new IntegerExp(1));
5160 s
= new IfStatement(Loc(), NULL
, e
, new ReturnStatement(Loc(), NULL
), NULL
, Loc());
5164 fbody
= new CompoundStatement(Loc(), sa
);
5167 FuncDeclaration::semantic(sc
);
5169 // We're going to need ModuleInfo
5170 Module
*m
= getModule();
5175 m
->needmoduleinfo
= 1;
5176 //printf("module1 %s needs moduleinfo\n", m->toChars());
5180 AggregateDeclaration
*StaticCtorDeclaration::isThis()
5185 bool StaticCtorDeclaration::isVirtual()
5190 bool StaticCtorDeclaration::hasStaticCtorOrDtor()
5195 bool StaticCtorDeclaration::addPreInvariant()
5200 bool StaticCtorDeclaration::addPostInvariant()
5205 /********************************* SharedStaticCtorDeclaration ****************************/
5207 SharedStaticCtorDeclaration::SharedStaticCtorDeclaration(Loc loc
, Loc endloc
, StorageClass stc
)
5208 : StaticCtorDeclaration(loc
, endloc
, "_sharedStaticCtor", stc
)
5212 Dsymbol
*SharedStaticCtorDeclaration::syntaxCopy(Dsymbol
*s
)
5215 SharedStaticCtorDeclaration
*scd
= new SharedStaticCtorDeclaration(loc
, endloc
, storage_class
);
5216 return FuncDeclaration::syntaxCopy(scd
);
5219 /********************************* StaticDtorDeclaration ****************************/
5221 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc
, Loc endloc
, StorageClass stc
)
5222 : FuncDeclaration(loc
, endloc
,
5223 Identifier::generateId("_staticDtor"), STCstatic
| stc
, NULL
)
5228 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc
, Loc endloc
, const char *name
, StorageClass stc
)
5229 : FuncDeclaration(loc
, endloc
,
5230 Identifier::generateId(name
), STCstatic
| stc
, NULL
)
5235 Dsymbol
*StaticDtorDeclaration::syntaxCopy(Dsymbol
*s
)
5238 StaticDtorDeclaration
*sdd
= new StaticDtorDeclaration(loc
, endloc
, storage_class
);
5239 return FuncDeclaration::syntaxCopy(sdd
);
5242 void StaticDtorDeclaration::semantic(Scope
*sc
)
5244 if (semanticRun
>= PASSsemanticdone
)
5252 parent
= sc
->parent
;
5253 Dsymbol
*p
= parent
->pastMixin();
5254 if (!p
->isScopeDsymbol())
5256 const char *s
= (isSharedStaticDtorDeclaration() ? "shared " : "");
5257 ::error(loc
, "%sstatic destructor can only be member of module/aggregate/template, not %s %s",
5258 s
, p
->kind(), p
->toChars());
5259 type
= Type::terror
;
5264 type
= new TypeFunction(NULL
, Type::tvoid
, false, LINKd
, storage_class
);
5266 /* If the static ctor appears within a template instantiation,
5267 * it could get called multiple times by the module constructors
5268 * for different modules. Thus, protect it with a gate.
5270 if (isInstantiated() && semanticRun
< PASSsemantic
)
5272 /* Add this prefix to the function:
5274 * if (--gate != 0) return;
5275 * Increment gate during constructor execution.
5276 * Note that this is not thread safe; should not have threads
5277 * during static destruction.
5279 VarDeclaration
*v
= new VarDeclaration(Loc(), Type::tint32
, Id::gate
, NULL
);
5280 v
->storage_class
= STCtemp
| (isSharedStaticDtorDeclaration() ? STCstatic
: STCtls
);
5281 Statements
*sa
= new Statements();
5282 Statement
*s
= new ExpStatement(Loc(), v
);
5284 Expression
*e
= new IdentifierExp(Loc(), v
->ident
);
5285 e
= new AddAssignExp(Loc(), e
, new IntegerExp(-1));
5286 e
= new EqualExp(TOKnotequal
, Loc(), e
, new IntegerExp(0));
5287 s
= new IfStatement(Loc(), NULL
, e
, new ReturnStatement(Loc(), NULL
), NULL
, Loc());
5291 fbody
= new CompoundStatement(Loc(), sa
);
5295 FuncDeclaration::semantic(sc
);
5297 // We're going to need ModuleInfo
5298 Module
*m
= getModule();
5303 m
->needmoduleinfo
= 1;
5304 //printf("module2 %s needs moduleinfo\n", m->toChars());
5308 AggregateDeclaration
*StaticDtorDeclaration::isThis()
5313 bool StaticDtorDeclaration::isVirtual()
5318 bool StaticDtorDeclaration::hasStaticCtorOrDtor()
5323 bool StaticDtorDeclaration::addPreInvariant()
5328 bool StaticDtorDeclaration::addPostInvariant()
5333 /********************************* SharedStaticDtorDeclaration ****************************/
5335 SharedStaticDtorDeclaration::SharedStaticDtorDeclaration(Loc loc
, Loc endloc
, StorageClass stc
)
5336 : StaticDtorDeclaration(loc
, endloc
, "_sharedStaticDtor", stc
)
5340 Dsymbol
*SharedStaticDtorDeclaration::syntaxCopy(Dsymbol
*s
)
5343 SharedStaticDtorDeclaration
*sdd
= new SharedStaticDtorDeclaration(loc
, endloc
, storage_class
);
5344 return FuncDeclaration::syntaxCopy(sdd
);
5347 /********************************* InvariantDeclaration ****************************/
5349 InvariantDeclaration::InvariantDeclaration(Loc loc
, Loc endloc
, StorageClass stc
, Identifier
*id
)
5350 : FuncDeclaration(loc
, endloc
,
5351 id
? id
: Identifier::generateId("__invariant"),
5356 Dsymbol
*InvariantDeclaration::syntaxCopy(Dsymbol
*s
)
5359 InvariantDeclaration
*id
= new InvariantDeclaration(loc
, endloc
, storage_class
);
5360 return FuncDeclaration::syntaxCopy(id
);
5363 void InvariantDeclaration::semantic(Scope
*sc
)
5365 if (semanticRun
>= PASSsemanticdone
)
5373 parent
= sc
->parent
;
5374 Dsymbol
*p
= parent
->pastMixin();
5375 AggregateDeclaration
*ad
= p
->isAggregateDeclaration();
5378 ::error(loc
, "invariant can only be a member of aggregate, not %s %s",
5379 p
->kind(), p
->toChars());
5380 type
= Type::terror
;
5384 if (ident
!= Id::classInvariant
&&
5385 semanticRun
< PASSsemantic
&&
5386 !ad
->isUnionDeclaration() // users are on their own with union fields
5388 ad
->invs
.push(this);
5390 type
= new TypeFunction(NULL
, Type::tvoid
, false, LINKd
, storage_class
);
5393 sc
->stc
&= ~STCstatic
; // not a static invariant
5394 sc
->stc
|= STCconst
; // invariant() is always const
5395 sc
->flags
= (sc
->flags
& ~SCOPEcontract
) | SCOPEinvariant
;
5396 sc
->linkage
= LINKd
;
5398 FuncDeclaration::semantic(sc
);
5403 bool InvariantDeclaration::isVirtual()
5408 bool InvariantDeclaration::addPreInvariant()
5413 bool InvariantDeclaration::addPostInvariant()
5418 /********************************* UnitTestDeclaration ****************************/
5420 /*******************************
5421 * Generate unique unittest function Id so we can have multiple
5422 * instances per module.
5425 static Identifier
*unitTestId(Loc loc
)
5428 buf
.printf("__unittestL%u_", loc
.linnum
);
5429 return Identifier::generateId(buf
.peekString());
5432 UnitTestDeclaration::UnitTestDeclaration(Loc loc
, Loc endloc
, StorageClass stc
, char *codedoc
)
5433 : FuncDeclaration(loc
, endloc
, unitTestId(loc
), stc
, NULL
)
5435 this->codedoc
= codedoc
;
5438 Dsymbol
*UnitTestDeclaration::syntaxCopy(Dsymbol
*s
)
5441 UnitTestDeclaration
*utd
= new UnitTestDeclaration(loc
, endloc
, storage_class
, codedoc
);
5442 return FuncDeclaration::syntaxCopy(utd
);
5445 void UnitTestDeclaration::semantic(Scope
*sc
)
5447 if (semanticRun
>= PASSsemanticdone
)
5455 protection
= sc
->protection
;
5457 parent
= sc
->parent
;
5458 Dsymbol
*p
= parent
->pastMixin();
5459 if (!p
->isScopeDsymbol())
5461 ::error(loc
, "unittest can only be a member of module/aggregate/template, not %s %s",
5462 p
->kind(), p
->toChars());
5463 type
= Type::terror
;
5468 if (global
.params
.useUnitTests
)
5471 type
= new TypeFunction(NULL
, Type::tvoid
, false, LINKd
, storage_class
);
5472 Scope
*sc2
= sc
->push();
5473 sc2
->linkage
= LINKd
;
5474 FuncDeclaration::semantic(sc2
);
5479 AggregateDeclaration
*UnitTestDeclaration::isThis()
5484 bool UnitTestDeclaration::isVirtual()
5489 bool UnitTestDeclaration::addPreInvariant()
5494 bool UnitTestDeclaration::addPostInvariant()
5499 /********************************* NewDeclaration ****************************/
5501 NewDeclaration::NewDeclaration(Loc loc
, Loc endloc
, StorageClass stc
, Parameters
*fparams
, int varargs
)
5502 : FuncDeclaration(loc
, endloc
, Id::classNew
, STCstatic
| stc
, NULL
)
5504 this->parameters
= fparams
;
5505 this->varargs
= varargs
;
5508 Dsymbol
*NewDeclaration::syntaxCopy(Dsymbol
*s
)
5511 NewDeclaration
*f
= new NewDeclaration(loc
, endloc
,
5512 storage_class
, Parameter::arraySyntaxCopy(parameters
), varargs
);
5513 return FuncDeclaration::syntaxCopy(f
);
5516 void NewDeclaration::semantic(Scope
*sc
)
5518 //printf("NewDeclaration::semantic()\n");
5519 if (semanticRun
>= PASSsemanticdone
)
5527 parent
= sc
->parent
;
5528 Dsymbol
*p
= parent
->pastMixin();
5529 if (!p
->isAggregateDeclaration())
5531 ::error(loc
, "allocator can only be a member of aggregate, not %s %s",
5532 p
->kind(), p
->toChars());
5533 type
= Type::terror
;
5537 Type
*tret
= Type::tvoid
->pointerTo();
5539 type
= new TypeFunction(parameters
, tret
, varargs
, LINKd
, storage_class
);
5541 type
= type
->semantic(loc
, sc
);
5543 // Check that there is at least one argument of type size_t
5544 TypeFunction
*tf
= type
->toTypeFunction();
5545 if (Parameter::dim(tf
->parameters
) < 1)
5547 error("at least one argument of type size_t expected");
5551 Parameter
*fparam
= Parameter::getNth(tf
->parameters
, 0);
5552 if (!fparam
->type
->equals(Type::tsize_t
))
5553 error("first argument must be type size_t, not %s", fparam
->type
->toChars());
5556 FuncDeclaration::semantic(sc
);
5559 const char *NewDeclaration::kind() const
5564 bool NewDeclaration::isVirtual()
5569 bool NewDeclaration::addPreInvariant()
5574 bool NewDeclaration::addPostInvariant()
5579 /********************************* DeleteDeclaration ****************************/
5581 DeleteDeclaration::DeleteDeclaration(Loc loc
, Loc endloc
, StorageClass stc
, Parameters
*fparams
)
5582 : FuncDeclaration(loc
, endloc
, Id::classDelete
, STCstatic
| stc
, NULL
)
5584 this->parameters
= fparams
;
5587 Dsymbol
*DeleteDeclaration::syntaxCopy(Dsymbol
*s
)
5590 DeleteDeclaration
*f
= new DeleteDeclaration(loc
, endloc
,
5591 storage_class
, Parameter::arraySyntaxCopy(parameters
));
5592 return FuncDeclaration::syntaxCopy(f
);
5595 void DeleteDeclaration::semantic(Scope
*sc
)
5597 //printf("DeleteDeclaration::semantic()\n");
5598 if (semanticRun
>= PASSsemanticdone
)
5606 parent
= sc
->parent
;
5607 Dsymbol
*p
= parent
->pastMixin();
5608 if (!p
->isAggregateDeclaration())
5610 ::error(loc
, "deallocator can only be a member of aggregate, not %s %s",
5611 p
->kind(), p
->toChars());
5612 type
= Type::terror
;
5617 type
= new TypeFunction(parameters
, Type::tvoid
, 0, LINKd
, storage_class
);
5619 type
= type
->semantic(loc
, sc
);
5621 // Check that there is only one argument of type void*
5622 TypeFunction
*tf
= type
->toTypeFunction();
5623 if (Parameter::dim(tf
->parameters
) != 1)
5625 error("one argument of type void* expected");
5629 Parameter
*fparam
= Parameter::getNth(tf
->parameters
, 0);
5630 if (!fparam
->type
->equals(Type::tvoid
->pointerTo()))
5631 error("one argument of type void* expected, not %s", fparam
->type
->toChars());
5634 FuncDeclaration::semantic(sc
);
5637 const char *DeleteDeclaration::kind() const
5639 return "deallocator";
5642 bool DeleteDeclaration::isDelete()
5647 bool DeleteDeclaration::isVirtual()
5652 bool DeleteDeclaration::addPreInvariant()
5657 bool DeleteDeclaration::addPostInvariant()