xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/d/dmd/func.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1 
2 /* Compiler implementation of the D programming language
3  * Copyright (C) 1999-2019 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
9  */
10 
11 #include "root/dsystem.h"
12 
13 #include "mars.h"
14 #include "init.h"
15 #include "declaration.h"
16 #include "attrib.h"
17 #include "expression.h"
18 #include "scope.h"
19 #include "mtype.h"
20 #include "aggregate.h"
21 #include "identifier.h"
22 #include "id.h"
23 #include "module.h"
24 #include "statement.h"
25 #include "template.h"
26 #include "hdrgen.h"
27 #include "target.h"
28 #include "parse.h"
29 #include "root/rmem.h"
30 #include "visitor.h"
31 #include "objc.h"
32 
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();
43 
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);
51 Objc *objc();
52 
53 
54 /* A visitor to walk entire statements and provides ability to replace any sub-statements.
55  */
56 class StatementRewriteWalker : public Visitor
57 {
58     /* Point the currently visited statement.
59      * By using replaceCurrent() method, you can replace AST during walking.
60      */
61     Statement **ps;
62 public:
visitStmt(Statement * & s)63     void visitStmt(Statement *&s) { ps = &s; s->accept(this); }
replaceCurrent(Statement * s)64     void replaceCurrent(Statement *s) { *ps = s; }
65 
visit(ErrorStatement *)66     void visit(ErrorStatement *) {  }
visit(PeelStatement * s)67     void visit(PeelStatement *s)
68     {
69         if (s->s)
70             visitStmt(s->s);
71     }
visit(ExpStatement *)72     void visit(ExpStatement *) {  }
visit(DtorExpStatement *)73     void visit(DtorExpStatement *) {  }
visit(CompileStatement *)74     void visit(CompileStatement *) {  }
visit(CompoundStatement * s)75     void visit(CompoundStatement *s)
76     {
77         if (s->statements && s->statements->dim)
78         {
79             for (size_t i = 0; i < s->statements->dim; i++)
80             {
81                 if ((*s->statements)[i])
82                     visitStmt((*s->statements)[i]);
83             }
84         }
85     }
visit(CompoundDeclarationStatement * s)86     void visit(CompoundDeclarationStatement *s) { visit((CompoundStatement *)s); }
visit(UnrolledLoopStatement * s)87     void visit(UnrolledLoopStatement *s)
88     {
89         if (s->statements && s->statements->dim)
90         {
91             for (size_t i = 0; i < s->statements->dim; i++)
92             {
93                 if ((*s->statements)[i])
94                     visitStmt((*s->statements)[i]);
95             }
96         }
97     }
visit(ScopeStatement * s)98     void visit(ScopeStatement *s)
99     {
100         if (s->statement)
101             visitStmt(s->statement);
102     }
visit(WhileStatement * s)103     void visit(WhileStatement *s)
104     {
105         if (s->_body)
106             visitStmt(s->_body);
107     }
visit(DoStatement * s)108     void visit(DoStatement *s)
109     {
110         if (s->_body)
111             visitStmt(s->_body);
112     }
visit(ForStatement * s)113     void visit(ForStatement *s)
114     {
115         if (s->_init)
116             visitStmt(s->_init);
117         if (s->_body)
118             visitStmt(s->_body);
119     }
visit(ForeachStatement * s)120     void visit(ForeachStatement *s)
121     {
122         if (s->_body)
123             visitStmt(s->_body);
124     }
visit(ForeachRangeStatement * s)125     void visit(ForeachRangeStatement *s)
126     {
127         if (s->_body)
128             visitStmt(s->_body);
129     }
visit(IfStatement * s)130     void visit(IfStatement *s)
131     {
132         if (s->ifbody)
133             visitStmt(s->ifbody);
134         if (s->elsebody)
135             visitStmt(s->elsebody);
136     }
visit(ConditionalStatement *)137     void visit(ConditionalStatement *) {  }
visit(PragmaStatement *)138     void visit(PragmaStatement *) {  }
visit(StaticAssertStatement *)139     void visit(StaticAssertStatement *) {  }
visit(SwitchStatement * s)140     void visit(SwitchStatement *s)
141     {
142         if (s->_body)
143             visitStmt(s->_body);
144     }
visit(CaseStatement * s)145     void visit(CaseStatement *s)
146     {
147         if (s->statement)
148             visitStmt(s->statement);
149     }
visit(CaseRangeStatement * s)150     void visit(CaseRangeStatement *s)
151     {
152         if (s->statement)
153             visitStmt(s->statement);
154     }
visit(DefaultStatement * s)155     void visit(DefaultStatement *s)
156     {
157         if (s->statement)
158             visitStmt(s->statement);
159     }
visit(GotoDefaultStatement *)160     void visit(GotoDefaultStatement *) {  }
visit(GotoCaseStatement *)161     void visit(GotoCaseStatement *) {  }
visit(SwitchErrorStatement *)162     void visit(SwitchErrorStatement *) {  }
visit(ReturnStatement *)163     void visit(ReturnStatement *) {  }
visit(BreakStatement *)164     void visit(BreakStatement *) {  }
visit(ContinueStatement *)165     void visit(ContinueStatement *) {  }
visit(SynchronizedStatement * s)166     void visit(SynchronizedStatement *s)
167     {
168         if (s->_body)
169             visitStmt(s->_body);
170     }
visit(WithStatement * s)171     void visit(WithStatement *s)
172     {
173         if (s->_body)
174             visitStmt(s->_body);
175     }
visit(TryCatchStatement * s)176     void visit(TryCatchStatement *s)
177     {
178         if (s->_body)
179             visitStmt(s->_body);
180         if (s->catches && s->catches->dim)
181         {
182             for (size_t i = 0; i < s->catches->dim; i++)
183             {
184                 Catch *c = (*s->catches)[i];
185                 if (c && c->handler)
186                     visitStmt(c->handler);
187             }
188         }
189     }
visit(TryFinallyStatement * s)190     void visit(TryFinallyStatement *s)
191     {
192         if (s->_body)
193             visitStmt(s->_body);
194         if (s->finalbody)
195             visitStmt(s->finalbody);
196     }
visit(OnScopeStatement *)197     void visit(OnScopeStatement *) {  }
visit(ThrowStatement *)198     void visit(ThrowStatement *) {  }
visit(DebugStatement * s)199     void visit(DebugStatement *s)
200     {
201         if (s->statement)
202             visitStmt(s->statement);
203     }
visit(GotoStatement *)204     void visit(GotoStatement *) {  }
visit(LabelStatement * s)205     void visit(LabelStatement *s)
206     {
207         if (s->statement)
208             visitStmt(s->statement);
209     }
visit(AsmStatement *)210     void visit(AsmStatement *) {  }
visit(ImportStatement *)211     void visit(ImportStatement *) {  }
212 };
213 
214 /* Tweak all return statements and dtor call for nrvo_var, for correct NRVO.
215  */
216 class NrvoWalker : public StatementRewriteWalker
217 {
218 public:
219     FuncDeclaration *fd;
220     Scope *sc;
221 
visit(ReturnStatement * s)222     void visit(ReturnStatement *s)
223     {
224         // See if all returns are instead to be replaced with a goto returnLabel;
225         if (fd->returnLabel)
226         {
227             /* Rewrite:
228              *  return exp;
229              * as:
230              *  vresult = exp; goto Lresult;
231              */
232             GotoStatement *gs = new GotoStatement(s->loc, Id::returnLabel);
233             gs->label = fd->returnLabel;
234 
235             Statement *s1 = gs;
236             if (s->exp)
237                 s1 = new CompoundStatement(s->loc, new ExpStatement(s->loc, s->exp), gs);
238 
239             replaceCurrent(s1);
240         }
241     }
visit(TryFinallyStatement * s)242     void visit(TryFinallyStatement *s)
243     {
244         DtorExpStatement *des;
245         if (fd->nrvo_can &&
246             s->finalbody && (des = s->finalbody->isDtorExpStatement()) != NULL &&
247             fd->nrvo_var == des->var)
248         {
249             if (!(global.params.useExceptions && ClassDeclaration::throwable))
250             {
251                 /* Don't need to call destructor at all, since it is nrvo
252                  */
253                 replaceCurrent(s->_body);
254                 s->_body->accept(this);
255                 return;
256             }
257 
258             /* Normally local variable dtors are called regardless exceptions.
259              * But for nrvo_var, its dtor should be called only when exception is thrown.
260              *
261              * Rewrite:
262              *      try { s->body; } finally { nrvo_var->edtor; }
263              *      // equivalent with:
264              *      //    s->body; scope(exit) nrvo_var->edtor;
265              * as:
266              *      try { s->body; } catch(Throwable __o) { nrvo_var->edtor; throw __o; }
267              *      // equivalent with:
268              *      //    s->body; scope(failure) nrvo_var->edtor;
269              */
270             Statement *sexception = new DtorExpStatement(Loc(), fd->nrvo_var->edtor, fd->nrvo_var);
271             Identifier *id = Identifier::generateId("__o");
272 
273             Statement *handler = new PeelStatement(sexception);
274             if (blockExit(sexception, fd, false) & BEfallthru)
275             {
276                 ThrowStatement *ts = new ThrowStatement(Loc(), new IdentifierExp(Loc(), id));
277                 ts->internalThrow = true;
278                 handler = new CompoundStatement(Loc(), handler, ts);
279             }
280 
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'
285             catches->push(ctch);
286 
287             Statement *s2 = new TryCatchStatement(Loc(), s->_body, catches);
288             replaceCurrent(s2);
289             s2->accept(this);
290         }
291         else
292             StatementRewriteWalker::visit(s);
293     }
294 };
295 
296 /********************************* FuncDeclaration ****************************/
297 
FuncDeclaration(Loc loc,Loc endloc,Identifier * id,StorageClass storage_class,Type * type)298 FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageClass storage_class, Type *type)
299     : Declaration(id)
300 {
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;
304     this->type = type;
305     if (type)
306     {
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);
310     }
311     this->loc = loc;
312     this->endloc = endloc;
313     fthrows = NULL;
314     frequire = NULL;
315     fdrequire = NULL;
316     fdensure = NULL;
317     mangleString = NULL;
318     outId = NULL;
319     vresult = NULL;
320     returnLabel = NULL;
321     fensure = NULL;
322     fbody = NULL;
323     localsymtab = NULL;
324     vthis = NULL;
325     v_arguments = NULL;
326     v_argptr = NULL;
327     parameters = NULL;
328     labtab = NULL;
329     overnext = NULL;
330     overnext0 = NULL;
331     vtblIndex = -1;
332     hasReturnExp = 0;
333     naked = false;
334     generated = false;
335     inlineStatusExp = ILSuninitialized;
336     inlineStatusStmt = ILSuninitialized;
337     inlining = PINLINEdefault;
338     inlineNest = 0;
339     ctfeCode = NULL;
340     isArrayOp = 0;
341     semantic3Errors = false;
342     fes = NULL;
343     interfaceVirtual = NULL;
344     introducing = 0;
345     tintro = NULL;
346     /* The type given for "infer the return type" is a TypeFunction with
347      * NULL for the return type.
348      */
349     inferRetType = (type && type->nextOf() == NULL);
350     storage_class2 = 0;
351     hasReturnExp = 0;
352     nrvo_can = 1;
353     nrvo_var = NULL;
354     shidden = NULL;
355     builtin = BUILTINunknown;
356     tookAddressOf = 0;
357     requiresClosure = false;
358     inlinedNestedCallees = NULL;
359     flags = 0;
360     returns = NULL;
361     gotos = NULL;
362     selector = NULL;
363 }
364 
create(Loc loc,Loc endloc,Identifier * id,StorageClass storage_class,Type * type)365 FuncDeclaration *FuncDeclaration::create(Loc loc, Loc endloc, Identifier *id, StorageClass storage_class, Type *type)
366 {
367     return new FuncDeclaration(loc, endloc, id, storage_class, type);
368 }
369 
syntaxCopy(Dsymbol * s)370 Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
371 {
372     //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
373     FuncDeclaration *f =
374         s ? (FuncDeclaration *)s
375           : new FuncDeclaration(loc, endloc, ident, storage_class, type->syntaxCopy());
376     f->outId = outId;
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
381     return f;
382 }
383 
384 /**********************************
385  * Decide if attributes for this function can be inferred from examining
386  * the function body.
387  * Returns:
388  *  true if can
389  */
canInferAttributes(FuncDeclaration * fd,Scope * sc)390 static bool canInferAttributes(FuncDeclaration *fd, Scope *sc)
391 {
392     if (!fd->fbody)
393         return false;
394 
395     if (fd->isVirtualMethod())
396         return false;               // since they may be overridden
397 
398     if (sc->func &&
399         /********** this is for backwards compatibility for the moment ********/
400         (!fd->isMember() || (sc->func->isSafeBypassingInference() && !fd->isInstantiated())))
401         return true;
402 
403     if (fd->isFuncLiteralDeclaration() ||               // externs are not possible with literals
404         (fd->storage_class & STCinference) ||           // do attribute inference
405         (fd->inferRetType && !fd->isCtorDeclaration()))
406         return true;
407 
408     if (fd->isInstantiated())
409     {
410         TemplateInstance *ti = fd->parent->isTemplateInstance();
411         if (ti == NULL || ti->isTemplateMixin() || ti->tempdecl->ident == fd->ident)
412             return true;
413     }
414 
415     return false;
416 }
417 
418 /*****************************************
419  * Initialize for inferring the attributes of this function.
420  */
initInferAttributes(FuncDeclaration * fd)421 static void initInferAttributes(FuncDeclaration *fd)
422 {
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;
427 
428     if (tf->trust == TRUSTdefault)
429         fd->flags |= FUNCFLAGsafetyInprocess;
430 
431     if (!tf->isnothrow)
432         fd->flags |= FUNCFLAGnothrowInprocess;
433 
434     if (!tf->isnogc)
435         fd->flags |= FUNCFLAGnogcInprocess;
436 
437     if (!fd->isVirtual() || fd->introducing)
438         fd->flags |= FUNCFLAGreturnInprocess;
439 
440     // Initialize for inferring STCscope
441     if (global.params.vsafe)
442         fd->flags |= FUNCFLAGinferScope;
443 }
444 
445 // Do the semantic analysis on the external interface to the function.
446 
semantic(Scope * sc)447 void FuncDeclaration::semantic(Scope *sc)
448 {
449     TypeFunction *f;
450     AggregateDeclaration *ad;
451     InterfaceDeclaration *id;
452 
453     if (semanticRun != PASSinit && isFuncLiteralDeclaration())
454     {
455         /* Member functions that have return types that are
456          * forward references can have semantic() run more than
457          * once on them.
458          * See test\interface2.d, test20
459          */
460         return;
461     }
462 
463     if (semanticRun >= PASSsemanticdone)
464         return;
465     assert(semanticRun <= PASSsemantic);
466     semanticRun = PASSsemantic;
467 
468     if (_scope)
469     {
470         sc = _scope;
471         _scope = NULL;
472     }
473 
474     if (!sc || errors)
475         return;
476 
477     parent = sc->parent;
478     Dsymbol *parent = toParent();
479 
480     foverrides.setDim(0);       // reset in case semantic() is being retried for this function
481 
482     storage_class |= sc->stc & ~STCref;
483     ad = isThis();
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)
487     {
488         storage_class |= ad->storage_class & (STC_TYPECTOR | STCsynchronized);
489         ad->makeNested();
490     }
491     if (sc->func)
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;
496 
497     //printf("function storage_class = x%llx, sc->stc = x%llx, %x\n", storage_class, sc->stc, Declaration::isFinal());
498 
499     FuncLiteralDeclaration *fld = isFuncLiteralDeclaration();
500     if (fld && fld->treq)
501     {
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;
508         else
509             assert(0);
510         linkage = treq->nextOf()->toTypeFunction()->linkage;
511     }
512     else
513         linkage = sc->linkage;
514     inlining = sc->inlining;
515     protection = sc->protection;
516     userAttribDecl = sc->userAttribDecl;
517 
518     if (!originalType)
519         originalType = type->syntaxCopy();
520     if (type->ty != Tfunction)
521     {
522         if (type->ty != Terror)
523         {
524             error("%s must be a function instead of %s", toChars(), type->toChars());
525             type = Type::terror;
526         }
527         errors = true;
528         return;
529     }
530     if (!type->deco)
531     {
532         sc = sc->push();
533         sc->stc |= storage_class & (STCdisable | STCdeprecated);  // forward to function type
534         TypeFunction *tf = type->toTypeFunction();
535 
536         if (sc->func)
537         {
538             /* If the nesting parent is pure without inference,
539              * then this function defaults to pure too.
540              *
541              *  auto foo() pure {
542              *    auto bar() {}     // become a weak purity funciton
543              *    class C {         // nested class
544              *      auto baz() {}   // become a weak purity funciton
545              *    }
546              *
547              *    static auto boo() {}   // typed as impure
548              *    // Even though, boo cannot call any impure functions.
549              *    // See also Expression::checkPurity().
550              *  }
551              */
552             if (tf->purity == PUREimpure && (isNested() || isThis()))
553             {
554                 FuncDeclaration *fd = NULL;
555                 for (Dsymbol *p = toParent2(); p; p = p->toParent2())
556                 {
557                     if (AggregateDeclaration *adx = p->isAggregateDeclaration())
558                     {
559                         if (adx->isNested())
560                             continue;
561                         break;
562                     }
563                     if ((fd = p->isFuncDeclaration()) != NULL)
564                         break;
565                 }
566 
567                 /* If the parent's purity is inferred, then this function's purity needs
568                  * to be inferred first.
569                  */
570                 if (fd && fd->isPureBypassingInference() >= PUREweak &&
571                     !isInstantiated())
572                 {
573                     tf->purity = PUREfwdref;            // default to pure
574                 }
575             }
576         }
577 
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;
589 
590         if (isCtorDeclaration())
591         {
592             sc->flags |= SCOPEctor;
593 
594             Type *tret = ad->handleType();
595             assert(tret);
596             tret = tret->addStorageClass(storage_class | sc->stc);
597             tret = tret->addMod(type->mod);
598             tf->next = tret;
599 
600             if (ad->isStructDeclaration())
601                 sc->stc |= STCref;
602         }
603 
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))
606             sc->stc |= STCscope;
607 
608         // If 'this' has no pointers, remove 'scope' as it has no meaning
609         if (sc->stc & STCscope && ad && ad->isStructDeclaration() && !ad->type->hasPointers())
610         {
611             sc->stc &= ~STCscope;
612             tf->isscope = false;
613         }
614 
615         sc->linkage = linkage;
616 
617         if (!tf->isNaked() && !(isThis() || isNested()))
618         {
619             OutBuffer buf;
620             MODtoBuffer(&buf, tf->mod);
621             error("without 'this' cannot be %s", buf.peekString());
622             tf->mod = 0;    // remove qualifiers
623         }
624 
625         /* Apply const, immutable, wild and shared storage class
626          * to the function type. Do this before type semantic.
627          */
628         StorageClass stc = storage_class;
629         if (type->isImmutable())
630             stc |= STCimmutable;
631         if (type->isConst())
632             stc |= STCconst;
633         if (type->isShared() || storage_class & STCsynchronized)
634             stc |= STCshared;
635         if (type->isWild())
636             stc |= STCwild;
637         switch (stc & STC_TYPECTOR)
638         {
639             case STCimmutable:
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();
649                 break;
650 
651             case STCconst:
652                 type = type->makeConst();
653                 break;
654 
655             case STCwild:
656                 type = type->makeWild();
657                 break;
658 
659             case STCwild | STCconst:
660                 type = type->makeWildConst();
661                 break;
662 
663             case STCshared:
664                 type = type->makeShared();
665                 break;
666 
667             case STCshared | STCconst:
668                 type = type->makeSharedConst();
669                 break;
670 
671             case STCshared | STCwild:
672                 type = type->makeSharedWild();
673                 break;
674 
675             case STCshared | STCwild | STCconst:
676                 type = type->makeSharedWildConst();
677                 break;
678 
679             case 0:
680                 break;
681 
682             default:
683                 assert(0);
684         }
685 
686         type = type->semantic(loc, sc);
687         sc = sc->pop();
688     }
689     if (type->ty != Tfunction)
690     {
691         if (type->ty != Terror)
692         {
693             error("%s must be a function instead of %s", toChars(), type->toChars());
694             type = Type::terror;
695         }
696         errors = true;
697         return;
698     }
699     else
700     {
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();
705         tfo->mod        = tfx->mod;
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;
714 
715         storage_class &= ~(STC_TYPECTOR | STC_FUNCATTR);
716     }
717 
718     f = (TypeFunction *)type;
719 
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'
723      */
724     if (f->isscope && !isNested() && !ad)
725     {
726         error("functions cannot be scope");
727     }
728 
729     if (f->isreturn && !needThis() && !isNested())
730     {
731         /* Non-static nested functions have a hidden 'this' pointer to which
732          * the 'return' applies
733          */
734         error("static member has no 'this' to which 'return' can apply");
735     }
736 
737     if (isAbstract() && !isVirtual())
738     {
739         const char *sfunc;
740         if (isStatic())
741             sfunc = "static";
742         else if (protection.kind == PROTprivate || protection.kind == PROTpackage)
743             sfunc = protectionToChars(protection.kind);
744         else
745             sfunc = "non-virtual";
746         error("%s functions cannot be abstract", sfunc);
747     }
748 
749     if (isOverride() && !isVirtual())
750     {
751         PROTKIND kind = prot().kind;
752         if ((kind == PROTprivate || kind == PROTpackage) && isMember())
753             error("%s method is not virtual and cannot override", protectionToChars(kind));
754         else
755             error("cannot override a non-virtual function");
756     }
757 
758     if (isAbstract() && isFinalFunc())
759         error("cannot be both final and abstract");
760 
761     id = parent->isInterfaceDeclaration();
762     if (id)
763     {
764         storage_class |= STCabstract;
765 
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());
774     }
775 
776     if (UnionDeclaration *ud = parent->isUnionDeclaration())
777     {
778         if (isPostBlitDeclaration() ||
779             isDtorDeclaration() ||
780             isInvariantDeclaration())
781             error("destructors, postblits and invariants are not allowed in union %s", ud->toChars());
782     }
783 
784     /* Contracts can only appear without a body when they are virtual interface functions
785      */
786     if (!fbody && (fensure || frequire) && !(id && isVirtual()))
787         error("in and out contracts require function body");
788 
789     if (parent->isStructDeclaration())
790     {
791         if (isCtorDeclaration())
792         {
793             goto Ldone;
794         }
795     }
796 
797     if (ClassDeclaration *cd = parent->isClassDeclaration())
798     {
799         if (isCtorDeclaration())
800         {
801             goto Ldone;
802         }
803 
804         if (storage_class & STCabstract)
805             cd->isabstract = ABSyes;
806 
807         // if static function, do not put in vtbl[]
808         if (!isVirtual())
809         {
810             //printf("\tnot virtual\n");
811             goto Ldone;
812         }
813         // Suppress further errors if the return type is an error
814         if (type->nextOf() == Type::terror)
815             goto Ldone;
816 
817         bool may_override = false;
818         for (size_t i = 0; i < cd->baseclasses->dim; i++)
819         {
820             BaseClass *b = (*cd->baseclasses)[i];
821             ClassDeclaration *cbd = b->type->toBasetype()->isClassHandle();
822             if (!cbd)
823                 continue;
824             for (size_t j = 0; j < cbd->vtbl.dim; j++)
825             {
826                 FuncDeclaration *f2 = cbd->vtbl[j]->isFuncDeclaration();
827                 if (!f2 || f2->ident != ident)
828                     continue;
829                 if (cbd->parent && cbd->parent->isTemplateInstance())
830                 {
831                     if (!f2->functionSemantic())
832                         goto Ldone;
833                 }
834                 may_override = true;
835             }
836         }
837         if (may_override && type->nextOf() == NULL)
838         {
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.
841              */
842             error("return type inference is not supported if may override base class function");
843         }
844 
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[])
847          */
848         int vi = cd->baseClass ? findVtblIndex((Dsymbols*)&cd->baseClass->vtbl, (int)cd->baseClass->vtbl.dim)
849                                : -1;
850 
851         bool doesoverride = false;
852         switch (vi)
853         {
854             case -1:
855         Lintro:
856                 /* Didn't find one, so
857                  * This is an 'introducing' function which gets a new
858                  * slot in the vtbl[].
859                  */
860 
861                 // Verify this doesn't override previous final function
862                 if (cd->baseClass)
863                 {
864                     Dsymbol *s = cd->baseClass->search(loc, ident);
865                     if (s)
866                     {
867                         FuncDeclaration *f2 = s->isFuncDeclaration();
868                         if (f2)
869                         {
870                             f2 = f2->overloadExactMatch(type);
871                             if (f2 && f2->isFinalFunc() && f2->prot().kind != PROTprivate)
872                                 error("cannot override final function %s", f2->toPrettyChars());
873                         }
874                     }
875                 }
876 
877                 /* These quirky conditions mimic what VC++ appears to do
878                  */
879                 if (global.params.mscoff && cd->isCPPclass() &&
880                     cd->baseClass && cd->baseClass->vtbl.dim)
881                 {
882                     /* if overriding an interface function, then this is not
883                      * introducing and don't put it in the class vtbl[]
884                      */
885                     interfaceVirtual = overrideInterface();
886                     if (interfaceVirtual)
887                     {
888                         //printf("\tinterface function %s\n", toChars());
889                         cd->vtblFinal.push(this);
890                         goto Linterfaces;
891                     }
892                 }
893 
894                 if (isFinalFunc())
895                 {
896                     // Don't check here, as it may override an interface function
897                     //if (isOverride())
898                         //error("is marked as override, but does not override any function");
899                     cd->vtblFinal.push(this);
900                 }
901                 else
902                 {
903                     //printf("\tintroducing function %s\n", toChars());
904                     introducing = 1;
905                     if (cd->isCPPclass() && Target::reverseCppOverloads)
906                     {
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++)
910                         {
911                             if (cd->vtbl[i]->ident == ident && cd->vtbl[i]->parent == parent)
912                             {
913                                 vtblIndex = (int)i;
914                                 break;
915                             }
916                         }
917                         // shift all existing functions back
918                         for (int i = (int)cd->vtbl.dim; i > vtblIndex; i--)
919                         {
920                             FuncDeclaration *fd = cd->vtbl[i-1]->isFuncDeclaration();
921                             assert(fd);
922                             fd->vtblIndex++;
923                         }
924                         cd->vtbl.insert(vtblIndex, this);
925                     }
926                     else
927                     {
928                         // Append to end of vtbl[]
929                         vi = (int)cd->vtbl.dim;
930                         cd->vtbl.push(this);
931                         vtblIndex = vi;
932                     }
933                 }
934                 break;
935 
936             case -2:
937                 // can't determine because of forward references
938                 errors = true;
939                 return;
940 
941             default:
942             {
943                 FuncDeclaration *fdv = cd->baseClass->vtbl[vi]->isFuncDeclaration();
944                 FuncDeclaration *fdc = cd->vtbl[vi]->isFuncDeclaration();
945                 // This function is covariant with fdv
946 
947                 if (fdc == this)
948                 {
949                     doesoverride = true;
950                     break;
951                 }
952 
953                 if (fdc->toParent() == parent)
954                 {
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());
959 
960                     // fdc overrides fdv exactly, then this introduces new function.
961                     if (fdc->type->mod == fdv->type->mod && this->type->mod != fdv->type->mod)
962                         goto Lintro;
963                 }
964 
965                 // This function overrides fdv
966                 if (fdv->isFinalFunc())
967                     error("cannot override final function %s", fdv->toPrettyChars());
968 
969                 if (!isOverride())
970                 {
971                     if (fdv->isFuture())
972                     {
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[]
976                         goto Lintro;
977                     }
978                     else
979                     {
980                         int vi2 = findVtblIndex(&cd->baseClass->vtbl, (int)cd->baseClass->vtbl.dim, false);
981                         if (vi2 < 0)
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());
985                         else
986                             ::error(loc, "implicitly overriding base class method %s with %s deprecated; add 'override' attribute",
987                                 fdv->toPrettyChars(), toPrettyChars());
988                     }
989                 }
990 
991                 doesoverride = true;
992                 if (fdc->toParent() == parent)
993                 {
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)
999                     {
1000                         error("multiple overrides of same function");
1001                     }
1002                     else if (!thismixin)    // fdc overrides fdv
1003                     {
1004                         // this doesn't override any function
1005                         break;
1006                     }
1007                 }
1008                 cd->vtbl[vi] = this;
1009                 vtblIndex = vi;
1010 
1011                 /* Remember which functions this overrides
1012                  */
1013                 foverrides.push(fdv);
1014 
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.
1021                  */
1022 
1023                 if (fdv->tintro)
1024                     tintro = fdv->tintro;
1025                 else if (!type->equals(fdv->type))
1026                 {
1027                     /* Only need to have a tintro if the vptr
1028                      * offsets differ
1029                      */
1030                     int offset;
1031                     if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
1032                     {
1033                         tintro = fdv->type;
1034                     }
1035                 }
1036                 break;
1037             }
1038         }
1039 
1040         /* Go through all the interface bases.
1041          * If this function is covariant with any members of those interface
1042          * functions, set the tintro.
1043          */
1044     Linterfaces:
1045         for (size_t i = 0; i < cd->interfaces.length; i++)
1046         {
1047             BaseClass *b = cd->interfaces.ptr[i];
1048             vi = findVtblIndex((Dsymbols *)&b->sym->vtbl, (int)b->sym->vtbl.dim);
1049             switch (vi)
1050             {
1051                 case -1:
1052                     break;
1053 
1054                 case -2:
1055                     // can't determine because of forward references
1056                     errors = true;
1057                     return;
1058 
1059                 default:
1060                 {
1061                     FuncDeclaration *fdv = (FuncDeclaration *)b->sym->vtbl[vi];
1062                     Type *ti = NULL;
1063 
1064                     /* Remember which functions this overrides
1065                      */
1066                     foverrides.push(fdv);
1067 
1068                     /* Should we really require 'override' when implementing
1069                      * an interface function?
1070                      */
1071                     //if (!isOverride())
1072                         //warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
1073 
1074                     if (fdv->tintro)
1075                         ti = fdv->tintro;
1076                     else if (!type->equals(fdv->type))
1077                     {
1078                         /* Only need to have a tintro if the vptr
1079                          * offsets differ
1080                          */
1081                         int offset;
1082                         if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset))
1083                         {
1084                             ti = fdv->type;
1085                         }
1086                     }
1087                     if (ti)
1088                     {
1089                         if (tintro)
1090                         {
1091                             if (!tintro->nextOf()->equals(ti->nextOf()) &&
1092                                 !tintro->nextOf()->isBaseOf(ti->nextOf(), NULL) &&
1093                                 !ti->nextOf()->isBaseOf(tintro->nextOf(), NULL))
1094                             {
1095                                 error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
1096                             }
1097                         }
1098                         tintro = ti;
1099                     }
1100                     goto L2;
1101                 }
1102             }
1103         }
1104 
1105         if (!doesoverride && isOverride() && (type->nextOf() || !may_override))
1106         {
1107             BaseClass *bc = NULL;
1108             Dsymbol *s = NULL;
1109             for (size_t i = 0; i < cd->baseclasses->dim; i++)
1110             {
1111                 bc = (*cd->baseclasses)[i];
1112                 s = bc->sym->search_correct(ident);
1113                 if (s) break;
1114             }
1115 
1116             if (s)
1117                 error("does not override any function, did you mean to override '%s%s'?",
1118                     bc->sym->isCPPclass() ? "extern (C++) " : "", s->toPrettyChars());
1119             else
1120                 error("does not override any function");
1121         }
1122 
1123     L2: ;
1124 
1125         /* Go through all the interface bases.
1126          * Disallow overriding any final functions in the interface(s).
1127          */
1128         for (size_t i = 0; i < cd->interfaces.length; i++)
1129         {
1130             BaseClass *b = cd->interfaces.ptr[i];
1131             if (b->sym)
1132             {
1133                 Dsymbol *s = search_function(b->sym, ident);
1134                 if (s)
1135                 {
1136                     FuncDeclaration *f2 = s->isFuncDeclaration();
1137                     if (f2)
1138                     {
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());
1142                     }
1143                 }
1144             }
1145         }
1146 
1147         if (isOverride())
1148         {
1149             if (storage_class & STCdisable)
1150                 deprecation("overridden functions cannot be annotated @disable");
1151             if (isDeprecated())
1152                 deprecation("deprecated functions cannot be annotated @disable");
1153         }
1154     }
1155     else if (isOverride() && !parent->isTemplateInstance())
1156         error("override only applies to class member functions");
1157 
1158     // Reflect this->type to f because it could be changed by findVtblIndex
1159     f = type->toTypeFunction();
1160 
1161     /* Do not allow template instances to add virtual functions
1162      * to a class.
1163      */
1164     if (isVirtual())
1165     {
1166         TemplateInstance *ti = parent->isTemplateInstance();
1167         if (ti)
1168         {
1169             // Take care of nested templates
1170             while (1)
1171             {
1172                 TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance();
1173                 if (!ti2)
1174                     break;
1175                 ti = ti2;
1176             }
1177 
1178             // If it's a member template
1179             ClassDeclaration *cd = ti->tempdecl->isClassMember();
1180             if (cd)
1181             {
1182                 error("cannot use template to add virtual function to class '%s'", cd->toChars());
1183             }
1184         }
1185     }
1186 
1187     if (isMain())
1188         checkDmain();       // Check main() parameters and return type
1189 
1190 Ldone:
1191     /* Purity and safety can be inferred for some functions by examining
1192      * the function body.
1193      */
1194     if (canInferAttributes(this, sc))
1195         initInferAttributes(this);
1196 
1197     Module::dprogress++;
1198     semanticRun = PASSsemanticdone;
1199 
1200     /* Save scope for possible later use (if we need the
1201      * function internals)
1202      */
1203     _scope = sc->copy();
1204     _scope->setNoFree();
1205 
1206     static bool printedMain = false;  // semantic might run more than once
1207     if (global.params.verbose && !printedMain)
1208     {
1209         const char *type = isMain() ? "main" : isWinMain() ? "winmain" : isDllMain() ? "dllmain" : (const char *)NULL;
1210         Module *mod = sc->_module;
1211 
1212         if (type && mod)
1213         {
1214             printedMain = true;
1215             const char *name = mod->srcfile->toChars();
1216             const char *path = FileName::searchPath(global.path, name, true);
1217             message("entry     %-10s\t%s", type, path ? path : name);
1218         }
1219     }
1220 
1221     if (fbody && isMain() && sc->_module->isRoot())
1222         Compiler::genCmain(sc);
1223 
1224     assert(type->ty != Terror || errors);
1225 }
1226 
semantic2(Scope * sc)1227 void FuncDeclaration::semantic2(Scope *sc)
1228 {
1229     if (semanticRun >= PASSsemantic2done)
1230         return;
1231     assert(semanticRun <= PASSsemantic2);
1232     semanticRun = PASSsemantic2;
1233 
1234     objc()->setSelector(this, sc);
1235     objc()->validateSelector(this);
1236 
1237     if (parent->isClassDeclaration())
1238     {
1239         objc()->checkLinkage(this);
1240     }
1241 }
1242 
1243 /****************************************************
1244  * Determine whether an 'out' contract is declared inside
1245  * the given function or any of its overrides.
1246  * Params:
1247  *      fd = the function to search
1248  * Returns:
1249  *      true    found an 'out' contract
1250  *      false   didn't find one
1251  */
needsFensure(FuncDeclaration * fd)1252 static bool needsFensure(FuncDeclaration *fd)
1253 {
1254     if (fd->fensure)
1255         return true;
1256 
1257     for (size_t i = 0; i < fd->foverrides.dim; i++)
1258     {
1259         FuncDeclaration *fdv = fd->foverrides[i];
1260 
1261         if (fdv->fensure)
1262             return true;
1263 
1264         if (needsFensure(fdv))
1265             return true;
1266     }
1267     return false;
1268 }
1269 
1270 /****************************************************
1271  * Rewrite contracts as nested functions, then call them. Doing it as nested
1272  * functions means that overriding functions can call them.
1273  * Params:
1274  *      fd = the function to rewrite contracts for
1275  */
buildEnsureRequire(FuncDeclaration * fdx)1276 static void buildEnsureRequire(FuncDeclaration *fdx)
1277 {
1278     if (!fdx->isVirtual())
1279         return;
1280 
1281     TypeFunction *f = (TypeFunction *)fdx->type;
1282 
1283     if (fdx->frequire)
1284     {
1285         /*   in { ... }
1286          * becomes:
1287          *   void __require() { ... }
1288          *   __require();
1289          */
1290         Loc loc = fdx->frequire->loc;
1291         TypeFunction *tf = new TypeFunction(NULL, Type::tvoid, 0, LINKd);
1292         tf->isnothrow = f->isnothrow;
1293         tf->isnogc = f->isnogc;
1294         tf->purity = f->purity;
1295         tf->trust = f->trust;
1296         FuncDeclaration *fd = new FuncDeclaration(loc, loc,
1297                                                   Id::require, STCundefined, tf);
1298         fd->fbody = fdx->frequire;
1299         Statement *s1 = new ExpStatement(loc, fd);
1300         Expression *e = new CallExp(loc, new VarExp(loc, fd, false), (Expressions *)NULL);
1301         Statement *s2 = new ExpStatement(loc, e);
1302         fdx->frequire = new CompoundStatement(loc, s1, s2);
1303         fdx->fdrequire = fd;
1304     }
1305 
1306     if (!fdx->outId && f->nextOf() && f->nextOf()->toBasetype()->ty != Tvoid)
1307         fdx->outId = Id::result; // provide a default
1308 
1309     if (fdx->fensure)
1310     {
1311         /*   out (result) { ... }
1312          * becomes:
1313          *   void __ensure(ref tret result) { ... }
1314          *   __ensure(result);
1315          */
1316         Loc loc = fdx->fensure->loc;
1317         Parameters *fparams = new Parameters();
1318         Parameter *p = NULL;
1319         if (fdx->outId)
1320         {
1321             p = new Parameter(STCref | STCconst, f->nextOf(), fdx->outId, NULL);
1322             fparams->push(p);
1323         }
1324         TypeFunction *tf = new TypeFunction(fparams, Type::tvoid, 0, LINKd);
1325         tf->isnothrow = f->isnothrow;
1326         tf->isnogc = f->isnogc;
1327         tf->purity = f->purity;
1328         tf->trust = f->trust;
1329         FuncDeclaration *fd = new FuncDeclaration(loc, loc,
1330                                                   Id::ensure, STCundefined, tf);
1331         fd->fbody = fdx->fensure;
1332         Statement *s1 = new ExpStatement(loc, fd);
1333         Expression *eresult = NULL;
1334         if (fdx->outId)
1335             eresult = new IdentifierExp(loc, fdx->outId);
1336         Expression *e = new CallExp(loc, new VarExp(loc, fd, false), eresult);
1337         Statement *s2 = new ExpStatement(loc, e);
1338         fdx->fensure = new CompoundStatement(loc, s1, s2);
1339         fdx->fdensure = fd;
1340     }
1341 }
1342 
1343 /* Determine if function should add `return 0;`
1344  */
addReturn0(FuncDeclaration * funcdecl)1345 static bool addReturn0(FuncDeclaration *funcdecl)
1346 {
1347     TypeFunction *f = (TypeFunction *)funcdecl->type;
1348 
1349     return f->next->ty == Tvoid &&
1350         (funcdecl->isMain() || (global.params.betterC && funcdecl->isCMain()));
1351 }
1352 
1353 // Do the semantic analysis on the internals of the function.
1354 
semantic3(Scope * sc)1355 void FuncDeclaration::semantic3(Scope *sc)
1356 {
1357     VarDeclaration *_arguments = NULL;
1358 
1359     if (!parent)
1360     {
1361         if (global.errors)
1362             return;
1363         //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
1364         assert(0);
1365     }
1366     if (errors || isError(parent))
1367     {
1368         errors = true;
1369         return;
1370     }
1371     //printf("FuncDeclaration::semantic3('%s.%s', %p, sc = %p, loc = %s)\n", parent->toChars(), toChars(), this, sc, loc.toChars());
1372     //fflush(stdout);
1373     //printf("storage class = x%x %x\n", sc->stc, storage_class);
1374     //{ static int x; if (++x == 2) *(char*)0=0; }
1375     //printf("\tlinkage = %d\n", sc->linkage);
1376 
1377     if (ident == Id::assign && !inuse)
1378     {
1379         if (storage_class & STCinference)
1380         {
1381             /* Bugzilla 15044: For generated opAssign function, any errors
1382              * from its body need to be gagged.
1383              */
1384             unsigned oldErrors = global.startGagging();
1385             ++inuse;
1386             semantic3(sc);
1387             --inuse;
1388             if (global.endGagging(oldErrors))   // if errors happened
1389             {
1390                 // Disable generated opAssign, because some members forbid identity assignment.
1391                 storage_class |= STCdisable;
1392                 fbody = NULL;   // remove fbody which contains the error
1393                 semantic3Errors = false;
1394             }
1395             return;
1396         }
1397     }
1398 
1399     //printf(" sc->incontract = %d\n", (sc->flags & SCOPEcontract));
1400     if (semanticRun >= PASSsemantic3)
1401         return;
1402     semanticRun = PASSsemantic3;
1403     semantic3Errors = false;
1404 
1405     if (!type || type->ty != Tfunction)
1406         return;
1407     TypeFunction *f = (TypeFunction *)type;
1408     if (!inferRetType && f->next->ty == Terror)
1409         return;
1410 
1411     if (!fbody && inferRetType && !f->next)
1412     {
1413         error("has no function body with return type inference");
1414         return;
1415     }
1416 
1417     unsigned oldErrors = global.errors;
1418 
1419     if (frequire)
1420     {
1421         for (size_t i = 0; i < foverrides.dim; i++)
1422         {
1423             FuncDeclaration *fdv = foverrides[i];
1424 
1425             if (fdv->fbody && !fdv->frequire)
1426             {
1427                 error("cannot have an in contract when overriden function %s does not have an in contract", fdv->toPrettyChars());
1428                 break;
1429             }
1430         }
1431     }
1432 
1433     // Remember whether we need to generate an 'out' contract.
1434     bool needEnsure = needsFensure(this);
1435 
1436     if (fbody || frequire || needEnsure)
1437     {
1438         /* Symbol table into which we place parameters and nested functions,
1439          * solely to diagnose name collisions.
1440          */
1441         localsymtab = new DsymbolTable();
1442 
1443         // Establish function scope
1444         ScopeDsymbol *ss = new ScopeDsymbol();
1445         // find enclosing scope symbol, might skip symbol-less CTFE and/or FuncExp scopes
1446         for (Scope *scx = sc; ; scx = scx->enclosing)
1447         {
1448             if (scx->scopesym)
1449             {
1450                 ss->parent = scx->scopesym;
1451                 break;
1452             }
1453         }
1454         ss->loc = loc;
1455         ss->endlinnum = endloc.linnum;
1456         Scope *sc2 = sc->push(ss);
1457         sc2->func = this;
1458         sc2->parent = this;
1459         sc2->callSuper = 0;
1460         sc2->sbreak = NULL;
1461         sc2->scontinue = NULL;
1462         sc2->sw = NULL;
1463         sc2->fes = fes;
1464         sc2->linkage = LINKd;
1465         sc2->stc &= ~(STCauto | STCscope | STCstatic | STCextern | STCabstract |
1466                         STCdeprecated | STCoverride |
1467                         STC_TYPECTOR | STCfinal | STCtls | STCgshared | STCref | STCreturn |
1468                         STCproperty | STCnothrow | STCpure | STCsafe | STCtrusted | STCsystem);
1469         sc2->protection = Prot(PROTpublic);
1470         sc2->explicitProtection = 0;
1471         sc2->aligndecl = NULL;
1472         if (this->ident != Id::require && this->ident != Id::ensure)
1473             sc2->flags = sc->flags & ~SCOPEcontract;
1474         sc2->flags &= ~SCOPEcompile;
1475         sc2->tf = NULL;
1476         sc2->os = NULL;
1477         sc2->noctor = 0;
1478         sc2->userAttribDecl = NULL;
1479         if (sc2->intypeof == 1) sc2->intypeof = 2;
1480         sc2->fieldinit = NULL;
1481         sc2->fieldinit_dim = 0;
1482 
1483         /* Note: When a lambda is defined immediately under aggregate member
1484          * scope, it should be contextless due to prevent interior pointers.
1485          * e.g.
1486          *      // dg points 'this' - it's interior pointer
1487          *      class C { int x; void delegate() dg = (){ this.x = 1; }; }
1488          *
1489          * However, lambdas could be used inside typeof, in order to check
1490          * some expressions varidity at compile time. For such case the lambda
1491          * body can access aggregate instance members.
1492          * e.g.
1493          *      class C { int x; static assert(is(typeof({ this.x = 1; }))); }
1494          *
1495          * To properly accept it, mark these lambdas as member functions.
1496          */
1497         if (FuncLiteralDeclaration *fld = isFuncLiteralDeclaration())
1498         {
1499             if (AggregateDeclaration *ad = isMember2())
1500             {
1501                 if (!sc->intypeof)
1502                 {
1503                     if (fld->tok == TOKdelegate)
1504                         error("cannot be %s members", ad->kind());
1505                     else
1506                         fld->tok = TOKfunction;
1507                 }
1508                 else
1509                 {
1510                     if (fld->tok != TOKfunction)
1511                         fld->tok = TOKdelegate;
1512                 }
1513             }
1514         }
1515 
1516         // Declare 'this'
1517         AggregateDeclaration *ad = isThis();
1518         vthis = declareThis(sc2, ad);
1519         //printf("[%s] ad = %p vthis = %p\n", loc.toChars(), ad, vthis);
1520         //if (vthis) printf("\tvthis->type = %s\n", vthis->type->toChars());
1521 
1522         // Declare hidden variable _arguments[] and _argptr
1523         if (f->varargs == 1)
1524         {
1525             if (f->linkage == LINKd)
1526             {
1527                 // Variadic arguments depend on Typeinfo being defined
1528                 if (!global.params.useTypeInfo || !Type::dtypeinfo || !Type::typeinfotypelist)
1529                 {
1530                     if (!global.params.useTypeInfo)
1531                         error("D-style variadic functions cannot be used with -betterC");
1532                     else if (!Type::typeinfotypelist)
1533                         error("`object.TypeInfo_Tuple` could not be found, but is implicitly used in D-style variadic functions");
1534                     else
1535                         error("`object.TypeInfo` could not be found, but is implicitly used in D-style variadic functions");
1536                     fatal();
1537                 }
1538 
1539                 // Declare _arguments[]
1540                 v_arguments = new VarDeclaration(Loc(), Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
1541                 v_arguments->storage_class |= STCtemp | STCparameter;
1542                 v_arguments->semantic(sc2);
1543                 sc2->insert(v_arguments);
1544                 v_arguments->parent = this;
1545 
1546                 //Type *t = Type::typeinfo->type->constOf()->arrayOf();
1547                 Type *t = Type::dtypeinfo->type->arrayOf();
1548                 _arguments = new VarDeclaration(Loc(), t, Id::_arguments, NULL);
1549                 _arguments->storage_class |= STCtemp;
1550                 _arguments->semantic(sc2);
1551                 sc2->insert(_arguments);
1552                 _arguments->parent = this;
1553             }
1554             if (f->linkage == LINKd || (f->parameters && Parameter::dim(f->parameters)))
1555             {
1556                 // Declare _argptr
1557                 Type *t = Type::tvalist;
1558                 v_argptr = new VarDeclaration(Loc(), t, Id::_argptr, NULL);
1559                 v_argptr->storage_class |= STCtemp;
1560                 v_argptr->semantic(sc2);
1561                 sc2->insert(v_argptr);
1562                 v_argptr->parent = this;
1563             }
1564         }
1565 
1566         /* Declare all the function parameters as variables
1567          * and install them in parameters[]
1568          */
1569         size_t nparams = Parameter::dim(f->parameters);
1570         if (nparams)
1571         {
1572             /* parameters[] has all the tuples removed, as the back end
1573              * doesn't know about tuples
1574              */
1575             parameters = new VarDeclarations();
1576             parameters->reserve(nparams);
1577             for (size_t i = 0; i < nparams; i++)
1578             {
1579                 Parameter *fparam = Parameter::getNth(f->parameters, i);
1580                 Identifier *id = fparam->ident;
1581                 StorageClass stc = 0;
1582                 if (!id)
1583                 {
1584                     /* Generate identifier for un-named parameter,
1585                      * because we need it later on.
1586                      */
1587                     fparam->ident = id = Identifier::generateId("_param_", i);
1588                     stc |= STCtemp;
1589                 }
1590                 Type *vtype = fparam->type;
1591                 VarDeclaration *v = new VarDeclaration(loc, vtype, id, NULL);
1592                 //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars());
1593                 stc |= STCparameter;
1594                 if (f->varargs == 2 && i + 1 == nparams)
1595                     stc |= STCvariadic;
1596                 if (flags & FUNCFLAGinferScope && !(fparam->storageClass & STCscope))
1597                     stc |= STCmaybescope;
1598                 stc |= fparam->storageClass & (STCin | STCout | STCref | STCreturn | STCscope | STClazy | STCfinal | STC_TYPECTOR | STCnodtor);
1599                 v->storage_class = stc;
1600                 v->semantic(sc2);
1601                 if (!sc2->insert(v))
1602                     error("parameter %s.%s is already defined", toChars(), v->toChars());
1603                 else
1604                     parameters->push(v);
1605                 localsymtab->insert(v);
1606                 v->parent = this;
1607             }
1608         }
1609 
1610         // Declare the tuple symbols and put them in the symbol table,
1611         // but not in parameters[].
1612         if (f->parameters)
1613         {
1614             for (size_t i = 0; i < f->parameters->dim; i++)
1615             {
1616                 Parameter *fparam = (*f->parameters)[i];
1617 
1618                 if (!fparam->ident)
1619                     continue;                   // never used, so ignore
1620                 if (fparam->type->ty == Ttuple)
1621                 {
1622                     TypeTuple *t = (TypeTuple *)fparam->type;
1623                     size_t dim = Parameter::dim(t->arguments);
1624                     Objects *exps = new Objects();
1625                     exps->setDim(dim);
1626                     for (size_t j = 0; j < dim; j++)
1627                     {
1628                         Parameter *narg = Parameter::getNth(t->arguments, j);
1629                         assert(narg->ident);
1630                         VarDeclaration *v = sc2->search(Loc(), narg->ident, NULL)->isVarDeclaration();
1631                         assert(v);
1632                         Expression *e = new VarExp(v->loc, v);
1633                         (*exps)[j] = e;
1634                     }
1635                     assert(fparam->ident);
1636                     TupleDeclaration *v = new TupleDeclaration(loc, fparam->ident, exps);
1637                     //printf("declaring tuple %s\n", v->toChars());
1638                     v->isexp = true;
1639                     if (!sc2->insert(v))
1640                         error("parameter %s.%s is already defined", toChars(), v->toChars());
1641                     localsymtab->insert(v);
1642                     v->parent = this;
1643                 }
1644             }
1645         }
1646 
1647         // Precondition invariant
1648         Statement *fpreinv = NULL;
1649         if (addPreInvariant())
1650         {
1651             Expression *e = addInvariant(loc, sc, ad, vthis, isDtorDeclaration() != NULL);
1652             if (e)
1653                 fpreinv = new ExpStatement(Loc(), e);
1654         }
1655 
1656         // Postcondition invariant
1657         Statement *fpostinv = NULL;
1658         if (addPostInvariant())
1659         {
1660             Expression *e = addInvariant(loc, sc, ad, vthis, isCtorDeclaration() != NULL);
1661             if (e)
1662                 fpostinv = new ExpStatement(Loc(), e);
1663         }
1664 
1665         // Pre/Postcondition contract
1666         if (!fbody)
1667             buildEnsureRequire(this);
1668 
1669         Scope *scout = NULL;
1670         if (needEnsure || addPostInvariant())
1671         {
1672             if ((needEnsure && global.params.useOut) || fpostinv)
1673             {
1674                 returnLabel = new LabelDsymbol(Id::returnLabel);
1675             }
1676 
1677             // scope of out contract (need for vresult->semantic)
1678             ScopeDsymbol *sym = new ScopeDsymbol();
1679             sym->parent = sc2->scopesym;
1680             sym->loc = loc;
1681             sym->endlinnum = endloc.linnum;
1682             scout = sc2->push(sym);
1683         }
1684 
1685         if (fbody)
1686         {
1687             ScopeDsymbol *sym = new ScopeDsymbol();
1688             sym->parent = sc2->scopesym;
1689             sym->loc = loc;
1690             sym->endlinnum = endloc.linnum;
1691             sc2 = sc2->push(sym);
1692 
1693             AggregateDeclaration *ad2 = isMember2();
1694 
1695             /* If this is a class constructor
1696              */
1697             if (ad2 && isCtorDeclaration())
1698             {
1699                 allocFieldinit(sc2, ad2->fields.dim);
1700                 for (size_t i = 0; i < ad2->fields.dim; i++)
1701                 {
1702                     VarDeclaration *v = ad2->fields[i];
1703                     v->ctorinit = 0;
1704                 }
1705             }
1706 
1707             if (!inferRetType && retStyle(f) != RETstack)
1708                 nrvo_can = 0;
1709 
1710             bool inferRef = (f->isref && (storage_class & STCauto));
1711 
1712             fbody = ::semantic(fbody, sc2);
1713             if (!fbody)
1714                 fbody = new CompoundStatement(Loc(), new Statements());
1715 
1716             if (naked)
1717             {
1718                 fpreinv = NULL;         // can't accommodate with no stack frame
1719                 fpostinv = NULL;
1720             }
1721 
1722             assert(type == f ||
1723                    (type->ty == Tfunction &&
1724                     f->purity == PUREimpure &&
1725                     ((TypeFunction *)type)->purity >= PUREfwdref));
1726             f = (TypeFunction *)type;
1727 
1728             if (inferRetType)
1729             {
1730                 // If no return type inferred yet, then infer a void
1731                 if (!f->next)
1732                     f->next = Type::tvoid;
1733                 if (f->checkRetType(loc))
1734                     fbody = new ErrorStatement();
1735             }
1736             if (global.params.vcomplex && f->next != NULL)
1737                 f->next->checkComplexTransition(loc);
1738 
1739             if (returns && !fbody->isErrorStatement())
1740             {
1741                 for (size_t i = 0; i < returns->dim; )
1742                 {
1743                     Expression *exp = (*returns)[i]->exp;
1744                     if (exp->op == TOKvar && ((VarExp *)exp)->var == vresult)
1745                     {
1746                         if (addReturn0(this))
1747                             exp->type = Type::tint32;
1748                         else
1749                             exp->type = f->next;
1750                         // Remove `return vresult;` from returns
1751                         returns->remove(i);
1752                         continue;
1753                     }
1754                     if (inferRef && f->isref && !exp->type->constConv(f->next))     // Bugzilla 13336
1755                         f->isref = false;
1756                     i++;
1757                 }
1758             }
1759             if (f->isref)   // Function returns a reference
1760             {
1761                 if (storage_class & STCauto)
1762                     storage_class &= ~STCauto;
1763             }
1764             if (retStyle(f) != RETstack)
1765                 nrvo_can = 0;
1766 
1767             if (fbody->isErrorStatement())
1768                 ;
1769             else if (isStaticCtorDeclaration())
1770             {
1771                 /* It's a static constructor. Ensure that all
1772                  * ctor consts were initialized.
1773                  */
1774                 ScopeDsymbol *pd = toParent()->isScopeDsymbol();
1775                 for (size_t i = 0; i < pd->members->dim; i++)
1776                 {
1777                     Dsymbol *s = (*pd->members)[i];
1778                     s->checkCtorConstInit();
1779                 }
1780             }
1781             else if (ad2 && isCtorDeclaration())
1782             {
1783                 ClassDeclaration *cd = ad2->isClassDeclaration();
1784 
1785                 // Verify that all the ctorinit fields got initialized
1786                 if (!(sc2->callSuper & CSXthis_ctor))
1787                 {
1788                     for (size_t i = 0; i < ad2->fields.dim; i++)
1789                     {
1790                         VarDeclaration *v = ad2->fields[i];
1791                         if (v->isThisDeclaration())
1792                             continue;
1793                         if (v->ctorinit == 0)
1794                         {
1795                             /* Current bugs in the flow analysis:
1796                              * 1. union members should not produce error messages even if
1797                              *    not assigned to
1798                              * 2. structs should recognize delegating opAssign calls as well
1799                              *    as delegating calls to other constructors
1800                              */
1801                             if (v->isCtorinit() && !v->type->isMutable() && cd)
1802                                 error("missing initializer for %s field %s", MODtoChars(v->type->mod), v->toChars());
1803                             else if (v->storage_class & STCnodefaultctor)
1804                                 ::error(loc, "field %s must be initialized in constructor", v->toChars());
1805                             else if (v->type->needsNested())
1806                                 ::error(loc, "field %s must be initialized in constructor, because it is nested struct", v->toChars());
1807                         }
1808                         else
1809                         {
1810                             bool mustInit = (v->storage_class & STCnodefaultctor ||
1811                                              v->type->needsNested());
1812                             if (mustInit && !(sc2->fieldinit[i] & CSXthis_ctor))
1813                             {
1814                                 error("field %s must be initialized but skipped", v->toChars());
1815                             }
1816                         }
1817                     }
1818                 }
1819                 freeFieldinit(sc2);
1820 
1821                 if (cd &&
1822                     !(sc2->callSuper & CSXany_ctor) &&
1823                     cd->baseClass && cd->baseClass->ctor)
1824                 {
1825                     sc2->callSuper = 0;
1826 
1827                     // Insert implicit super() at start of fbody
1828                     FuncDeclaration *fd = resolveFuncCall(Loc(), sc2, cd->baseClass->ctor, NULL, vthis->type, NULL, 1);
1829                     if (!fd)
1830                     {
1831                         error("no match for implicit super() call in constructor");
1832                     }
1833                     else if (fd->storage_class & STCdisable)
1834                     {
1835                         error("cannot call super() implicitly because it is annotated with @disable");
1836                     }
1837                     else
1838                     {
1839                         Expression *e1 = new SuperExp(Loc());
1840                         Expression *e = new CallExp(Loc(), e1);
1841                         e = ::semantic(e, sc2);
1842 
1843                         Statement *s = new ExpStatement(Loc(), e);
1844                         fbody = new CompoundStatement(Loc(), s, fbody);
1845                     }
1846                 }
1847                 //printf("callSuper = x%x\n", sc2->callSuper);
1848             }
1849 
1850             /* https://issues.dlang.org/show_bug.cgi?id=17502
1851              * Wait until after the return type has been inferred before
1852              * generating the contracts for this function, and merging contracts
1853              * from overrides.
1854              *
1855              * https://issues.dlang.org/show_bug.cgi?id=17893
1856              * However should take care to generate this before inferered
1857              * function attributes are applied, such as 'nothrow'.
1858              *
1859              * This was originally at the end of the first semantic pass, but
1860              * required a fix-up to be done here for the '__result' variable
1861              * type of __ensure() inside auto functions, but this didn't work
1862              * if the out parameter was implicit.
1863              */
1864             buildEnsureRequire(this);
1865 
1866             int blockexit = BEnone;
1867             if (!fbody->isErrorStatement())
1868             {
1869                 // Check for errors related to 'nothrow'.
1870                 unsigned int nothrowErrors = global.errors;
1871                 blockexit = blockExit(fbody, this, f->isnothrow);
1872                 if (f->isnothrow && (global.errors != nothrowErrors))
1873                     ::error(loc, "nothrow %s '%s' may throw", kind(), toPrettyChars());
1874                 if (flags & FUNCFLAGnothrowInprocess)
1875                 {
1876                     if (type == f) f = (TypeFunction *)f->copy();
1877                     f->isnothrow = !(blockexit & BEthrow);
1878                 }
1879             }
1880 
1881             if (fbody->isErrorStatement())
1882                 ;
1883             else if (ad2 && isCtorDeclaration())
1884             {
1885                 /* Append:
1886                  *  return this;
1887                  * to function body
1888                  */
1889                 if (blockexit & BEfallthru)
1890                 {
1891                     Statement *s = new ReturnStatement(loc, NULL);
1892                     s = ::semantic(s, sc2);
1893                     fbody = new CompoundStatement(loc, fbody, s);
1894                     hasReturnExp |= (hasReturnExp & 1 ? 16 : 1);
1895                 }
1896             }
1897             else if (fes)
1898             {
1899                 // For foreach(){} body, append a return 0;
1900                 if (blockexit & BEfallthru)
1901                 {
1902                     Expression *e = new IntegerExp(0);
1903                     Statement *s = new ReturnStatement(Loc(), e);
1904                     fbody = new CompoundStatement(Loc(), fbody, s);
1905                     hasReturnExp |= (hasReturnExp & 1 ? 16 : 1);
1906                 }
1907                 assert(!returnLabel);
1908             }
1909             else
1910             {
1911                 const bool inlineAsm = (hasReturnExp & 8) != 0;
1912                 if ((blockexit & BEfallthru) && f->next->ty != Tvoid && !inlineAsm)
1913                 {
1914                     Expression *e;
1915                     if (!hasReturnExp)
1916                         error("has no return statement, but is expected to return a value of type %s", f->next->toChars());
1917                     else
1918                         error("no return exp; or assert(0); at end of function");
1919                     if (global.params.useAssert &&
1920                         !global.params.useInline)
1921                     {
1922                         /* Add an assert(0, msg); where the missing return
1923                          * should be.
1924                          */
1925                         e = new AssertExp(
1926                               endloc,
1927                               new IntegerExp(0),
1928                               new StringExp(loc, const_cast<char *>("missing return expression"))
1929                             );
1930                     }
1931                     else
1932                         e = new HaltExp(endloc);
1933                     e = new CommaExp(Loc(), e, f->next->defaultInit());
1934                     e = ::semantic(e, sc2);
1935                     Statement *s = new ExpStatement(Loc(), e);
1936                     fbody = new CompoundStatement(Loc(), fbody, s);
1937                 }
1938             }
1939 
1940             if (returns)
1941             {
1942                 bool implicit0 = addReturn0(this);
1943                 Type *tret = implicit0 ? Type::tint32 : f->next;
1944                 assert(tret->ty != Tvoid);
1945                 if (vresult || returnLabel)
1946                     buildResultVar(scout ? scout : sc2, tret);
1947 
1948                 /* Cannot move this loop into NrvoWalker, because
1949                  * returns[i] may be in the nested delegate for foreach-body.
1950                  */
1951                 for (size_t i = 0; i < returns->dim; i++)
1952                 {
1953                     ReturnStatement *rs = (*returns)[i];
1954                     Expression *exp = rs->exp;
1955                     if (exp->op == TOKerror)
1956                         continue;
1957                     if (tret->ty == Terror)
1958                     {
1959                         // Bugzilla 13702
1960                         exp = checkGC(sc2, exp);
1961                         continue;
1962                     }
1963 
1964                     if (!exp->implicitConvTo(tret) &&
1965                         parametersIntersect(exp->type))
1966                     {
1967                         if (exp->type->immutableOf()->implicitConvTo(tret))
1968                             exp = exp->castTo(sc2, exp->type->immutableOf());
1969                         else if (exp->type->wildOf()->implicitConvTo(tret))
1970                             exp = exp->castTo(sc2, exp->type->wildOf());
1971                     }
1972                     exp = exp->implicitCastTo(sc2, tret);
1973 
1974                     if (f->isref)
1975                     {
1976                         // Function returns a reference
1977                         exp = exp->toLvalue(sc2, exp);
1978                         checkReturnEscapeRef(sc2, exp, false);
1979                     }
1980                     else
1981                     {
1982                         exp = exp->optimize(WANTvalue);
1983 
1984                         /* Bugzilla 10789:
1985                          * If NRVO is not possible, all returned lvalues should call their postblits.
1986                          */
1987                         if (!nrvo_can)
1988                             exp = doCopyOrMove(sc2, exp);
1989 
1990                         if (tret->hasPointers())
1991                             checkReturnEscape(sc2, exp, false);
1992                     }
1993 
1994                     exp = checkGC(sc2, exp);
1995 
1996                     if (vresult)
1997                     {
1998                         // Create: return vresult = exp;
1999                         exp = new BlitExp(rs->loc, vresult, exp);
2000                         exp->type = vresult->type;
2001 
2002                         if (rs->caseDim)
2003                             exp = Expression::combine(exp, new IntegerExp(rs->caseDim));
2004                     }
2005                     else if (tintro && !tret->equals(tintro->nextOf()))
2006                     {
2007                         exp = exp->implicitCastTo(sc2, tintro->nextOf());
2008                     }
2009                     rs->exp = exp;
2010                 }
2011             }
2012             if (nrvo_var || returnLabel)
2013             {
2014                 NrvoWalker nw;
2015                 nw.fd = this;
2016                 nw.sc = sc2;
2017                 nw.visitStmt(fbody);
2018             }
2019 
2020             sc2 = sc2->pop();
2021         }
2022 
2023         frequire = mergeFrequire(frequire);
2024         fensure = mergeFensure(fensure, outId);
2025 
2026         Statement *freq = frequire;
2027         Statement *fens = fensure;
2028 
2029         /* Do the semantic analysis on the [in] preconditions and
2030          * [out] postconditions.
2031          */
2032         if (freq)
2033         {
2034             /* frequire is composed of the [in] contracts
2035              */
2036             ScopeDsymbol *sym = new ScopeDsymbol();
2037             sym->parent = sc2->scopesym;
2038             sym->loc = loc;
2039             sym->endlinnum = endloc.linnum;
2040             sc2 = sc2->push(sym);
2041             sc2->flags = (sc2->flags & ~SCOPEcontract) | SCOPErequire;
2042 
2043             // BUG: need to error if accessing out parameters
2044             // BUG: need to treat parameters as const
2045             // BUG: need to disallow returns and throws
2046             // BUG: verify that all in and ref parameters are read
2047             freq = ::semantic(freq, sc2);
2048             blockExit(freq, this, false);
2049 
2050             sc2 = sc2->pop();
2051 
2052             if (!global.params.useIn)
2053                 freq = NULL;
2054         }
2055 
2056         if (fens)
2057         {
2058             /* fensure is composed of the [out] contracts
2059              */
2060             if (f->next->ty == Tvoid && outId)
2061                 error("void functions have no result");
2062 
2063             sc2 = scout;    //push
2064             sc2->flags = (sc2->flags & ~SCOPEcontract) | SCOPEensure;
2065 
2066             // BUG: need to treat parameters as const
2067             // BUG: need to disallow returns and throws
2068             if (fensure && f->next->ty != Tvoid)
2069                 buildResultVar(scout, f->next);
2070 
2071             fens = ::semantic(fens, sc2);
2072             blockExit(fens, this, false);
2073 
2074             sc2 = sc2->pop();
2075 
2076             if (!global.params.useOut)
2077                 fens = NULL;
2078         }
2079 
2080         if (fbody && fbody->isErrorStatement())
2081             ;
2082         else
2083         {
2084             Statements *a = new Statements();
2085 
2086             // Merge in initialization of 'out' parameters
2087             if (parameters)
2088             {
2089                 for (size_t i = 0; i < parameters->dim; i++)
2090                 {
2091                     VarDeclaration *v = (*parameters)[i];
2092                     if (v->storage_class & STCout)
2093                     {
2094                         assert(v->_init);
2095                         ExpInitializer *ie = v->_init->isExpInitializer();
2096                         assert(ie);
2097                         if (ie->exp->op == TOKconstruct)
2098                             ie->exp->op = TOKassign; // construction occured in parameter processing
2099                         a->push(new ExpStatement(Loc(), ie->exp));
2100                     }
2101                 }
2102             }
2103 
2104             if (v_argptr)
2105             {
2106                 // Handled in FuncDeclaration::toObjFile
2107                 v_argptr->_init = new VoidInitializer(loc);
2108             }
2109 
2110             if (_arguments)
2111             {
2112                 /* Advance to elements[] member of TypeInfo_Tuple with:
2113                  *  _arguments = v_arguments.elements;
2114                  */
2115                 Expression *e = new VarExp(Loc(), v_arguments);
2116                 e = new DotIdExp(Loc(), e, Id::elements);
2117                 e = new ConstructExp(Loc(), _arguments, e);
2118                 e = ::semantic(e, sc2);
2119 
2120                 _arguments->_init = new ExpInitializer(Loc(), e);
2121                 DeclarationExp *de = new DeclarationExp(Loc(), _arguments);
2122                 a->push(new ExpStatement(Loc(), de));
2123             }
2124 
2125             // Merge contracts together with body into one compound statement
2126 
2127             if (freq || fpreinv)
2128             {
2129                 if (!freq)
2130                     freq = fpreinv;
2131                 else if (fpreinv)
2132                     freq = new CompoundStatement(Loc(), freq, fpreinv);
2133 
2134                 a->push(freq);
2135             }
2136 
2137             if (fbody)
2138                 a->push(fbody);
2139 
2140             if (fens || fpostinv)
2141             {
2142                 if (!fens)
2143                     fens = fpostinv;
2144                 else if (fpostinv)
2145                     fens = new CompoundStatement(Loc(), fpostinv, fens);
2146 
2147                 LabelStatement *ls = new LabelStatement(Loc(), Id::returnLabel, fens);
2148                 returnLabel->statement = ls;
2149                 a->push(returnLabel->statement);
2150 
2151                 if (f->next->ty != Tvoid && vresult)
2152                 {
2153                     // Create: return vresult;
2154                     Expression *e = new VarExp(Loc(), vresult);
2155                     if (tintro)
2156                     {
2157                         e = e->implicitCastTo(sc, tintro->nextOf());
2158                         e = ::semantic(e, sc);
2159                     }
2160                     ReturnStatement *s = new ReturnStatement(Loc(), e);
2161                     a->push(s);
2162                 }
2163             }
2164             if (addReturn0(this))
2165             {
2166                 // Add a return 0; statement
2167                 Statement *s = new ReturnStatement(Loc(), new IntegerExp(0));
2168                 a->push(s);
2169             }
2170 
2171             Statement *sbody = new CompoundStatement(Loc(), a);
2172             /* Append destructor calls for parameters as finally blocks.
2173              */
2174             if (parameters)
2175             {
2176                 for (size_t i = 0; i < parameters->dim; i++)
2177                 {
2178                     VarDeclaration *v = (*parameters)[i];
2179 
2180                     if (v->storage_class & (STCref | STCout | STClazy))
2181                         continue;
2182 
2183                     if (v->needsScopeDtor())
2184                     {
2185                         // same with ExpStatement.scopeCode()
2186                         Statement *s = new DtorExpStatement(Loc(), v->edtor, v);
2187                         v->storage_class |= STCnodtor;
2188 
2189                         s = ::semantic(s, sc2);
2190 
2191                         bool isnothrow = f->isnothrow & !(flags & FUNCFLAGnothrowInprocess);
2192                         int blockexit = blockExit(s, this, isnothrow);
2193                         if (f->isnothrow && isnothrow && blockexit & BEthrow)
2194                             ::error(loc, "nothrow %s '%s' may throw", kind(), toPrettyChars());
2195                         if (flags & FUNCFLAGnothrowInprocess && blockexit & BEthrow)
2196                             f->isnothrow = false;
2197                         if (blockExit(sbody, this, f->isnothrow) == BEfallthru)
2198                             sbody = new CompoundStatement(Loc(), sbody, s);
2199                         else
2200                             sbody = new TryFinallyStatement(Loc(), sbody, s);
2201                     }
2202                 }
2203             }
2204             // from this point on all possible 'throwers' are checked
2205             flags &= ~FUNCFLAGnothrowInprocess;
2206 
2207             if (isSynchronized())
2208             {
2209                 /* Wrap the entire function body in a synchronized statement
2210                  */
2211                 ClassDeclaration *cd = isThis() ? isThis()->isClassDeclaration() : parent->isClassDeclaration();
2212 
2213                 if (cd)
2214                 {
2215                     if (!global.params.is64bit &&
2216                         global.params.isWindows &&
2217                         !isStatic() && !sbody->usesEH() && !global.params.trace)
2218                     {
2219                         /* The back end uses the "jmonitor" hack for syncing;
2220                          * no need to do the sync at this level.
2221                          */
2222                     }
2223                     else
2224                     {
2225                         Expression *vsync;
2226                         if (isStatic())
2227                         {
2228                             // The monitor is in the ClassInfo
2229                             vsync = new DotIdExp(loc, resolve(loc, sc2, cd, false), Id::classinfo);
2230                         }
2231                         else
2232                         {
2233                             // 'this' is the monitor
2234                             vsync = new VarExp(loc, vthis);
2235                         }
2236                         sbody = new PeelStatement(sbody);       // don't redo semantic()
2237                         sbody = new SynchronizedStatement(loc, vsync, sbody);
2238                         sbody = ::semantic(sbody, sc2);
2239                     }
2240                 }
2241                 else
2242                 {
2243                     error("synchronized function %s must be a member of a class", toChars());
2244                 }
2245             }
2246 
2247             // If declaration has no body, don't set sbody to prevent incorrect codegen.
2248             InterfaceDeclaration *id = parent->isInterfaceDeclaration();
2249             if (fbody || (id && (fdensure || fdrequire) && isVirtual()))
2250                 fbody = sbody;
2251         }
2252 
2253         // Fix up forward-referenced gotos
2254         if (gotos)
2255         {
2256             for (size_t i = 0; i < gotos->dim; ++i)
2257             {
2258                 (*gotos)[i]->checkLabel();
2259             }
2260         }
2261 
2262         if (naked && (fensure || frequire))
2263             error("naked assembly functions with contracts are not supported");
2264 
2265         sc2->callSuper = 0;
2266         sc2->pop();
2267     }
2268 
2269     if (checkClosure())
2270     {
2271         // We should be setting errors here instead of relying on the global error count.
2272         //errors = true;
2273     }
2274 
2275     /* If function survived being marked as impure, then it is pure
2276      */
2277     if (flags & FUNCFLAGpurityInprocess)
2278     {
2279         flags &= ~FUNCFLAGpurityInprocess;
2280         if (type == f)
2281             f = (TypeFunction *)f->copy();
2282         f->purity = PUREfwdref;
2283     }
2284 
2285     if (flags & FUNCFLAGsafetyInprocess)
2286     {
2287         flags &= ~FUNCFLAGsafetyInprocess;
2288         if (type == f)
2289             f = (TypeFunction *)f->copy();
2290         f->trust = TRUSTsafe;
2291     }
2292 
2293     if (flags & FUNCFLAGnogcInprocess)
2294     {
2295         flags &= ~FUNCFLAGnogcInprocess;
2296         if (type == f)
2297             f = (TypeFunction *)f->copy();
2298         f->isnogc = true;
2299     }
2300 
2301     if (flags & FUNCFLAGreturnInprocess)
2302     {
2303         flags &= ~FUNCFLAGreturnInprocess;
2304         if (storage_class & STCreturn)
2305         {
2306             if (type == f)
2307                 f = (TypeFunction *)f->copy();
2308             f->isreturn = true;
2309         }
2310     }
2311 
2312     flags &= ~FUNCFLAGinferScope;
2313 
2314     // Infer STCscope
2315     if (parameters)
2316     {
2317         size_t nfparams = Parameter::dim(f->parameters);
2318         assert(nfparams == parameters->dim);
2319         for (size_t u = 0; u < parameters->dim; u++)
2320         {
2321             VarDeclaration *v = (*parameters)[u];
2322             if (v->storage_class & STCmaybescope)
2323             {
2324                 //printf("Inferring scope for %s\n", v->toChars());
2325                 Parameter *p = Parameter::getNth(f->parameters, u);
2326                 v->storage_class &= ~STCmaybescope;
2327                 v->storage_class |= STCscope | STCscopeinferred;
2328                 p->storageClass |= STCscope | STCscopeinferred;
2329                 assert(!(p->storageClass & STCmaybescope));
2330             }
2331         }
2332     }
2333 
2334     if (vthis && vthis->storage_class & STCmaybescope)
2335     {
2336         vthis->storage_class &= ~STCmaybescope;
2337         vthis->storage_class |= STCscope | STCscopeinferred;
2338         f->isscope = true;
2339         f->isscopeinferred = true;
2340     }
2341 
2342     // reset deco to apply inference result to mangled name
2343     if (f != type)
2344         f->deco = NULL;
2345 
2346     // Do semantic type AFTER pure/nothrow inference.
2347     if (!f->deco && ident != Id::xopEquals && ident != Id::xopCmp)
2348     {
2349         sc = sc->push();
2350         if (isCtorDeclaration()) // Bugzilla #15665
2351             sc->flags |= SCOPEctor;
2352         sc->stc = 0;
2353         sc->linkage = linkage;  // Bugzilla 8496
2354         type = f->semantic(loc, sc);
2355         sc = sc->pop();
2356     }
2357 
2358     /* If this function had instantiated with gagging, error reproduction will be
2359      * done by TemplateInstance::semantic.
2360      * Otherwise, error gagging should be temporarily ungagged by functionSemantic3.
2361      */
2362     semanticRun = PASSsemantic3done;
2363     semantic3Errors = (global.errors != oldErrors) || (fbody && fbody->isErrorStatement());
2364     if (type->ty == Terror)
2365         errors = true;
2366     //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
2367     //fflush(stdout);
2368 }
2369 
2370 /****************************************************
2371  * Resolve forward reference of function signature -
2372  * parameter types, return type, and attributes.
2373  * Returns false if any errors exist in the signature.
2374  */
functionSemantic()2375 bool FuncDeclaration::functionSemantic()
2376 {
2377     if (!_scope)
2378         return !errors;
2379 
2380     if (!originalType)      // semantic not yet run
2381     {
2382         TemplateInstance *spec = isSpeculative();
2383         unsigned olderrs = global.errors;
2384         unsigned oldgag = global.gag;
2385         if (global.gag && !spec)
2386             global.gag = 0;
2387         semantic(_scope);
2388         global.gag = oldgag;
2389         if (spec && global.errors != olderrs)
2390             spec->errors = (global.errors - olderrs != 0);
2391         if (olderrs != global.errors)   // if errors compiling this function
2392             return false;
2393     }
2394 
2395     // if inferring return type, sematic3 needs to be run
2396     // - When the function body contains any errors, we cannot assume
2397     //   the inferred return type is valid.
2398     //   So, the body errors should become the function signature error.
2399     if (inferRetType && type && !type->nextOf())
2400         return functionSemantic3();
2401 
2402     TemplateInstance *ti;
2403     if (isInstantiated() && !isVirtualMethod() &&
2404         ((ti = parent->isTemplateInstance()) == NULL || ti->isTemplateMixin() || ti->tempdecl->ident == ident))
2405     {
2406         AggregateDeclaration *ad = isMember2();
2407         if (ad && ad->sizeok != SIZEOKdone)
2408         {
2409             /* Currently dmd cannot resolve forward references per methods,
2410              * then setting SIZOKfwd is too conservative and would break existing code.
2411              * So, just stop method attributes inference until ad->semantic() done.
2412              */
2413             //ad->sizeok = SIZEOKfwd;
2414         }
2415         else
2416             return functionSemantic3() || !errors;
2417     }
2418 
2419     if (storage_class & STCinference)
2420         return functionSemantic3() || !errors;
2421 
2422     return !errors;
2423 }
2424 
2425 /****************************************************
2426  * Resolve forward reference of function body.
2427  * Returns false if any errors exist in the body.
2428  */
functionSemantic3()2429 bool FuncDeclaration::functionSemantic3()
2430 {
2431     if (semanticRun < PASSsemantic3 && _scope)
2432     {
2433         /* Forward reference - we need to run semantic3 on this function.
2434          * If errors are gagged, and it's not part of a template instance,
2435          * we need to temporarily ungag errors.
2436          */
2437         TemplateInstance *spec = isSpeculative();
2438         unsigned olderrs = global.errors;
2439         unsigned oldgag = global.gag;
2440         if (global.gag && !spec)
2441             global.gag = 0;
2442         semantic3(_scope);
2443         global.gag = oldgag;
2444 
2445         // If it is a speculatively-instantiated template, and errors occur,
2446         // we need to mark the template as having errors.
2447         if (spec && global.errors != olderrs)
2448             spec->errors = (global.errors - olderrs != 0);
2449         if (olderrs != global.errors)   // if errors compiling this function
2450             return false;
2451     }
2452 
2453     return !errors && !semantic3Errors;
2454 }
2455 
2456 /****************************************************
2457  * Check that this function type is properly resolved.
2458  * If not, report "forward reference error" and return true.
2459  */
checkForwardRef(Loc loc)2460 bool FuncDeclaration::checkForwardRef(Loc loc)
2461 {
2462     if (!functionSemantic())
2463         return true;
2464 
2465     /* No deco means the functionSemantic() call could not resolve
2466      * forward referenes in the type of this function.
2467      */
2468     if (!type->deco)
2469     {
2470         bool inSemantic3 = (inferRetType && semanticRun >= PASSsemantic3);
2471         ::error(loc, "forward reference to %s'%s'",
2472             (inSemantic3 ? "inferred return type of function " : ""),
2473             toChars());
2474         return true;
2475     }
2476     return false;
2477 }
2478 
declareThis(Scope * sc,AggregateDeclaration * ad)2479 VarDeclaration *FuncDeclaration::declareThis(Scope *sc, AggregateDeclaration *ad)
2480 {
2481     if (ad)
2482     {
2483         VarDeclaration *v;
2484         {
2485             //printf("declareThis() %s\n", toChars());
2486             Type *thandle = ad->handleType();
2487             assert(thandle);
2488             thandle = thandle->addMod(type->mod);
2489             thandle = thandle->addStorageClass(storage_class);
2490             v = new ThisDeclaration(loc, thandle);
2491             v->storage_class |= STCparameter;
2492             if (thandle->ty == Tstruct)
2493             {
2494                 v->storage_class |= STCref;
2495 
2496                 // if member function is marked 'inout', then 'this' is 'return ref'
2497                 if (type->ty == Tfunction && ((TypeFunction *)type)->iswild & 2)
2498                     v->storage_class |= STCreturn;
2499             }
2500             if (type->ty == Tfunction)
2501             {
2502                 TypeFunction *tf = (TypeFunction *)type;
2503                 if (tf->isreturn)
2504                     v->storage_class |= STCreturn;
2505                 if (tf->isscope)
2506                     v->storage_class |= STCscope;
2507             }
2508             if (flags & FUNCFLAGinferScope && !(v->storage_class & STCscope))
2509                 v->storage_class |= STCmaybescope;
2510 
2511             v->semantic(sc);
2512             if (!sc->insert(v))
2513                 assert(0);
2514             v->parent = this;
2515             return v;
2516         }
2517     }
2518     else if (isNested())
2519     {
2520         /* The 'this' for a nested function is the link to the
2521          * enclosing function's stack frame.
2522          * Note that nested functions and member functions are disjoint.
2523          */
2524         VarDeclaration *v = new ThisDeclaration(loc, Type::tvoid->pointerTo());
2525         v->storage_class |= STCparameter;
2526         if (type->ty == Tfunction)
2527         {
2528             TypeFunction *tf = (TypeFunction *)type;
2529             if (tf->isreturn)
2530                 v->storage_class |= STCreturn;
2531             if (tf->isscope)
2532                 v->storage_class |= STCscope;
2533         }
2534         if (flags & FUNCFLAGinferScope && !(v->storage_class & STCscope))
2535             v->storage_class |= STCmaybescope;
2536 
2537         v->semantic(sc);
2538         if (!sc->insert(v))
2539             assert(0);
2540         v->parent = this;
2541         return v;
2542     }
2543 
2544     return NULL;
2545 }
2546 
equals(RootObject * o)2547 bool FuncDeclaration::equals(RootObject *o)
2548 {
2549     if (this == o)
2550         return true;
2551 
2552     Dsymbol *s = isDsymbol(o);
2553     if (s)
2554     {
2555         FuncDeclaration *fd1 = this;
2556         FuncDeclaration *fd2 = s->isFuncDeclaration();
2557         if (!fd2)
2558             return false;
2559 
2560         FuncAliasDeclaration *fa1 = fd1->isFuncAliasDeclaration();
2561         FuncAliasDeclaration *fa2 = fd2->isFuncAliasDeclaration();
2562         if (fa1 && fa2)
2563         {
2564             return fa1->toAliasFunc()->equals(fa2->toAliasFunc()) &&
2565                    fa1->hasOverloads == fa2->hasOverloads;
2566         }
2567 
2568         if (fa1 && (fd1 = fa1->toAliasFunc())->isUnique() && !fa1->hasOverloads)
2569             fa1 = NULL;
2570         if (fa2 && (fd2 = fa2->toAliasFunc())->isUnique() && !fa2->hasOverloads)
2571             fa2 = NULL;
2572         if ((fa1 != NULL) != (fa2 != NULL))
2573             return false;
2574 
2575         return fd1->toParent()->equals(fd2->toParent()) &&
2576             fd1->ident->equals(fd2->ident) && fd1->type->equals(fd2->type);
2577     }
2578     return false;
2579 }
2580 
2581 /****************************************************
2582  * Declare result variable lazily.
2583  */
2584 
buildResultVar(Scope * sc,Type * tret)2585 void FuncDeclaration::buildResultVar(Scope *sc, Type *tret)
2586 {
2587     if (!vresult)
2588     {
2589         Loc loc = fensure ? fensure->loc : this->loc;
2590 
2591         /* If inferRetType is true, tret may not be a correct return type yet.
2592          * So, in here it may be a temporary type for vresult, and after
2593          * fbody->semantic() running, vresult->type might be modified.
2594          */
2595         vresult = new VarDeclaration(loc, tret, outId ? outId : Id::result, NULL);
2596         vresult->storage_class |= STCnodtor;
2597 
2598         if (outId == Id::result)
2599             vresult->storage_class |= STCtemp;
2600         if (!isVirtual())
2601             vresult->storage_class |= STCconst;
2602         vresult->storage_class |= STCresult;
2603 
2604         // set before the semantic() for checkNestedReference()
2605         vresult->parent = this;
2606     }
2607 
2608     if (sc && vresult->semanticRun == PASSinit)
2609     {
2610         TypeFunction *tf = type->toTypeFunction();
2611         if (tf->isref)
2612             vresult->storage_class |= STCref;
2613         vresult->type = tret;
2614 
2615         vresult->semantic(sc);
2616 
2617         if (!sc->insert(vresult))
2618             error("out result %s is already defined", vresult->toChars());
2619         assert(vresult->parent == this);
2620     }
2621 }
2622 
2623 /****************************************************
2624  * Merge into this function the 'in' contracts of all it overrides.
2625  * 'in's are OR'd together, i.e. only one of them needs to pass.
2626  */
2627 
mergeFrequire(Statement * sf)2628 Statement *FuncDeclaration::mergeFrequire(Statement *sf)
2629 {
2630     /* If a base function and its override both have an IN contract, then
2631      * only one of them needs to succeed. This is done by generating:
2632      *
2633      * void derived.in() {
2634      *  try {
2635      *    base.in();
2636      *  }
2637      *  catch () {
2638      *    ... body of derived.in() ...
2639      *  }
2640      * }
2641      *
2642      * So if base.in() doesn't throw, derived.in() need not be executed, and the contract is valid.
2643      * If base.in() throws, then derived.in()'s body is executed.
2644      */
2645 
2646     /* Implementing this is done by having the overriding function call
2647      * nested functions (the fdrequire functions) nested inside the overridden
2648      * function. This requires that the stack layout of the calling function's
2649      * parameters and 'this' pointer be in the same place (as the nested
2650      * function refers to them).
2651      * This is easy for the parameters, as they are all on the stack in the same
2652      * place by definition, since it's an overriding function. The problem is
2653      * getting the 'this' pointer in the same place, since it is a local variable.
2654      * We did some hacks in the code generator to make this happen:
2655      *  1. always generate exception handler frame, or at least leave space for it
2656      *     in the frame (Windows 32 SEH only)
2657      *  2. always generate an EBP style frame
2658      *  3. since 'this' is passed in a register that is subsequently copied into
2659      *     a stack local, allocate that local immediately following the exception
2660      *     handler block, so it is always at the same offset from EBP.
2661      */
2662     for (size_t i = 0; i < foverrides.dim; i++)
2663     {
2664         FuncDeclaration *fdv = foverrides[i];
2665 
2666         /* The semantic pass on the contracts of the overridden functions must
2667          * be completed before code generation occurs.
2668          * https://issues.dlang.org/show_bug.cgi?id=3602
2669          */
2670         if (fdv->frequire && fdv->semanticRun != PASSsemantic3done)
2671         {
2672             assert(fdv->_scope);
2673             Scope *sc = fdv->_scope->push();
2674             sc->stc &= ~STCoverride;
2675             fdv->semantic3(sc);
2676             sc->pop();
2677         }
2678 
2679         sf = fdv->mergeFrequire(sf);
2680         if (sf && fdv->fdrequire)
2681         {
2682             //printf("fdv->frequire: %s\n", fdv->frequire->toChars());
2683             /* Make the call:
2684              *   try { __require(); }
2685              *   catch (Throwable) { frequire; }
2686              */
2687             Expression *eresult = NULL;
2688             Expression *e = new CallExp(loc, new VarExp(loc, fdv->fdrequire, false), eresult);
2689             Statement *s2 = new ExpStatement(loc, e);
2690 
2691             Catch *c = new Catch(loc, getThrowable(), NULL, sf);
2692             c->internalCatch = true;
2693             Catches *catches = new Catches();
2694             catches->push(c);
2695             sf = new TryCatchStatement(loc, s2, catches);
2696         }
2697         else
2698             return NULL;
2699     }
2700     return sf;
2701 }
2702 
2703 /****************************************************
2704  * Merge into this function the 'out' contracts of all it overrides.
2705  * 'out's are AND'd together, i.e. all of them need to pass.
2706  */
2707 
mergeFensure(Statement * sf,Identifier * oid)2708 Statement *FuncDeclaration::mergeFensure(Statement *sf, Identifier *oid)
2709 {
2710     /* Same comments as for mergeFrequire(), except that we take care
2711      * of generating a consistent reference to the 'result' local by
2712      * explicitly passing 'result' to the nested function as a reference
2713      * argument.
2714      * This won't work for the 'this' parameter as it would require changing
2715      * the semantic code for the nested function so that it looks on the parameter
2716      * list for the 'this' pointer, something that would need an unknown amount
2717      * of tweaking of various parts of the compiler that I'd rather leave alone.
2718      */
2719     for (size_t i = 0; i < foverrides.dim; i++)
2720     {
2721         FuncDeclaration *fdv = foverrides[i];
2722 
2723         /* The semantic pass on the contracts of the overridden functions must
2724          * be completed before code generation occurs.
2725          * https://issues.dlang.org/show_bug.cgi?id=3602 and
2726          * https://issues.dlang.org/show_bug.cgi?id=5230
2727          */
2728         if (needsFensure(fdv) && fdv->semanticRun != PASSsemantic3done)
2729         {
2730             assert(fdv->_scope);
2731             Scope *sc = fdv->_scope->push();
2732             sc->stc &= ~STCoverride;
2733             fdv->semantic3(sc);
2734             sc->pop();
2735         }
2736 
2737         sf = fdv->mergeFensure(sf, oid);
2738         if (fdv->fdensure)
2739         {
2740             //printf("fdv->fensure: %s\n", fdv->fensure->toChars());
2741             // Make the call: __ensure(result)
2742             Expression *eresult = NULL;
2743             if (outId)
2744             {
2745                 eresult = new IdentifierExp(loc, oid);
2746 
2747                 Type *t1 = fdv->type->nextOf()->toBasetype();
2748                 Type *t2 = this->type->nextOf()->toBasetype();
2749                 if (t1->isBaseOf(t2, NULL))
2750                 {
2751                     /* Making temporary reference variable is necessary
2752                      * in covariant return.
2753                      * See bugzilla 5204 and 10479.
2754                      */
2755                     ExpInitializer *ei = new ExpInitializer(Loc(), eresult);
2756                     VarDeclaration *v = new VarDeclaration(Loc(), t1, Identifier::generateId("__covres"), ei);
2757                     v->storage_class |= STCtemp;
2758                     DeclarationExp *de = new DeclarationExp(Loc(), v);
2759                     VarExp *ve = new VarExp(Loc(), v);
2760                     eresult = new CommaExp(Loc(), de, ve);
2761                 }
2762             }
2763             Expression *e = new CallExp(loc, new VarExp(loc, fdv->fdensure, false), eresult);
2764             Statement *s2 = new ExpStatement(loc, e);
2765 
2766             if (sf)
2767             {
2768                 sf = new CompoundStatement(sf->loc, s2, sf);
2769             }
2770             else
2771                 sf = s2;
2772         }
2773     }
2774     return sf;
2775 }
2776 
2777 /****************************************************
2778  * Determine if 'this' overrides fd.
2779  * Return !=0 if it does.
2780  */
2781 
overrides(FuncDeclaration * fd)2782 int FuncDeclaration::overrides(FuncDeclaration *fd)
2783 {   int result = 0;
2784 
2785     if (fd->ident == ident)
2786     {
2787         int cov = type->covariant(fd->type);
2788         if (cov)
2789         {   ClassDeclaration *cd1 = toParent()->isClassDeclaration();
2790             ClassDeclaration *cd2 = fd->toParent()->isClassDeclaration();
2791 
2792             if (cd1 && cd2 && cd2->isBaseOf(cd1, NULL))
2793                 result = 1;
2794         }
2795     }
2796     return result;
2797 }
2798 
2799 /*************************************************
2800  * Find index of function in vtbl[0..dim] that
2801  * this function overrides.
2802  * Prefer an exact match to a covariant one.
2803  * Params:
2804  *      fix17349 = enable fix https://issues.dlang.org/show_bug.cgi?id=17349
2805  * Returns:
2806  *      -1      didn't find one
2807  *      -2      can't determine because of forward references
2808  */
2809 
findVtblIndex(Dsymbols * vtbl,int dim,bool fix17349)2810 int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim, bool fix17349)
2811 {
2812     //printf("findVtblIndex() %s\n", toChars());
2813     FuncDeclaration *mismatch = NULL;
2814     StorageClass mismatchstc = 0;
2815     int mismatchvi = -1;
2816     int exactvi = -1;
2817     int bestvi = -1;
2818     for (int vi = 0; vi < dim; vi++)
2819     {
2820         FuncDeclaration *fdv = (*vtbl)[vi]->isFuncDeclaration();
2821         if (fdv && fdv->ident == ident)
2822         {
2823             if (type->equals(fdv->type))        // if exact match
2824             {
2825                 if (fdv->parent->isClassDeclaration())
2826                 {
2827                     if (fdv->isFuture())
2828                     {
2829                         bestvi = vi;
2830                         continue;           // keep looking
2831                     }
2832                     return vi;                  // no need to look further
2833                 }
2834 
2835                 if (exactvi >= 0)
2836                 {
2837                     error("cannot determine overridden function");
2838                     return exactvi;
2839                 }
2840                 exactvi = vi;
2841 
2842                 bestvi = vi;
2843                 continue;
2844             }
2845 
2846             StorageClass stc = 0;
2847             int cov = type->covariant(fdv->type, &stc, fix17349);
2848             //printf("\tbaseclass cov = %d\n", cov);
2849             switch (cov)
2850             {
2851                 case 0:         // types are distinct
2852                     break;
2853 
2854                 case 1:
2855                     bestvi = vi;        // covariant, but not identical
2856                     break;              // keep looking for an exact match
2857 
2858                 case 2:
2859                     mismatchvi = vi;
2860                     mismatchstc = stc;
2861                     mismatch = fdv;     // overrides, but is not covariant
2862                     break;              // keep looking for an exact match
2863 
2864                 case 3:
2865                     return -2;  // forward references
2866 
2867                 default:
2868                     assert(0);
2869             }
2870         }
2871     }
2872     if (bestvi == -1 && mismatch)
2873     {
2874         //type->print();
2875         //mismatch->type->print();
2876         //printf("%s %s\n", type->deco, mismatch->type->deco);
2877         //printf("stc = %llx\n", mismatchstc);
2878         if (mismatchstc)
2879         {   // Fix it by modifying the type to add the storage classes
2880             type = type->addStorageClass(mismatchstc);
2881             bestvi = mismatchvi;
2882         }
2883     }
2884     return bestvi;
2885 }
2886 
2887 /*********************************
2888  * If function a function in a base class,
2889  * return that base class.
2890  * Params:
2891  *  cd = class that function is in
2892  * Returns:
2893  *  base class if overriding, NULL if not
2894  */
overrideInterface()2895 BaseClass *FuncDeclaration::overrideInterface()
2896 {
2897     ClassDeclaration *cd = parent->isClassDeclaration();
2898     for (size_t i = 0; i < cd->interfaces.length; i++)
2899     {
2900         BaseClass *b = cd->interfaces.ptr[i];
2901         int v = findVtblIndex((Dsymbols *)&b->sym->vtbl, (int)b->sym->vtbl.dim);
2902         if (v >= 0)
2903             return b;
2904     }
2905     return NULL;
2906 }
2907 
2908 /****************************************************
2909  * Overload this FuncDeclaration with the new one f.
2910  * Return true if successful; i.e. no conflict.
2911  */
2912 
overloadInsert(Dsymbol * s)2913 bool FuncDeclaration::overloadInsert(Dsymbol *s)
2914 {
2915     //printf("FuncDeclaration::overloadInsert(s = %s) this = %s\n", s->toChars(), toChars());
2916     assert(s != this);
2917 
2918     AliasDeclaration *ad = s->isAliasDeclaration();
2919     if (ad)
2920     {
2921         if (overnext)
2922             return overnext->overloadInsert(ad);
2923         if (!ad->aliassym && ad->type->ty != Tident && ad->type->ty != Tinstance)
2924         {
2925             //printf("\tad = '%s'\n", ad->type->toChars());
2926             return false;
2927         }
2928         overnext = ad;
2929         //printf("\ttrue: no conflict\n");
2930         return true;
2931     }
2932     TemplateDeclaration *td = s->isTemplateDeclaration();
2933     if (td)
2934     {
2935         if (!td->funcroot)
2936             td->funcroot = this;
2937         if (overnext)
2938             return overnext->overloadInsert(td);
2939         overnext = td;
2940         return true;
2941     }
2942     FuncDeclaration *fd = s->isFuncDeclaration();
2943     if (!fd)
2944         return false;
2945 
2946     if (overnext)
2947     {
2948         td = overnext->isTemplateDeclaration();
2949         if (td)
2950             fd->overloadInsert(td);
2951         else
2952             return overnext->overloadInsert(fd);
2953     }
2954     overnext = fd;
2955     //printf("\ttrue: no conflict\n");
2956     return true;
2957 }
2958 
2959 /***************************************************
2960  * Visit each overloaded function/template in turn, and call
2961  * (*fp)(param, s) on it.
2962  * Exit when no more, or (*fp)(param, f) returns nonzero.
2963  * Returns:
2964  *      ==0     continue
2965  *      !=0     done
2966  */
2967 
overloadApply(Dsymbol * fstart,void * param,int (* fp)(void *,Dsymbol *))2968 int overloadApply(Dsymbol *fstart, void *param, int (*fp)(void *, Dsymbol *))
2969 {
2970     Dsymbol *d;
2971     Dsymbol *next;
2972     for (d = fstart; d; d = next)
2973     {
2974         if (OverDeclaration *od = d->isOverDeclaration())
2975         {
2976             if (od->hasOverloads)
2977             {
2978                 if (int r = overloadApply(od->aliassym, param, fp))
2979                     return r;
2980             }
2981             else
2982             {
2983                 if (int r = (*fp)(param, od->aliassym))
2984                     return r;
2985             }
2986             next = od->overnext;
2987         }
2988         else if (FuncAliasDeclaration *fa = d->isFuncAliasDeclaration())
2989         {
2990             if (fa->hasOverloads)
2991             {
2992                 if (int r = overloadApply(fa->funcalias, param, fp))
2993                     return r;
2994             }
2995             else
2996             {
2997                 FuncDeclaration *fd = fa->toAliasFunc();
2998                 if (!fd)
2999                 {
3000                     d->error("is aliased to a function");
3001                     break;
3002                 }
3003                 if (int r = (*fp)(param, fd))
3004                     return r;
3005             }
3006             next = fa->overnext;
3007         }
3008         else if (AliasDeclaration *ad = d->isAliasDeclaration())
3009         {
3010             next = ad->toAlias();
3011             if (next == ad)
3012                 break;
3013             if (next == fstart)
3014                 break;
3015         }
3016         else if (TemplateDeclaration *td = d->isTemplateDeclaration())
3017         {
3018             if (int r = (*fp)(param, td))
3019                 return r;
3020             next = td->overnext;
3021         }
3022         else
3023         {
3024             FuncDeclaration *fd = d->isFuncDeclaration();
3025             if (!fd)
3026             {
3027                 d->error("is aliased to a function");
3028                 break;              // BUG: should print error message?
3029             }
3030             if (int r = (*fp)(param, fd))
3031                 return r;
3032             next = fd->overnext;
3033         }
3034     }
3035     return 0;
3036 }
3037 
3038 /********************************************
3039  * If there are no overloads of function f, return that function,
3040  * otherwise return NULL.
3041  */
3042 
isUnique()3043 FuncDeclaration *FuncDeclaration::isUnique()
3044 {
3045   struct ParamUnique
3046   {
3047     static int fp(void *param, Dsymbol *s)
3048     {
3049         FuncDeclaration *f = s->isFuncDeclaration();
3050         if (!f)
3051             return 0;
3052         FuncDeclaration **pf = (FuncDeclaration **)param;
3053 
3054         if (*pf)
3055         {
3056             *pf = NULL;
3057             return 1;               // ambiguous, done
3058         }
3059         else
3060         {
3061             *pf = f;
3062             return 0;
3063         }
3064     }
3065   };
3066     FuncDeclaration *result = NULL;
3067     overloadApply(this, &result, &ParamUnique::fp);
3068     return result;
3069 }
3070 
3071 /********************************************
3072  * Find function in overload list that exactly matches t.
3073  */
3074 
overloadExactMatch(Type * t)3075 FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t)
3076 {
3077   struct ParamExact
3078   {
3079     Type *t;            // type to match
3080     FuncDeclaration *f; // return value
3081 
3082     static int fp(void *param, Dsymbol *s)
3083     {
3084         FuncDeclaration *f = s->isFuncDeclaration();
3085         if (!f)
3086             return 0;
3087         ParamExact *p = (ParamExact *)param;
3088         Type *t = p->t;
3089 
3090         if (t->equals(f->type))
3091         {
3092             p->f = f;
3093             return 1;
3094         }
3095 
3096         /* Allow covariant matches, as long as the return type
3097          * is just a const conversion.
3098          * This allows things like pure functions to match with an impure function type.
3099          */
3100         if (t->ty == Tfunction)
3101         {   TypeFunction *tf = (TypeFunction *)f->type;
3102             if (tf->covariant(t) == 1 &&
3103                 tf->nextOf()->implicitConvTo(t->nextOf()) >= MATCHconst)
3104             {
3105                 p->f = f;
3106                 return 1;
3107             }
3108         }
3109         return 0;
3110     }
3111   };
3112     ParamExact p;
3113     p.t = t;
3114     p.f = NULL;
3115     overloadApply(this, &p, &ParamExact::fp);
3116     return p.f;
3117 }
3118 
MODMatchToBuffer(OutBuffer * buf,unsigned char lhsMod,unsigned char rhsMod)3119 void MODMatchToBuffer(OutBuffer *buf, unsigned char lhsMod, unsigned char rhsMod)
3120 {
3121     bool bothMutable = ((lhsMod & rhsMod) == 0);
3122     bool sharedMismatch = ((lhsMod ^ rhsMod) & MODshared) != 0;
3123     bool sharedMismatchOnly = ((lhsMod ^ rhsMod) == MODshared);
3124 
3125     if (lhsMod & MODshared)
3126         buf->writestring("shared ");
3127     else if (sharedMismatch && !(lhsMod & MODimmutable))
3128         buf->writestring("non-shared ");
3129 
3130     if (bothMutable && sharedMismatchOnly)
3131     { }
3132     else if (lhsMod & MODimmutable)
3133         buf->writestring("immutable ");
3134     else if (lhsMod & MODconst)
3135         buf->writestring("const ");
3136     else if (lhsMod & MODwild)
3137         buf->writestring("inout ");
3138     else
3139         buf->writestring("mutable ");
3140 }
3141 
3142 /********************************************
3143  * Find function in overload list that matches to the 'this' modifier.
3144  * There's four result types.
3145  *
3146  * 1. If the 'tthis' matches only one candidate, it's an "exact match".
3147  *    Returns the function and 'hasOverloads' is set to false.
3148  *      eg. If 'tthis" is mutable and there's only one mutable method.
3149  * 2. If there's two or more match candidates, but a candidate function will be
3150  *    a "better match".
3151  *    Returns the better match function but 'hasOverloads' is set to true.
3152  *      eg. If 'tthis' is mutable, and there's both mutable and const methods,
3153  *          the mutable method will be a better match.
3154  * 3. If there's two or more match candidates, but there's no better match,
3155  *    Returns NULL and 'hasOverloads' is set to true to represent "ambiguous match".
3156  *      eg. If 'tthis' is mutable, and there's two or more mutable methods.
3157  * 4. If there's no candidates, it's "no match" and returns NULL with error report.
3158  *      e.g. If 'tthis' is const but there's no const methods.
3159  */
overloadModMatch(Loc loc,Type * tthis,bool & hasOverloads)3160 FuncDeclaration *FuncDeclaration::overloadModMatch(Loc loc, Type *tthis, bool &hasOverloads)
3161 {
3162     //printf("FuncDeclaration::overloadModMatch('%s')\n", toChars());
3163     Match m;
3164     memset(&m, 0, sizeof(m));
3165     m.last = MATCHnomatch;
3166 
3167   struct ParamMod
3168   {
3169     Match *m;
3170     Type *tthis;
3171 
3172     static int fp(void *param, Dsymbol *s)
3173     {
3174         if (FuncDeclaration *fd = s->isFuncDeclaration())
3175             return ((ParamMod *)param)->fp(fd);
3176         return 0;
3177     }
3178     int fp(FuncDeclaration *f)
3179     {
3180         if (f == m->lastf)          // skip duplicates
3181             return 0;
3182 
3183         m->anyf = f;
3184         TypeFunction *tf = f->type->toTypeFunction();
3185         //printf("tf = %s\n", tf->toChars());
3186 
3187         MATCH match;
3188         if (tthis)   // non-static functions are preferred than static ones
3189         {
3190             if (f->needThis())
3191                 match = f->isCtorDeclaration() ? MATCHexact : MODmethodConv(tthis->mod, tf->mod);
3192             else
3193                 match = MATCHconst; // keep static funciton in overload candidates
3194         }
3195         else            // static functions are preferred than non-static ones
3196         {
3197             if (f->needThis())
3198                 match = MATCHconvert;
3199             else
3200                 match = MATCHexact;
3201         }
3202         if (match != MATCHnomatch)
3203         {
3204             if (match > m->last) goto LfIsBetter;
3205             if (match < m->last) goto LlastIsBetter;
3206 
3207             /* See if one of the matches overrides the other.
3208              */
3209             if (m->lastf->overrides(f)) goto LlastIsBetter;
3210             if (f->overrides(m->lastf)) goto LfIsBetter;
3211 
3212             //printf("\tambiguous\n");
3213             m->nextf = f;
3214             m->count++;
3215             return 0;
3216 
3217         LlastIsBetter:
3218             //printf("\tlastbetter\n");
3219             m->count++; // count up
3220             return 0;
3221 
3222         LfIsBetter:
3223             //printf("\tisbetter\n");
3224             if (m->last <= MATCHconvert)
3225             {
3226                 // clear last secondary matching
3227                 m->nextf = NULL;
3228                 m->count = 0;
3229             }
3230             m->last = match;
3231             m->lastf = f;
3232             m->count++;     // count up
3233             return 0;
3234         }
3235         return 0;
3236     }
3237   };
3238     ParamMod p;
3239     p.m = &m;
3240     p.tthis = tthis;
3241     overloadApply(this, &p, &ParamMod::fp);
3242 
3243     if (m.count == 1)       // exact match
3244     {
3245         hasOverloads = false;
3246     }
3247     else if (m.count > 1)   // better or ambiguous match
3248     {
3249         hasOverloads = true;
3250     }
3251     else                    // no match
3252     {
3253         hasOverloads = true;
3254         TypeFunction *tf = this->type->toTypeFunction();
3255         assert(tthis);
3256         assert(!MODimplicitConv(tthis->mod, tf->mod));  // modifier mismatch
3257         {
3258             OutBuffer thisBuf, funcBuf;
3259             MODMatchToBuffer(&thisBuf, tthis->mod, tf->mod);
3260             MODMatchToBuffer(&funcBuf, tf->mod, tthis->mod);
3261             ::error(loc, "%smethod %s is not callable using a %sobject",
3262                 funcBuf.peekString(), this->toPrettyChars(), thisBuf.peekString());
3263         }
3264     }
3265 
3266     return m.lastf;
3267 }
3268 
3269 /********************************************
3270  * Returns true if function was declared
3271  * directly or indirectly in a unittest block
3272  */
inUnittest()3273 bool FuncDeclaration::inUnittest()
3274 {
3275     Dsymbol *f = this;
3276     do
3277     {
3278         if (f->isUnitTestDeclaration())
3279             return true;
3280         f = f->toParent();
3281     } while (f);
3282 
3283     return false;
3284 }
3285 
3286 /********************************************
3287  * find function template root in overload list
3288  */
3289 
findTemplateDeclRoot()3290 TemplateDeclaration *FuncDeclaration::findTemplateDeclRoot()
3291 {
3292     FuncDeclaration *f = this;
3293     while (f && f->overnext)
3294     {
3295         //printf("f->overnext = %p %s\n", f->overnext, f->overnext->toChars());
3296         TemplateDeclaration *td = f->overnext->isTemplateDeclaration();
3297         if (td)
3298             return td;
3299         f = f->overnext->isFuncDeclaration();
3300     }
3301     return NULL;
3302 }
3303 
3304 /*************************************
3305  * Determine partial specialization order of 'this' vs g.
3306  * This is very similar to TemplateDeclaration::leastAsSpecialized().
3307  * Returns:
3308  *      match   'this' is at least as specialized as g
3309  *      0       g is more specialized than 'this'
3310  */
3311 
leastAsSpecialized(FuncDeclaration * g)3312 MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
3313 {
3314     /* This works by calling g() with f()'s parameters, and
3315      * if that is possible, then f() is at least as specialized
3316      * as g() is.
3317      */
3318 
3319     TypeFunction *tf = type->toTypeFunction();
3320     TypeFunction *tg = g->type->toTypeFunction();
3321     size_t nfparams = Parameter::dim(tf->parameters);
3322 
3323     /* If both functions have a 'this' pointer, and the mods are not
3324      * the same and g's is not const, then this is less specialized.
3325      */
3326     if (needThis() && g->needThis() && tf->mod != tg->mod)
3327     {
3328         if (isCtorDeclaration())
3329         {
3330             if (!MODimplicitConv(tg->mod, tf->mod))
3331                 return MATCHnomatch;
3332         }
3333         else
3334         {
3335             if (!MODimplicitConv(tf->mod, tg->mod))
3336                 return MATCHnomatch;
3337         }
3338     }
3339 
3340     /* Create a dummy array of arguments out of the parameters to f()
3341      */
3342     Expressions args;
3343     args.setDim(nfparams);
3344     for (size_t u = 0; u < nfparams; u++)
3345     {
3346         Parameter *p = Parameter::getNth(tf->parameters, u);
3347         Expression *e;
3348         if (p->storageClass & (STCref | STCout))
3349         {
3350             e = new IdentifierExp(Loc(), p->ident);
3351             e->type = p->type;
3352         }
3353         else
3354             e = p->type->defaultInitLiteral(Loc());
3355         args[u] = e;
3356     }
3357 
3358     MATCH m = (MATCH) tg->callMatch(NULL, &args, 1);
3359     if (m > MATCHnomatch)
3360     {
3361         /* A variadic parameter list is less specialized than a
3362          * non-variadic one.
3363          */
3364         if (tf->varargs && !tg->varargs)
3365             goto L1;    // less specialized
3366 
3367         return m;
3368     }
3369   L1:
3370     return MATCHnomatch;
3371 }
3372 
3373 /// Walk through candidate template overloads and print them in the diagnostics.
3374 struct TemplateCandidateWalker
3375 {
3376     Loc loc;
3377     int numToDisplay;  // max num of overloads to print (-v overrides this).
3378 
3379     /// Count template overloads.
3380     struct CountWalker
3381     {
3382         int numOverloads;
3383 
fpTemplateCandidateWalker::CountWalker3384         static int fp(void *param, Dsymbol *)
3385         {
3386             CountWalker *p = (CountWalker *)param;
3387             ++(p->numOverloads);
3388             return 0;
3389         }
3390     };
3391 
fpTemplateCandidateWalker3392     static int fp(void *param, Dsymbol *s)
3393     {
3394         TemplateDeclaration *t = s->isTemplateDeclaration();
3395         if (!t) return 0;
3396 
3397         TemplateCandidateWalker *p = (TemplateCandidateWalker *)param;
3398 
3399         ::errorSupplemental(t->loc, "%s", t->toPrettyChars());
3400 
3401         if (!global.params.verbose && --(p->numToDisplay) == 0 && t->overnext)
3402         {
3403             // Too many overloads to sensibly display.
3404             // Just show count of remaining overloads.
3405             CountWalker cw;
3406             cw.numOverloads = 0;
3407             overloadApply(t->overnext, &cw, &CountWalker::fp);
3408 
3409             if (cw.numOverloads > 0)
3410                 ::errorSupplemental(p->loc, "... (%d more, -v to show) ...", cw.numOverloads);
3411 
3412             return 1;  // stop iterating
3413         }
3414 
3415         return 0;
3416     }
3417 };
3418 
3419 /// Walk through candidate template overloads and print them in the diagnostics.
3420 struct FuncCandidateWalker
3421 {
3422     Loc loc;
3423     int numToDisplay;  // max num of overloads to print (-v overrides this).
3424 
3425     /// Count function overloads.
3426     struct CountWalker
3427     {
3428         int numOverloads;
3429 
fpFuncCandidateWalker::CountWalker3430         static int fp(void *param, Dsymbol *)
3431         {
3432             CountWalker *p = (CountWalker *)param;
3433             ++(p->numOverloads);
3434             return 0;
3435         }
3436     };
3437 
fpFuncCandidateWalker3438     static int fp(void *param, Dsymbol *s)
3439     {
3440         FuncDeclaration *fd = s->isFuncDeclaration();
3441         TemplateDeclaration *td = s->isTemplateDeclaration();
3442         if (fd)
3443         {
3444             if (fd->errors || fd->type->ty == Terror)
3445                 return 0;
3446 
3447             TypeFunction *tf = (TypeFunction *)fd->type;
3448 
3449             ::errorSupplemental(fd->loc, "%s%s", fd->toPrettyChars(),
3450                 parametersTypeToChars(tf->parameters, tf->varargs));
3451         }
3452         else
3453         {
3454             ::errorSupplemental(td->loc, "%s", td->toPrettyChars());
3455         }
3456 
3457         FuncCandidateWalker *p = (FuncCandidateWalker *)param;
3458         if (global.params.verbose || --(p->numToDisplay) != 0 || !fd)
3459             return 0;
3460 
3461         // Too many overloads to sensibly display.
3462         CountWalker cw;
3463         cw.numOverloads = 0;
3464         overloadApply(fd->overnext, &cw, &CountWalker::fp);
3465 
3466         if (cw.numOverloads > 0)
3467             ::errorSupplemental(p->loc, "... (%d more, -v to show) ...", cw.numOverloads);
3468 
3469         return 1;  // stop iterating
3470     }
3471 };
3472 
3473 /*******************************************
3474  * Given a symbol that could be either a FuncDeclaration or
3475  * a function template, resolve it to a function symbol.
3476  *      loc             instantiation location
3477  *      sc              instantiation scope
3478  *      tiargs          initial list of template arguments
3479  *      tthis           if !NULL, the 'this' pointer argument
3480  *      fargs           arguments to function
3481  *      flags           1: do not issue error message on no match, just return NULL
3482  *                      2: overloadResolve only
3483  */
3484 
resolveFuncCall(Loc loc,Scope * sc,Dsymbol * s,Objects * tiargs,Type * tthis,Expressions * fargs,int flags)3485 FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s,
3486         Objects *tiargs, Type *tthis, Expressions *fargs, int flags)
3487 {
3488     if (!s)
3489         return NULL;                    // no match
3490 
3491     if ((tiargs && arrayObjectIsError(tiargs)) ||
3492         (fargs  && arrayObjectIsError((Objects *)fargs)))
3493     {
3494         return NULL;
3495     }
3496 
3497     Match m;
3498     memset(&m, 0, sizeof(m));
3499     m.last = MATCHnomatch;
3500 
3501     functionResolve(&m, s, loc, sc, tiargs, tthis, fargs);
3502 
3503     if (m.last > MATCHnomatch && m.lastf)
3504     {
3505         if (m.count == 1)   // exactly one match
3506         {
3507             if (!(flags & 1))
3508                 m.lastf->functionSemantic();
3509             return m.lastf;
3510         }
3511         if ((flags & 2) && !tthis && m.lastf->needThis())
3512         {
3513             return m.lastf;
3514         }
3515     }
3516 
3517     /* Failed to find a best match.
3518      * Do nothing or print error.
3519      */
3520     if (m.last <= MATCHnomatch)
3521     {
3522         // error was caused on matched function
3523         if (m.count == 1)
3524             return m.lastf;
3525 
3526         // if do not print error messages
3527         if (flags & 1)
3528             return NULL;    // no match
3529     }
3530 
3531     FuncDeclaration *fd = s->isFuncDeclaration();
3532     OverDeclaration *od = s->isOverDeclaration();
3533     TemplateDeclaration *td = s->isTemplateDeclaration();
3534     if (td && td->funcroot)
3535         s = fd = td->funcroot;
3536 
3537     OutBuffer tiargsBuf;
3538     arrayObjectsToBuffer(&tiargsBuf, tiargs);
3539 
3540     OutBuffer fargsBuf;
3541     fargsBuf.writeByte('(');
3542     argExpTypesToCBuffer(&fargsBuf, fargs);
3543     fargsBuf.writeByte(')');
3544     if (tthis)
3545         tthis->modToBuffer(&fargsBuf);
3546 
3547     const int numOverloadsDisplay = 5; // sensible number to display
3548 
3549     if (!m.lastf && !(flags & 1))   // no match
3550     {
3551         if (td && !fd)  // all of overloads are templates
3552         {
3553             ::error(loc, "%s %s.%s cannot deduce function from argument types !(%s)%s, candidates are:",
3554                     td->kind(), td->parent->toPrettyChars(), td->ident->toChars(),
3555                     tiargsBuf.peekString(), fargsBuf.peekString());
3556 
3557             // Display candidate templates (even if there are no multiple overloads)
3558             TemplateCandidateWalker tcw;
3559             tcw.loc = loc;
3560             tcw.numToDisplay = numOverloadsDisplay;
3561             overloadApply(td, &tcw, &TemplateCandidateWalker::fp);
3562         }
3563         else if (od)
3564         {
3565             ::error(loc, "none of the overloads of '%s' are callable using argument types !(%s)%s",
3566                 od->ident->toChars(), tiargsBuf.peekString(), fargsBuf.peekString());
3567         }
3568         else
3569         {
3570             assert(fd);
3571 
3572             bool hasOverloads = fd->overnext != NULL;
3573             TypeFunction *tf = fd->type->toTypeFunction();
3574             if (tthis && !MODimplicitConv(tthis->mod, tf->mod)) // modifier mismatch
3575             {
3576                 OutBuffer thisBuf, funcBuf;
3577                 MODMatchToBuffer(&thisBuf, tthis->mod, tf->mod);
3578                 MODMatchToBuffer(&funcBuf, tf->mod, tthis->mod);
3579                 if (hasOverloads)
3580                     ::error(loc, "none of the overloads of '%s' are callable using a %sobject, candidates are:",
3581                         fd->ident->toChars(), thisBuf.peekString());
3582                 else
3583                     ::error(loc, "%smethod %s is not callable using a %sobject",
3584                         funcBuf.peekString(), fd->toPrettyChars(), thisBuf.peekString());
3585             }
3586             else
3587             {
3588                 //printf("tf = %s, args = %s\n", tf->deco, (*fargs)[0]->type->deco);
3589                 if (hasOverloads)
3590                     ::error(loc, "none of the overloads of '%s' are callable using argument types %s, candidates are:",
3591                             fd->ident->toChars(), fargsBuf.peekString());
3592                 else
3593                     fd->error(loc, "%s%s is not callable using argument types %s",
3594                         parametersTypeToChars(tf->parameters, tf->varargs),
3595                         tf->modToChars(),
3596                         fargsBuf.peekString());
3597             }
3598 
3599             // Display candidate functions
3600             if (hasOverloads)
3601             {
3602                 FuncCandidateWalker fcw;
3603                 fcw.loc = loc;
3604                 fcw.numToDisplay = numOverloadsDisplay;
3605                 overloadApply(fd, &fcw, &FuncCandidateWalker::fp);
3606             }
3607         }
3608     }
3609     else if (m.nextf)
3610     {
3611         TypeFunction *tf1 = m.lastf->type->toTypeFunction();
3612         TypeFunction *tf2 = m.nextf->type->toTypeFunction();
3613         const char *lastprms = parametersTypeToChars(tf1->parameters, tf1->varargs);
3614         const char *nextprms = parametersTypeToChars(tf2->parameters, tf2->varargs);
3615         ::error(loc, "%s.%s called with argument types %s matches both:\n"
3616                      "%s:     %s%s\nand:\n%s:     %s%s",
3617                 s->parent->toPrettyChars(), s->ident->toChars(),
3618                 fargsBuf.peekString(),
3619                 m.lastf->loc.toChars(), m.lastf->toPrettyChars(), lastprms,
3620                 m.nextf->loc.toChars(), m.nextf->toPrettyChars(), nextprms);
3621     }
3622     return NULL;
3623 }
3624 
3625 /********************************
3626  * Labels are in a separate scope, one per function.
3627  */
3628 
searchLabel(Identifier * ident)3629 LabelDsymbol *FuncDeclaration::searchLabel(Identifier *ident)
3630 {   Dsymbol *s;
3631 
3632     if (!labtab)
3633         labtab = new DsymbolTable();    // guess we need one
3634 
3635     s = labtab->lookup(ident);
3636     if (!s)
3637     {
3638         s = new LabelDsymbol(ident);
3639         labtab->insert(s);
3640     }
3641     return (LabelDsymbol *)s;
3642 }
3643 
3644 /*****************************************
3645  * Determine lexical level difference from 'this' to nested function 'fd'.
3646  * Error if this cannot call fd.
3647  * Returns:
3648  *      0       same level
3649  *      >0      decrease nesting by number
3650  *      -1      increase nesting by 1 (fd is nested within 'this')
3651  *      -2      error
3652  */
3653 
getLevel(Loc loc,Scope * sc,FuncDeclaration * fd)3654 int FuncDeclaration::getLevel(Loc loc, Scope *sc, FuncDeclaration *fd)
3655 {
3656     int level;
3657     Dsymbol *s;
3658     Dsymbol *fdparent;
3659 
3660     //printf("FuncDeclaration::getLevel(fd = '%s')\n", fd->toChars());
3661     fdparent = fd->toParent2();
3662     if (fdparent == this)
3663         return -1;
3664     s = this;
3665     level = 0;
3666     while (fd != s && fdparent != s->toParent2())
3667     {
3668         //printf("\ts = %s, '%s'\n", s->kind(), s->toChars());
3669         FuncDeclaration *thisfd = s->isFuncDeclaration();
3670         if (thisfd)
3671         {
3672             if (!thisfd->isNested() && !thisfd->vthis && !sc->intypeof)
3673                 goto Lerr;
3674         }
3675         else
3676         {
3677             AggregateDeclaration *thiscd = s->isAggregateDeclaration();
3678             if (thiscd)
3679             {
3680                 /* AggregateDeclaration::isNested returns true only when
3681                  * it has a hidden pointer.
3682                  * But, calling the function belongs unrelated lexical scope
3683                  * is still allowed inside typeof.
3684                  *
3685                  * struct Map(alias fun) {
3686                  *   typeof({ return fun(); }) RetType;
3687                  *   // No member function makes Map struct 'not nested'.
3688                  * }
3689                  */
3690                 if (!thiscd->isNested() && !sc->intypeof)
3691                     goto Lerr;
3692             }
3693             else
3694                 goto Lerr;
3695         }
3696 
3697         s = s->toParent2();
3698         assert(s);
3699         level++;
3700     }
3701     return level;
3702 
3703 Lerr:
3704     // Don't give error if in template constraint
3705     if (!(sc->flags & SCOPEconstraint))
3706     {
3707         const char *xstatic = isStatic() ? "static " : "";
3708         // better diagnostics for static functions
3709         ::error(loc, "%s%s %s cannot access frame of function %s",
3710             xstatic, kind(), toPrettyChars(), fd->toPrettyChars());
3711         return -2;
3712     }
3713     return 1;
3714 }
3715 
toPrettyChars(bool QualifyTypes)3716 const char *FuncDeclaration::toPrettyChars(bool QualifyTypes)
3717 {
3718     if (isMain())
3719         return "D main";
3720     else
3721         return Dsymbol::toPrettyChars(QualifyTypes);
3722 }
3723 
3724 /** for diagnostics, e.g. 'int foo(int x, int y) pure' */
toFullSignature()3725 const char *FuncDeclaration::toFullSignature()
3726 {
3727     OutBuffer buf;
3728     functionToBufferWithIdent(type->toTypeFunction(), &buf, toChars());
3729     return buf.extractString();
3730 }
3731 
isMain()3732 bool FuncDeclaration::isMain()
3733 {
3734     return ident == Id::main &&
3735         linkage != LINKc && !isMember() && !isNested();
3736 }
3737 
isCMain()3738 bool FuncDeclaration::isCMain()
3739 {
3740     return ident == Id::main &&
3741         linkage == LINKc && !isMember() && !isNested();
3742 }
3743 
isWinMain()3744 bool FuncDeclaration::isWinMain()
3745 {
3746     //printf("FuncDeclaration::isWinMain() %s\n", toChars());
3747     return ident == Id::WinMain &&
3748         linkage != LINKc && !isMember();
3749 }
3750 
isDllMain()3751 bool FuncDeclaration::isDllMain()
3752 {
3753     return ident == Id::DllMain &&
3754         linkage != LINKc && !isMember();
3755 }
3756 
isExport()3757 bool FuncDeclaration::isExport() const
3758 {
3759     return protection.kind == PROTexport;
3760 }
3761 
isImportedSymbol()3762 bool FuncDeclaration::isImportedSymbol() const
3763 {
3764     //printf("isImportedSymbol()\n");
3765     //printf("protection = %d\n", protection);
3766     return (protection.kind == PROTexport) && !fbody;
3767 }
3768 
3769 // Determine if function goes into virtual function pointer table
3770 
isVirtual()3771 bool FuncDeclaration::isVirtual()
3772 {
3773     if (toAliasFunc() != this)
3774         return toAliasFunc()->isVirtual();
3775 
3776     Dsymbol *p = toParent();
3777     return isMember() &&
3778         !(isStatic() || protection.kind == PROTprivate || protection.kind == PROTpackage) &&
3779         p->isClassDeclaration() &&
3780         !(p->isInterfaceDeclaration() && isFinalFunc());
3781 }
3782 
3783 // Determine if a function is pedantically virtual
3784 
isVirtualMethod()3785 bool FuncDeclaration::isVirtualMethod()
3786 {
3787     if (toAliasFunc() != this)
3788         return toAliasFunc()->isVirtualMethod();
3789 
3790     //printf("FuncDeclaration::isVirtualMethod() %s\n", toChars());
3791     if (!isVirtual())
3792         return false;
3793     // If it's a final method, and does not override anything, then it is not virtual
3794     if (isFinalFunc() && foverrides.dim == 0)
3795     {
3796         return false;
3797     }
3798     return true;
3799 }
3800 
isFinalFunc()3801 bool FuncDeclaration::isFinalFunc()
3802 {
3803     if (toAliasFunc() != this)
3804         return toAliasFunc()->isFinalFunc();
3805 
3806     ClassDeclaration *cd;
3807     return isMember() &&
3808         (Declaration::isFinal() ||
3809          ((cd = toParent()->isClassDeclaration()) != NULL && cd->storage_class & STCfinal));
3810 }
3811 
isCodeseg()3812 bool FuncDeclaration::isCodeseg() const
3813 {
3814     return true;                // functions are always in the code segment
3815 }
3816 
isOverloadable()3817 bool FuncDeclaration::isOverloadable()
3818 {
3819     return true;                // functions can be overloaded
3820 }
3821 
isPure()3822 PURE FuncDeclaration::isPure()
3823 {
3824     //printf("FuncDeclaration::isPure() '%s'\n", toChars());
3825     TypeFunction *tf = type->toTypeFunction();
3826     if (flags & FUNCFLAGpurityInprocess)
3827         setImpure();
3828     if (tf->purity == PUREfwdref)
3829         tf->purityLevel();
3830     PURE purity = tf->purity;
3831     if (purity > PUREweak && isNested())
3832         purity = PUREweak;
3833     if (purity > PUREweak && needThis())
3834     {
3835         // The attribute of the 'this' reference affects purity strength
3836         if (type->mod & MODimmutable)
3837             ;
3838         else if (type->mod & (MODconst | MODwild) && purity >= PUREconst)
3839             purity = PUREconst;
3840         else
3841             purity = PUREweak;
3842     }
3843     tf->purity = purity;
3844     // ^ This rely on the current situation that every FuncDeclaration has a
3845     //   unique TypeFunction.
3846     return purity;
3847 }
3848 
isPureBypassingInference()3849 PURE FuncDeclaration::isPureBypassingInference()
3850 {
3851     if (flags & FUNCFLAGpurityInprocess)
3852         return PUREfwdref;
3853     else
3854         return isPure();
3855 }
3856 
3857 /**************************************
3858  * The function is doing something impure,
3859  * so mark it as impure.
3860  * If there's a purity error, return true.
3861  */
setImpure()3862 bool FuncDeclaration::setImpure()
3863 {
3864     if (flags & FUNCFLAGpurityInprocess)
3865     {
3866         flags &= ~FUNCFLAGpurityInprocess;
3867         if (fes)
3868             fes->func->setImpure();
3869     }
3870     else if (isPure())
3871         return true;
3872     return false;
3873 }
3874 
isSafe()3875 bool FuncDeclaration::isSafe()
3876 {
3877     if (flags & FUNCFLAGsafetyInprocess)
3878         setUnsafe();
3879     return type->toTypeFunction()->trust == TRUSTsafe;
3880 }
3881 
isSafeBypassingInference()3882 bool FuncDeclaration::isSafeBypassingInference()
3883 {
3884     return !(flags & FUNCFLAGsafetyInprocess) && isSafe();
3885 }
3886 
isTrusted()3887 bool FuncDeclaration::isTrusted()
3888 {
3889     if (flags & FUNCFLAGsafetyInprocess)
3890         setUnsafe();
3891     return type->toTypeFunction()->trust == TRUSTtrusted;
3892 }
3893 
3894 /**************************************
3895  * The function is doing something unsave,
3896  * so mark it as unsafe.
3897  * If there's a safe error, return true.
3898  */
setUnsafe()3899 bool FuncDeclaration::setUnsafe()
3900 {
3901     if (flags & FUNCFLAGsafetyInprocess)
3902     {
3903         flags &= ~FUNCFLAGsafetyInprocess;
3904         type->toTypeFunction()->trust = TRUSTsystem;
3905         if (fes)
3906             fes->func->setUnsafe();
3907     }
3908     else if (isSafe())
3909         return true;
3910     return false;
3911 }
3912 
isNogc()3913 bool FuncDeclaration::isNogc()
3914 {
3915     if (flags & FUNCFLAGnogcInprocess)
3916         setGC();
3917     return type->toTypeFunction()->isnogc;
3918 }
3919 
isNogcBypassingInference()3920 bool FuncDeclaration::isNogcBypassingInference()
3921 {
3922     return !(flags & FUNCFLAGnogcInprocess) && isNogc();
3923 }
3924 
3925 /**************************************
3926  * The function is doing something that may allocate with the GC,
3927  * so mark it as not nogc (not no-how).
3928  * Returns:
3929  *      true if function is marked as @nogc, meaning a user error occurred
3930  */
setGC()3931 bool FuncDeclaration::setGC()
3932 {
3933     if (flags & FUNCFLAGnogcInprocess)
3934     {
3935         flags &= ~FUNCFLAGnogcInprocess;
3936         type->toTypeFunction()->isnogc = false;
3937         if (fes)
3938             fes->func->setGC();
3939     }
3940     else if (isNogc())
3941         return true;
3942     return false;
3943 }
3944 
3945 /**************************************
3946  * Returns an indirect type one step from t.
3947  */
3948 
getIndirection(Type * t)3949 Type *getIndirection(Type *t)
3950 {
3951     t = t->baseElemOf();
3952     if (t->ty == Tarray || t->ty == Tpointer)
3953         return t->nextOf()->toBasetype();
3954     if (t->ty == Taarray || t->ty == Tclass)
3955         return t;
3956     if (t->ty == Tstruct)
3957         return t->hasPointers() ? t : NULL; // TODO
3958 
3959     // should consider TypeDelegate?
3960     return NULL;
3961 }
3962 
3963 /**************************************
3964  * Returns true if memory reachable through a reference B to a value of type tb,
3965  * which has been constructed with a reference A to a value of type ta
3966  * available, can alias memory reachable from A based on the types involved
3967  * (either directly or via any number of indirections).
3968  *
3969  * Note that this relation is not symmetric in the two arguments. For example,
3970  * a const(int) reference can point to a pre-existing int, but not the other
3971  * way round.
3972  */
3973 bool traverseIndirections(Type *ta, Type *tb, void *p = NULL, bool reversePass = false)
3974 {
3975     Type *source = ta;
3976     Type *target = tb;
3977     if (reversePass)
3978     {
3979         source = tb;
3980         target = ta;
3981     }
3982 
3983     if (source->constConv(target))
3984         return true;
3985     else if (target->ty == Tvoid && MODimplicitConv(source->mod, target->mod))
3986         return true;
3987 
3988     // No direct match, so try breaking up one of the types (starting with tb).
3989     Type *tbb = tb->toBasetype()->baseElemOf();
3990     if (tbb != tb)
3991         return traverseIndirections(ta, tbb, p, reversePass);
3992 
3993     // context date to detect circular look up
3994     struct Ctxt
3995     {
3996         Ctxt *prev;
3997         Type *type;
3998     };
3999     Ctxt *ctxt = (Ctxt *)p;
4000 
4001     if (tb->ty == Tclass || tb->ty == Tstruct)
4002     {
4003         for (Ctxt *c = ctxt; c; c = c->prev)
4004             if (tb == c->type) return false;
4005         Ctxt c;
4006         c.prev = ctxt;
4007         c.type = tb;
4008 
4009         AggregateDeclaration *sym = tb->toDsymbol(NULL)->isAggregateDeclaration();
4010         for (size_t i = 0; i < sym->fields.dim; i++)
4011         {
4012             VarDeclaration *v = sym->fields[i];
4013             Type *tprmi = v->type->addMod(tb->mod);
4014             //printf("\ttb = %s, tprmi = %s\n", tb->toChars(), tprmi->toChars());
4015             if (traverseIndirections(ta, tprmi, &c, reversePass))
4016                 return true;
4017         }
4018     }
4019     else if (tb->ty == Tarray || tb->ty == Taarray || tb->ty == Tpointer)
4020     {
4021         Type *tind = tb->nextOf();
4022         if (traverseIndirections(ta, tind, ctxt, reversePass))
4023             return true;
4024     }
4025     else if (tb->hasPointers())
4026     {
4027         // FIXME: function pointer/delegate types should be considered.
4028         return true;
4029     }
4030 
4031     // Still no match, so try breaking up ta if we have note done so yet.
4032     if (!reversePass)
4033         return traverseIndirections(tb, ta, ctxt, true);
4034 
4035     return false;
4036 }
4037 
4038 /********************************************
4039  * Returns true if the function return value has no indirection
4040  * which comes from the parameters.
4041  */
4042 
isolateReturn()4043 bool FuncDeclaration::isolateReturn()
4044 {
4045     TypeFunction *tf = type->toTypeFunction();
4046     assert(tf->next);
4047 
4048     Type *treti = tf->next;
4049     treti = tf->isref ? treti : getIndirection(treti);
4050     if (!treti)
4051         return true;    // target has no mutable indirection
4052     return parametersIntersect(treti);
4053 }
4054 
4055 /********************************************
4056  * Returns true if an object typed t can have indirections
4057  * which come from the parameters.
4058  */
4059 
parametersIntersect(Type * t)4060 bool FuncDeclaration::parametersIntersect(Type *t)
4061 {
4062     assert(t);
4063     if (!isPureBypassingInference() || isNested())
4064         return false;
4065 
4066     TypeFunction *tf = type->toTypeFunction();
4067 
4068     //printf("parametersIntersect(%s) t = %s\n", tf->toChars(), t->toChars());
4069 
4070     size_t dim = Parameter::dim(tf->parameters);
4071     for (size_t i = 0; i < dim; i++)
4072     {
4073         Parameter *fparam = Parameter::getNth(tf->parameters, i);
4074         if (!fparam->type)
4075             continue;
4076         Type *tprmi = (fparam->storageClass & (STClazy | STCout | STCref))
4077                 ? fparam->type : getIndirection(fparam->type);
4078         if (!tprmi)
4079             continue;   // there is no mutable indirection
4080 
4081         //printf("\t[%d] tprmi = %d %s\n", i, tprmi->ty, tprmi->toChars());
4082         if (traverseIndirections(tprmi, t))
4083             return false;
4084     }
4085     if (AggregateDeclaration *ad = isCtorDeclaration() ? NULL : isThis())
4086     {
4087         Type *tthis = ad->getType()->addMod(tf->mod);
4088         //printf("\ttthis = %s\n", tthis->toChars());
4089         if (traverseIndirections(tthis, t))
4090             return false;
4091     }
4092 
4093     return true;
4094 }
4095 
4096 /****************************************
4097  * Determine if function needs a static frame pointer.
4098  * Returns:
4099  *  `true` if function is really nested within other function.
4100  * Contracts:
4101  *  If isNested() returns true, isThis() should return false.
4102  */
isNested()4103 bool FuncDeclaration::isNested()
4104 {
4105     FuncDeclaration *f = toAliasFunc();
4106     //printf("\ttoParent2() = '%s'\n", f->toParent2()->toChars());
4107     return ((f->storage_class & STCstatic) == 0) &&
4108            (f->linkage == LINKd) &&
4109            (f->toParent2()->isFuncDeclaration() != NULL);
4110 }
4111 
4112 /****************************************
4113  * Determine if function is a non-static member function
4114  * that has an implicit 'this' expression.
4115  * Returns:
4116  *  The aggregate it is a member of, or null.
4117  * Contracts:
4118  *  If isThis() returns true, isNested() should return false.
4119  */
isThis()4120 AggregateDeclaration *FuncDeclaration::isThis()
4121 {
4122     //printf("+FuncDeclaration::isThis() '%s'\n", toChars());
4123     AggregateDeclaration *ad = (storage_class & STCstatic) ? NULL : isMember2();
4124     //printf("-FuncDeclaration::isThis() %p\n", ad);
4125     return ad;
4126 }
4127 
needThis()4128 bool FuncDeclaration::needThis()
4129 {
4130     //printf("FuncDeclaration::needThis() '%s'\n", toChars());
4131     return toAliasFunc()->isThis() != NULL;
4132 }
4133 
addPreInvariant()4134 bool FuncDeclaration::addPreInvariant()
4135 {
4136     AggregateDeclaration *ad = isThis();
4137     ClassDeclaration *cd = ad ? ad->isClassDeclaration() : NULL;
4138     return (ad && !(cd && cd->isCPPclass()) &&
4139             global.params.useInvariants &&
4140             (protection.kind == PROTprotected || protection.kind == PROTpublic || protection.kind == PROTexport) &&
4141             !naked);
4142 }
4143 
addPostInvariant()4144 bool FuncDeclaration::addPostInvariant()
4145 {
4146     AggregateDeclaration *ad = isThis();
4147     ClassDeclaration *cd = ad ? ad->isClassDeclaration() : NULL;
4148     return (ad && !(cd && cd->isCPPclass()) &&
4149             ad->inv &&
4150             global.params.useInvariants &&
4151             (protection.kind == PROTprotected || protection.kind == PROTpublic || protection.kind == PROTexport) &&
4152             !naked);
4153 }
4154 
4155 /********************************************************
4156  * Generate Expression to call the invariant.
4157  * Input:
4158  *      ad      aggregate with the invariant
4159  *      vthis   variable with 'this'
4160  *      direct  call invariant directly
4161  * Returns:
4162  *      void expression that calls the invariant
4163  */
addInvariant(Loc loc,Scope * sc,AggregateDeclaration * ad,VarDeclaration * vthis,bool direct)4164 Expression *addInvariant(Loc loc, Scope *sc, AggregateDeclaration *ad, VarDeclaration *vthis, bool direct)
4165 {
4166     Expression *e = NULL;
4167     if (direct)
4168     {
4169         // Call invariant directly only if it exists
4170         FuncDeclaration *inv = ad->inv;
4171         ClassDeclaration *cd = ad->isClassDeclaration();
4172 
4173         while (!inv && cd)
4174         {
4175             cd = cd->baseClass;
4176             if (!cd)
4177                 break;
4178             inv = cd->inv;
4179         }
4180         if (inv)
4181         {
4182         #if 1
4183             // Workaround for bugzilla 13394: For the correct mangling,
4184             // run attribute inference on inv if needed.
4185             inv->functionSemantic();
4186         #endif
4187 
4188             //e = new DsymbolExp(Loc(), inv);
4189             //e = new CallExp(Loc(), e);
4190             //e = e->semantic(sc2);
4191 
4192             /* Bugzilla 13113: Currently virtual invariant calls completely
4193              * bypass attribute enforcement.
4194              * Change the behavior of pre-invariant call by following it.
4195              */
4196             e = new ThisExp(Loc());
4197             e->type = vthis->type;
4198             e = new DotVarExp(Loc(), e, inv, false);
4199             e->type = inv->type;
4200             e = new CallExp(Loc(), e);
4201             e->type = Type::tvoid;
4202         }
4203     }
4204     else
4205     {
4206     #if 1
4207         // Workaround for bugzilla 13394: For the correct mangling,
4208         // run attribute inference on inv if needed.
4209         if (ad->isStructDeclaration() && ad->inv)
4210             ad->inv->functionSemantic();
4211     #endif
4212 
4213         // Call invariant virtually
4214         Expression *v = new ThisExp(Loc());
4215         v->type = vthis->type;
4216         if (ad->isStructDeclaration())
4217             v = v->addressOf();
4218         e = new StringExp(Loc(), const_cast<char *>("null this"));
4219         e = new AssertExp(loc, v, e);
4220         e = semantic(e, sc);
4221     }
4222     return e;
4223 }
4224 
4225 /**********************************
4226  * Generate a FuncDeclaration for a runtime library function.
4227  */
4228 
genCfunc(Parameters * fparams,Type * treturn,const char * name,StorageClass stc)4229 FuncDeclaration *FuncDeclaration::genCfunc(Parameters *fparams, Type *treturn, const char *name, StorageClass stc)
4230 {
4231     return genCfunc(fparams, treturn, Identifier::idPool(name), stc);
4232 }
4233 
genCfunc(Parameters * fparams,Type * treturn,Identifier * id,StorageClass stc)4234 FuncDeclaration *FuncDeclaration::genCfunc(Parameters *fparams, Type *treturn, Identifier *id, StorageClass stc)
4235 {
4236     FuncDeclaration *fd;
4237     TypeFunction *tf;
4238     Dsymbol *s;
4239     static DsymbolTable *st = NULL;
4240 
4241     //printf("genCfunc(name = '%s')\n", id->toChars());
4242     //printf("treturn\n\t"); treturn->print();
4243 
4244     // See if already in table
4245     if (!st)
4246         st = new DsymbolTable();
4247     s = st->lookup(id);
4248     if (s)
4249     {
4250         fd = s->isFuncDeclaration();
4251         assert(fd);
4252         assert(fd->type->nextOf()->equals(treturn));
4253     }
4254     else
4255     {
4256         tf = new TypeFunction(fparams, treturn, 0, LINKc, stc);
4257         fd = new FuncDeclaration(Loc(), Loc(), id, STCstatic, tf);
4258         fd->protection = Prot(PROTpublic);
4259         fd->linkage = LINKc;
4260 
4261         st->insert(fd);
4262     }
4263     return fd;
4264 }
4265 
4266 /******************
4267  * Check parameters and return type of D main() function.
4268  * Issue error messages.
4269  */
checkDmain()4270 void FuncDeclaration::checkDmain()
4271 {
4272     TypeFunction *tf = type->toTypeFunction();
4273     const size_t nparams = Parameter::dim(tf->parameters);
4274     bool argerr = false;
4275     if (nparams == 1)
4276     {
4277         Parameter *fparam0 = Parameter::getNth(tf->parameters, 0);
4278         Type *t = fparam0->type->toBasetype();
4279         if (t->ty != Tarray ||
4280             t->nextOf()->ty != Tarray ||
4281             t->nextOf()->nextOf()->ty != Tchar ||
4282             fparam0->storageClass & (STCout | STCref | STClazy))
4283         {
4284             argerr = true;
4285         }
4286     }
4287 
4288     if (!tf->nextOf())
4289         error("must return int or void");
4290     else if (tf->nextOf()->ty != Tint32 && tf->nextOf()->ty != Tvoid)
4291         error("must return int or void, not %s", tf->nextOf()->toChars());
4292     else if (tf->varargs || nparams >= 2 || argerr)
4293         error("parameters must be main() or main(string[] args)");
4294 }
4295 
kind()4296 const char *FuncDeclaration::kind() const
4297 {
4298     return generated ? "generated function" : "function";
4299 }
4300 
4301 /*********************************************
4302  * In the current function, we are calling 'this' function.
4303  * 1. Check to see if the current function can call 'this' function, issue error if not.
4304  * 2. If the current function is not the parent of 'this' function, then add
4305  *    the current function to the list of siblings of 'this' function.
4306  * 3. If the current function is a literal, and it's accessing an uplevel scope,
4307  *    then mark it as a delegate.
4308  * Returns true if error occurs.
4309  */
checkNestedReference(Scope * sc,Loc loc)4310 bool FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
4311 {
4312     //printf("FuncDeclaration::checkNestedReference() %s\n", toPrettyChars());
4313 
4314     if (FuncLiteralDeclaration *fld = this->isFuncLiteralDeclaration())
4315     {
4316         if (fld->tok == TOKreserved)
4317         {
4318             fld->tok = TOKfunction;
4319             fld->vthis = NULL;
4320         }
4321     }
4322 
4323     if (!parent || parent == sc->parent)
4324         return false;
4325     if (ident == Id::require || ident == Id::ensure)
4326         return false;
4327     if (!isThis() && !isNested())
4328         return false;
4329 
4330     // The current function
4331     FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
4332     if (!fdthis)
4333         return false;   // out of function scope
4334 
4335     Dsymbol *p = toParent2();
4336 
4337     // Function literals from fdthis to p must be delegates
4338     checkNestedRef(fdthis, p);
4339 
4340     if (isNested())
4341     {
4342         // The function that this function is in
4343         FuncDeclaration *fdv = p->isFuncDeclaration();
4344         if (!fdv)
4345             return false;
4346         if (fdv == fdthis)
4347             return false;
4348 
4349         //printf("this = %s in [%s]\n", this->toChars(), this->loc.toChars());
4350         //printf("fdv = %s in [%s]\n", fdv->toChars(), fdv->loc.toChars());
4351         //printf("fdthis = %s in [%s]\n", fdthis->toChars(), fdthis->loc.toChars());
4352 
4353         // Add this function to the list of those which called us
4354         if (fdthis != this)
4355         {
4356             bool found = false;
4357             for (size_t i = 0; i < siblingCallers.dim; ++i)
4358             {
4359                 if (siblingCallers[i] == fdthis)
4360                     found = true;
4361             }
4362             if (!found)
4363             {
4364                 //printf("\tadding sibling %s\n", fdthis->toPrettyChars());
4365                 if (!sc->intypeof && !(sc->flags & SCOPEcompile))
4366                     siblingCallers.push(fdthis);
4367             }
4368         }
4369 
4370         int lv = fdthis->getLevel(loc, sc, fdv);
4371         if (lv == -2)
4372             return true;    // error
4373         if (lv == -1)
4374             return false;   // downlevel call
4375         if (lv == 0)
4376             return false;   // same level call
4377         // Uplevel call
4378     }
4379     return false;
4380 }
4381 
4382 /* For all functions between outerFunc and f, mark them as needing
4383  * a closure.
4384  */
markAsNeedingClosure(Dsymbol * f,FuncDeclaration * outerFunc)4385 void markAsNeedingClosure(Dsymbol *f, FuncDeclaration *outerFunc)
4386 {
4387     for (Dsymbol *sx = f; sx && sx != outerFunc; sx = sx->parent)
4388     {
4389         FuncDeclaration *fy = sx->isFuncDeclaration();
4390         if (fy && fy->closureVars.dim)
4391         {
4392             /* fy needs a closure if it has closureVars[],
4393              * because the frame pointer in the closure will be accessed.
4394              */
4395             fy->requiresClosure = true;
4396         }
4397     }
4398 }
4399 
4400 
4401 /* Given a nested function f inside a function outerFunc, check
4402  * if any sibling callers of f have escaped. If so, mark
4403  * all the enclosing functions as needing closures.
4404  * Return true if any closures were detected.
4405  * This is recursive: we need to check the callers of our siblings.
4406  * Note that nested functions can only call lexically earlier nested
4407  * functions, so loops are impossible.
4408  */
4409 bool checkEscapingSiblings(FuncDeclaration *f, FuncDeclaration *outerFunc, void *p = NULL)
4410 {
4411     struct PrevSibling
4412     {
4413         PrevSibling *p;
4414         FuncDeclaration *f;
4415     };
4416 
4417     PrevSibling ps;
4418     ps.p = (PrevSibling *)p;
4419     ps.f = f;
4420 
4421     //printf("checkEscapingSiblings(f = %s, outerfunc = %s)\n", f->toChars(), outerFunc->toChars());
4422     bool bAnyClosures = false;
4423     for (size_t i = 0; i < f->siblingCallers.dim; ++i)
4424     {
4425         FuncDeclaration *g = f->siblingCallers[i];
4426         if (g->isThis() || g->tookAddressOf)
4427         {
4428             markAsNeedingClosure(g, outerFunc);
4429             bAnyClosures = true;
4430         }
4431 
4432         PrevSibling *prev = (PrevSibling *)p;
4433         while (1)
4434         {
4435             if (!prev)
4436             {
4437                 bAnyClosures |= checkEscapingSiblings(g, outerFunc, &ps);
4438                 break;
4439             }
4440             if (prev->f == g)
4441                 break;
4442             prev = prev->p;
4443         }
4444     }
4445     //printf("\t%d\n", bAnyClosures);
4446     return bAnyClosures;
4447 }
4448 
4449 
4450 /*******************************
4451  * Look at all the variables in this function that are referenced
4452  * by nested functions, and determine if a closure needs to be
4453  * created for them.
4454  */
4455 
needsClosure()4456 bool FuncDeclaration::needsClosure()
4457 {
4458     /* Need a closure for all the closureVars[] if any of the
4459      * closureVars[] are accessed by a
4460      * function that escapes the scope of this function.
4461      * We take the conservative approach and decide that a function needs
4462      * a closure if it:
4463      * 1) is a virtual function
4464      * 2) has its address taken
4465      * 3) has a parent that escapes
4466      * 4) calls another nested function that needs a closure
4467      *
4468      * Note that since a non-virtual function can be called by
4469      * a virtual one, if that non-virtual function accesses a closure
4470      * var, the closure still has to be taken. Hence, we check for isThis()
4471      * instead of isVirtual(). (thanks to David Friedman)
4472      *
4473      * When the function returns a local struct or class, `requiresClosure`
4474      * is already set to `true` upon entering this function when the
4475      * struct/class refers to a local variable and a closure is needed.
4476      */
4477 
4478     //printf("FuncDeclaration::needsClosure() %s\n", toChars());
4479 
4480     if (requiresClosure)
4481         goto Lyes;
4482 
4483     for (size_t i = 0; i < closureVars.dim; i++)
4484     {
4485         VarDeclaration *v = closureVars[i];
4486         //printf("\tv = %s\n", v->toChars());
4487 
4488         for (size_t j = 0; j < v->nestedrefs.dim; j++)
4489         {
4490             FuncDeclaration *f = v->nestedrefs[j];
4491             assert(f != this);
4492 
4493             //printf("\t\tf = %s, isVirtual=%d, isThis=%p, tookAddressOf=%d\n", f->toChars(), f->isVirtual(), f->isThis(), f->tookAddressOf);
4494 
4495             /* Look to see if f escapes. We consider all parents of f within
4496              * this, and also all siblings which call f; if any of them escape,
4497              * so does f.
4498              * Mark all affected functions as requiring closures.
4499              */
4500             for (Dsymbol *s = f; s && s != this; s = s->parent)
4501             {
4502                 FuncDeclaration *fx = s->isFuncDeclaration();
4503                 if (!fx)
4504                     continue;
4505                 if (fx->isThis() || fx->tookAddressOf)
4506                 {
4507                     //printf("\t\tfx = %s, isVirtual=%d, isThis=%p, tookAddressOf=%d\n", fx->toChars(), fx->isVirtual(), fx->isThis(), fx->tookAddressOf);
4508 
4509                     /* Mark as needing closure any functions between this and f
4510                      */
4511                     markAsNeedingClosure( (fx == f) ? fx->parent : fx, this);
4512 
4513                     requiresClosure = true;
4514                 }
4515 
4516                 /* We also need to check if any sibling functions that
4517                  * called us, have escaped. This is recursive: we need
4518                  * to check the callers of our siblings.
4519                  */
4520                 if (checkEscapingSiblings(fx, this))
4521                     requiresClosure = true;
4522 
4523                 /* Bugzilla 12406: Iterate all closureVars to mark all descendant
4524                  * nested functions that access to the closing context of this funciton.
4525                  */
4526             }
4527         }
4528     }
4529     if (requiresClosure)
4530         goto Lyes;
4531 
4532     return false;
4533 
4534 Lyes:
4535     //printf("\tneeds closure\n");
4536     return true;
4537 }
4538 
4539 /***********************************************
4540  * Check that the function contains any closure.
4541  * If it's @nogc, report suitable errors.
4542  * This is mostly consistent with FuncDeclaration::needsClosure().
4543  *
4544  * Returns:
4545  *      true if any errors occur.
4546  */
checkClosure()4547 bool FuncDeclaration::checkClosure()
4548 {
4549     if (!needsClosure())
4550         return false;
4551 
4552     if (setGC())
4553     {
4554         error("is @nogc yet allocates closures with the GC");
4555         if (global.gag)     // need not report supplemental errors
4556             return true;
4557     }
4558     else
4559     {
4560         printGCUsage(loc, "using closure causes GC allocation");
4561         return false;
4562     }
4563 
4564     FuncDeclarations a;
4565     for (size_t i = 0; i < closureVars.dim; i++)
4566     {
4567         VarDeclaration *v = closureVars[i];
4568 
4569         for (size_t j = 0; j < v->nestedrefs.dim; j++)
4570         {
4571             FuncDeclaration *f = v->nestedrefs[j];
4572             assert(f != this);
4573 
4574             for (Dsymbol *s = f; s && s != this; s = s->parent)
4575             {
4576                 FuncDeclaration *fx = s->isFuncDeclaration();
4577                 if (!fx)
4578                     continue;
4579                 if (fx->isThis() || fx->tookAddressOf)
4580                     goto Lfound;
4581                 if (checkEscapingSiblings(fx, this))
4582                     goto Lfound;
4583             }
4584             continue;
4585 
4586         Lfound:
4587             for (size_t k = 0; ; k++)
4588             {
4589                 if (k == a.dim)
4590                 {
4591                     a.push(f);
4592                     ::errorSupplemental(f->loc, "%s closes over variable %s at %s",
4593                         f->toPrettyChars(), v->toChars(), v->loc.toChars());
4594                     break;
4595                 }
4596                 if (a[k] == f)
4597                     break;
4598             }
4599             continue;
4600         }
4601     }
4602 
4603     return true;
4604 }
4605 
4606 /***********************************************
4607  * Determine if function's variables are referenced by a function
4608  * nested within it.
4609  */
4610 
hasNestedFrameRefs()4611 bool FuncDeclaration::hasNestedFrameRefs()
4612 {
4613     if (closureVars.dim)
4614         return true;
4615 
4616     /* If a virtual function has contracts, assume its variables are referenced
4617      * by those contracts, even if they aren't. Because they might be referenced
4618      * by the overridden or overriding function's contracts.
4619      * This can happen because frequire and fensure are implemented as nested functions,
4620      * and they can be called directly by an overriding function and the overriding function's
4621      * context had better match, or Bugzilla 7335 will bite.
4622      */
4623     if (fdrequire || fdensure)
4624         return true;
4625 
4626     if (foverrides.dim && isVirtualMethod())
4627     {
4628         for (size_t i = 0; i < foverrides.dim; i++)
4629         {
4630             FuncDeclaration *fdv = foverrides[i];
4631             if (fdv->hasNestedFrameRefs())
4632                 return true;
4633         }
4634     }
4635 
4636     return false;
4637 }
4638 
4639 /*********************************************
4640  * Return the function's parameter list, and whether
4641  * it is variadic or not.
4642  */
4643 
getParameters(int * pvarargs)4644 Parameters *FuncDeclaration::getParameters(int *pvarargs)
4645 {
4646     Parameters *fparameters = NULL;
4647     int fvarargs = 0;
4648 
4649     if (type)
4650     {
4651         TypeFunction *fdtype = type->toTypeFunction();
4652         fparameters = fdtype->parameters;
4653         fvarargs = fdtype->varargs;
4654     }
4655     if (pvarargs)
4656         *pvarargs = fvarargs;
4657     return fparameters;
4658 }
4659 
4660 
4661 /****************************** FuncAliasDeclaration ************************/
4662 
4663 // Used as a way to import a set of functions from another scope into this one.
4664 
FuncAliasDeclaration(Identifier * ident,FuncDeclaration * funcalias,bool hasOverloads)4665 FuncAliasDeclaration::FuncAliasDeclaration(Identifier *ident, FuncDeclaration *funcalias, bool hasOverloads)
4666     : FuncDeclaration(funcalias->loc, funcalias->endloc, ident,
4667         funcalias->storage_class, funcalias->type)
4668 {
4669     assert(funcalias != this);
4670     this->funcalias = funcalias;
4671 
4672     this->hasOverloads = hasOverloads;
4673     if (hasOverloads)
4674     {
4675         if (FuncAliasDeclaration *fad = funcalias->isFuncAliasDeclaration())
4676             this->hasOverloads = fad->hasOverloads;
4677     }
4678     else
4679     {   // for internal use
4680         assert(!funcalias->isFuncAliasDeclaration());
4681         this->hasOverloads = false;
4682     }
4683     userAttribDecl = funcalias->userAttribDecl;
4684 }
4685 
kind()4686 const char *FuncAliasDeclaration::kind() const
4687 {
4688     return "function alias";
4689 }
4690 
toAliasFunc()4691 FuncDeclaration *FuncAliasDeclaration::toAliasFunc()
4692 {
4693     return funcalias->toAliasFunc();
4694 }
4695 
4696 
4697 /****************************** FuncLiteralDeclaration ************************/
4698 
FuncLiteralDeclaration(Loc loc,Loc endloc,Type * type,TOK tok,ForeachStatement * fes,Identifier * id)4699 FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
4700         TOK tok, ForeachStatement *fes, Identifier *id)
4701     : FuncDeclaration(loc, endloc, NULL, STCundefined, type)
4702 {
4703     this->ident = id ? id : Id::empty;
4704     this->tok = tok;
4705     this->fes = fes;
4706     this->treq = NULL;
4707     this->deferToObj = false;
4708     //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
4709 }
4710 
syntaxCopy(Dsymbol * s)4711 Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
4712 {
4713     //printf("FuncLiteralDeclaration::syntaxCopy('%s')\n", toChars());
4714     assert(!s);
4715     FuncLiteralDeclaration *f = new FuncLiteralDeclaration(loc, endloc,
4716         type->syntaxCopy(), tok, fes, ident);
4717     f->treq = treq;     // don't need to copy
4718     return FuncDeclaration::syntaxCopy(f);
4719 }
4720 
isNested()4721 bool FuncLiteralDeclaration::isNested()
4722 {
4723     //printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
4724     return (tok != TOKfunction) && !isThis();
4725 }
4726 
isThis()4727 AggregateDeclaration *FuncLiteralDeclaration::isThis()
4728 {
4729     //printf("FuncLiteralDeclaration::isThis() '%s'\n", toChars());
4730     return tok == TOKdelegate ? FuncDeclaration::isThis() : NULL;
4731 }
4732 
isVirtual()4733 bool FuncLiteralDeclaration::isVirtual()
4734 {
4735     return false;
4736 }
4737 
addPreInvariant()4738 bool FuncLiteralDeclaration::addPreInvariant()
4739 {
4740     return false;
4741 }
4742 
addPostInvariant()4743 bool FuncLiteralDeclaration::addPostInvariant()
4744 {
4745     return false;
4746 }
4747 
4748 /*******************************
4749  * Modify all expression type of return statements to tret.
4750  *
4751  * On function literals, return type may be modified based on the context type
4752  * after its semantic3 is done, in FuncExp::implicitCastTo.
4753  *
4754  *  A function() dg = (){ return new B(); } // OK if is(B : A) == true
4755  *
4756  * If B to A conversion is convariant that requires offseet adjusting,
4757  * all return statements should be adjusted to return expressions typed A.
4758  */
modifyReturns(Scope * sc,Type * tret)4759 void FuncLiteralDeclaration::modifyReturns(Scope *sc, Type *tret)
4760 {
4761     class RetWalker : public StatementRewriteWalker
4762     {
4763     public:
4764         Scope *sc;
4765         Type *tret;
4766         FuncLiteralDeclaration *fld;
4767 
4768         void visit(ReturnStatement *s)
4769         {
4770             Expression *exp = s->exp;
4771             if (exp && !exp->type->equals(tret))
4772             {
4773                 s->exp = exp->castTo(sc, tret);
4774             }
4775         }
4776     };
4777 
4778     if (semanticRun < PASSsemantic3done)
4779         return;
4780 
4781     if (fes)
4782         return;
4783 
4784     RetWalker w;
4785     w.sc = sc;
4786     w.tret = tret;
4787     w.fld = this;
4788     fbody->accept(&w);
4789 
4790     // Also update the inferred function type to match the new return type.
4791     // This is required so the code generator does not try to cast the
4792     // modified returns back to the original type.
4793     if (inferRetType && type->nextOf() != tret)
4794         type->toTypeFunction()->next = tret;
4795 }
4796 
kind()4797 const char *FuncLiteralDeclaration::kind() const
4798 {
4799     return (tok != TOKfunction) ? "delegate" : "function";
4800 }
4801 
toPrettyChars(bool QualifyTypes)4802 const char *FuncLiteralDeclaration::toPrettyChars(bool QualifyTypes)
4803 {
4804     if (parent)
4805     {
4806         TemplateInstance *ti = parent->isTemplateInstance();
4807         if (ti)
4808             return ti->tempdecl->toPrettyChars(QualifyTypes);
4809     }
4810     return Dsymbol::toPrettyChars(QualifyTypes);
4811 }
4812 
4813 /********************************* CtorDeclaration ****************************/
4814 
CtorDeclaration(Loc loc,Loc endloc,StorageClass stc,Type * type)4815 CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Type *type)
4816     : FuncDeclaration(loc, endloc, Id::ctor, stc, type)
4817 {
4818     //printf("CtorDeclaration(loc = %s) %s\n", loc.toChars(), toChars());
4819 }
4820 
syntaxCopy(Dsymbol * s)4821 Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s)
4822 {
4823     assert(!s);
4824     CtorDeclaration *f = new CtorDeclaration(loc, endloc, storage_class, type->syntaxCopy());
4825     return FuncDeclaration::syntaxCopy(f);
4826 }
4827 
semantic(Scope * sc)4828 void CtorDeclaration::semantic(Scope *sc)
4829 {
4830     //printf("CtorDeclaration::semantic() %s\n", toChars());
4831     if (semanticRun >= PASSsemanticdone)
4832         return;
4833     if (_scope)
4834     {
4835         sc = _scope;
4836         _scope = NULL;
4837     }
4838 
4839     parent = sc->parent;
4840     Dsymbol *p = toParent2();
4841     AggregateDeclaration *ad = p->isAggregateDeclaration();
4842     if (!ad)
4843     {
4844         ::error(loc, "constructor can only be a member of aggregate, not %s %s",
4845             p->kind(), p->toChars());
4846         type = Type::terror;
4847         errors = true;
4848         return;
4849     }
4850 
4851     sc = sc->push();
4852     sc->stc &= ~STCstatic;              // not a static constructor
4853     sc->flags |= SCOPEctor;
4854 
4855     FuncDeclaration::semantic(sc);
4856 
4857     sc->pop();
4858 
4859     if (errors)
4860         return;
4861 
4862     TypeFunction *tf = type->toTypeFunction();
4863 
4864     /* See if it's the default constructor
4865      * But, template constructor should not become a default constructor.
4866      */
4867     if (ad && (!parent->isTemplateInstance() || parent->isTemplateMixin()))
4868     {
4869         const size_t dim = Parameter::dim(tf->parameters);
4870 
4871         if (StructDeclaration *sd = ad->isStructDeclaration())
4872         {
4873             if (dim == 0 && tf->varargs == 0) // empty default ctor w/o any varargs
4874             {
4875                 if (fbody || !(storage_class & STCdisable) || dim)
4876                 {
4877                     error("default constructor for structs only allowed "
4878                         "with @disable, no body, and no parameters");
4879                     storage_class |= STCdisable;
4880                     fbody = NULL;
4881                 }
4882                 sd->noDefaultCtor = true;
4883             }
4884             else if (dim == 0 && tf->varargs) // allow varargs only ctor
4885             {
4886             }
4887             else if (dim && Parameter::getNth(tf->parameters, 0)->defaultArg)
4888             {
4889                 // if the first parameter has a default argument, then the rest does as well
4890                 if (storage_class & STCdisable)
4891                 {
4892                     deprecation("@disable'd constructor cannot have default "
4893                                 "arguments for all parameters.");
4894                     deprecationSupplemental(loc, "Use @disable this(); if you want to disable default initialization.");
4895                 }
4896                 else
4897                     deprecation("all parameters have default arguments, "
4898                                 "but structs cannot have default constructors.");
4899             }
4900 
4901         }
4902         else if (dim == 0 && tf->varargs == 0)
4903         {
4904             ad->defaultCtor = this;
4905         }
4906     }
4907 }
4908 
kind()4909 const char *CtorDeclaration::kind() const
4910 {
4911     return "constructor";
4912 }
4913 
toChars()4914 const char *CtorDeclaration::toChars()
4915 {
4916     return "this";
4917 }
4918 
isVirtual()4919 bool CtorDeclaration::isVirtual()
4920 {
4921     return false;
4922 }
4923 
addPreInvariant()4924 bool CtorDeclaration::addPreInvariant()
4925 {
4926     return false;
4927 }
4928 
addPostInvariant()4929 bool CtorDeclaration::addPostInvariant()
4930 {
4931     return (isThis() && vthis && global.params.useInvariants);
4932 }
4933 
4934 
4935 /********************************* PostBlitDeclaration ****************************/
4936 
PostBlitDeclaration(Loc loc,Loc endloc,StorageClass stc,Identifier * id)4937 PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id)
4938     : FuncDeclaration(loc, endloc, id, stc, NULL)
4939 {
4940 }
4941 
syntaxCopy(Dsymbol * s)4942 Dsymbol *PostBlitDeclaration::syntaxCopy(Dsymbol *s)
4943 {
4944     assert(!s);
4945     PostBlitDeclaration *dd = new PostBlitDeclaration(loc, endloc, storage_class, ident);
4946     return FuncDeclaration::syntaxCopy(dd);
4947 }
4948 
semantic(Scope * sc)4949 void PostBlitDeclaration::semantic(Scope *sc)
4950 {
4951     //printf("PostBlitDeclaration::semantic() %s\n", toChars());
4952     //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
4953     //printf("stc = x%llx\n", sc->stc);
4954     if (semanticRun >= PASSsemanticdone)
4955         return;
4956     if (_scope)
4957     {
4958         sc = _scope;
4959         _scope = NULL;
4960     }
4961 
4962     parent = sc->parent;
4963     Dsymbol *p = toParent2();
4964     StructDeclaration *ad = p->isStructDeclaration();
4965     if (!ad)
4966     {
4967         ::error(loc, "postblit can only be a member of struct/union, not %s %s",
4968             p->kind(), p->toChars());
4969         type = Type::terror;
4970         errors = true;
4971         return;
4972     }
4973     if (ident == Id::postblit && semanticRun < PASSsemantic)
4974         ad->postblits.push(this);
4975     if (!type)
4976         type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class);
4977 
4978     sc = sc->push();
4979     sc->stc &= ~STCstatic;              // not static
4980     sc->linkage = LINKd;
4981 
4982     FuncDeclaration::semantic(sc);
4983 
4984     sc->pop();
4985 }
4986 
overloadInsert(Dsymbol *)4987 bool PostBlitDeclaration::overloadInsert(Dsymbol *)
4988 {
4989     return false;       // cannot overload postblits
4990 }
4991 
addPreInvariant()4992 bool PostBlitDeclaration::addPreInvariant()
4993 {
4994     return false;
4995 }
4996 
addPostInvariant()4997 bool PostBlitDeclaration::addPostInvariant()
4998 {
4999     return (isThis() && vthis && global.params.useInvariants);
5000 }
5001 
isVirtual()5002 bool PostBlitDeclaration::isVirtual()
5003 {
5004     return false;
5005 }
5006 
5007 /********************************* DtorDeclaration ****************************/
5008 
DtorDeclaration(Loc loc,Loc endloc)5009 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc)
5010     : FuncDeclaration(loc, endloc, Id::dtor, STCundefined, NULL)
5011 {
5012 }
5013 
DtorDeclaration(Loc loc,Loc endloc,StorageClass stc,Identifier * id)5014 DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id)
5015     : FuncDeclaration(loc, endloc, id, stc, NULL)
5016 {
5017 }
5018 
syntaxCopy(Dsymbol * s)5019 Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
5020 {
5021     assert(!s);
5022     DtorDeclaration *dd = new DtorDeclaration(loc, endloc, storage_class, ident);
5023     return FuncDeclaration::syntaxCopy(dd);
5024 }
5025 
semantic(Scope * sc)5026 void DtorDeclaration::semantic(Scope *sc)
5027 {
5028     //printf("DtorDeclaration::semantic() %s\n", toChars());
5029     //printf("ident: %s, %s, %p, %p\n", ident->toChars(), Id::dtor->toChars(), ident, Id::dtor);
5030     if (semanticRun >= PASSsemanticdone)
5031         return;
5032     if (_scope)
5033     {
5034         sc = _scope;
5035         _scope = NULL;
5036     }
5037 
5038     parent = sc->parent;
5039     Dsymbol *p = toParent2();
5040     AggregateDeclaration *ad = p->isAggregateDeclaration();
5041     if (!ad)
5042     {
5043         ::error(loc, "destructor can only be a member of aggregate, not %s %s",
5044             p->kind(), p->toChars());
5045         type = Type::terror;
5046         errors = true;
5047         return;
5048     }
5049     if (ident == Id::dtor && semanticRun < PASSsemantic)
5050         ad->dtors.push(this);
5051     if (!type)
5052         type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class);
5053 
5054     sc = sc->push();
5055     sc->stc &= ~STCstatic;              // not a static destructor
5056     if (sc->linkage != LINKcpp)
5057         sc->linkage = LINKd;
5058 
5059     FuncDeclaration::semantic(sc);
5060 
5061     sc->pop();
5062 }
5063 
overloadInsert(Dsymbol *)5064 bool DtorDeclaration::overloadInsert(Dsymbol *)
5065 {
5066     return false;       // cannot overload destructors
5067 }
5068 
addPreInvariant()5069 bool DtorDeclaration::addPreInvariant()
5070 {
5071     return (isThis() && vthis && global.params.useInvariants);
5072 }
5073 
addPostInvariant()5074 bool DtorDeclaration::addPostInvariant()
5075 {
5076     return false;
5077 }
5078 
kind()5079 const char *DtorDeclaration::kind() const
5080 {
5081     return "destructor";
5082 }
5083 
toChars()5084 const char *DtorDeclaration::toChars()
5085 {
5086     return "~this";
5087 }
5088 
isVirtual()5089 bool DtorDeclaration::isVirtual()
5090 {
5091     // false so that dtor's don't get put into the vtbl[]
5092     return false;
5093 }
5094 
5095 /********************************* StaticCtorDeclaration ****************************/
5096 
StaticCtorDeclaration(Loc loc,Loc endloc,StorageClass stc)5097 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc, StorageClass stc)
5098     : FuncDeclaration(loc, endloc,
5099       Identifier::generateId("_staticCtor"), STCstatic | stc, NULL)
5100 {
5101 }
5102 
StaticCtorDeclaration(Loc loc,Loc endloc,const char * name,StorageClass stc)5103 StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc, const char *name, StorageClass stc)
5104     : FuncDeclaration(loc, endloc,
5105       Identifier::generateId(name), STCstatic | stc, NULL)
5106 {
5107 }
5108 
syntaxCopy(Dsymbol * s)5109 Dsymbol *StaticCtorDeclaration::syntaxCopy(Dsymbol *s)
5110 {
5111     assert(!s);
5112     StaticCtorDeclaration *scd = new StaticCtorDeclaration(loc, endloc, storage_class);
5113     return FuncDeclaration::syntaxCopy(scd);
5114 }
5115 
semantic(Scope * sc)5116 void StaticCtorDeclaration::semantic(Scope *sc)
5117 {
5118     //printf("StaticCtorDeclaration::semantic()\n");
5119     if (semanticRun >= PASSsemanticdone)
5120         return;
5121     if (_scope)
5122     {
5123         sc = _scope;
5124         _scope = NULL;
5125     }
5126 
5127     parent = sc->parent;
5128     Dsymbol *p = parent->pastMixin();
5129     if (!p->isScopeDsymbol())
5130     {
5131         const char *s = (isSharedStaticCtorDeclaration() ? "shared " : "");
5132         ::error(loc, "%sstatic constructor can only be member of module/aggregate/template, not %s %s",
5133             s, p->kind(), p->toChars());
5134         type = Type::terror;
5135         errors = true;
5136         return;
5137     }
5138     if (!type)
5139         type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class);
5140 
5141     /* If the static ctor appears within a template instantiation,
5142      * it could get called multiple times by the module constructors
5143      * for different modules. Thus, protect it with a gate.
5144      */
5145     if (isInstantiated() && semanticRun < PASSsemantic)
5146     {
5147         /* Add this prefix to the function:
5148          *      static int gate;
5149          *      if (++gate != 1) return;
5150          * Note that this is not thread safe; should not have threads
5151          * during static construction.
5152          */
5153         VarDeclaration *v = new VarDeclaration(Loc(), Type::tint32, Id::gate, NULL);
5154         v->storage_class = STCtemp | (isSharedStaticCtorDeclaration() ? STCstatic : STCtls);
5155         Statements *sa = new Statements();
5156         Statement *s = new ExpStatement(Loc(), v);
5157         sa->push(s);
5158         Expression *e = new IdentifierExp(Loc(), v->ident);
5159         e = new AddAssignExp(Loc(), e, new IntegerExp(1));
5160         e = new EqualExp(TOKnotequal, Loc(), e, new IntegerExp(1));
5161         s = new IfStatement(Loc(), NULL, e, new ReturnStatement(Loc(), NULL), NULL, Loc());
5162         sa->push(s);
5163         if (fbody)
5164             sa->push(fbody);
5165         fbody = new CompoundStatement(Loc(), sa);
5166     }
5167 
5168     FuncDeclaration::semantic(sc);
5169 
5170     // We're going to need ModuleInfo
5171     Module *m = getModule();
5172     if (!m)
5173         m = sc->_module;
5174     if (m)
5175     {
5176         m->needmoduleinfo = 1;
5177         //printf("module1 %s needs moduleinfo\n", m->toChars());
5178     }
5179 }
5180 
isThis()5181 AggregateDeclaration *StaticCtorDeclaration::isThis()
5182 {
5183     return NULL;
5184 }
5185 
isVirtual()5186 bool StaticCtorDeclaration::isVirtual()
5187 {
5188     return false;
5189 }
5190 
hasStaticCtorOrDtor()5191 bool StaticCtorDeclaration::hasStaticCtorOrDtor()
5192 {
5193     return true;
5194 }
5195 
addPreInvariant()5196 bool StaticCtorDeclaration::addPreInvariant()
5197 {
5198     return false;
5199 }
5200 
addPostInvariant()5201 bool StaticCtorDeclaration::addPostInvariant()
5202 {
5203     return false;
5204 }
5205 
5206 /********************************* SharedStaticCtorDeclaration ****************************/
5207 
SharedStaticCtorDeclaration(Loc loc,Loc endloc,StorageClass stc)5208 SharedStaticCtorDeclaration::SharedStaticCtorDeclaration(Loc loc, Loc endloc, StorageClass stc)
5209     : StaticCtorDeclaration(loc, endloc, "_sharedStaticCtor", stc)
5210 {
5211 }
5212 
syntaxCopy(Dsymbol * s)5213 Dsymbol *SharedStaticCtorDeclaration::syntaxCopy(Dsymbol *s)
5214 {
5215     assert(!s);
5216     SharedStaticCtorDeclaration *scd = new SharedStaticCtorDeclaration(loc, endloc, storage_class);
5217     return FuncDeclaration::syntaxCopy(scd);
5218 }
5219 
5220 /********************************* StaticDtorDeclaration ****************************/
5221 
StaticDtorDeclaration(Loc loc,Loc endloc,StorageClass stc)5222 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc, StorageClass stc)
5223     : FuncDeclaration(loc, endloc,
5224       Identifier::generateId("_staticDtor"), STCstatic | stc, NULL)
5225 {
5226     vgate = NULL;
5227 }
5228 
StaticDtorDeclaration(Loc loc,Loc endloc,const char * name,StorageClass stc)5229 StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc, const char *name, StorageClass stc)
5230     : FuncDeclaration(loc, endloc,
5231       Identifier::generateId(name), STCstatic | stc, NULL)
5232 {
5233     vgate = NULL;
5234 }
5235 
syntaxCopy(Dsymbol * s)5236 Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
5237 {
5238     assert(!s);
5239     StaticDtorDeclaration *sdd = new StaticDtorDeclaration(loc, endloc, storage_class);
5240     return FuncDeclaration::syntaxCopy(sdd);
5241 }
5242 
semantic(Scope * sc)5243 void StaticDtorDeclaration::semantic(Scope *sc)
5244 {
5245     if (semanticRun >= PASSsemanticdone)
5246         return;
5247     if (_scope)
5248     {
5249         sc = _scope;
5250         _scope = NULL;
5251     }
5252 
5253     parent = sc->parent;
5254     Dsymbol *p = parent->pastMixin();
5255     if (!p->isScopeDsymbol())
5256     {
5257         const char *s = (isSharedStaticDtorDeclaration() ? "shared " : "");
5258         ::error(loc, "%sstatic destructor can only be member of module/aggregate/template, not %s %s",
5259             s, p->kind(), p->toChars());
5260         type = Type::terror;
5261         errors = true;
5262         return;
5263     }
5264     if (!type)
5265         type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class);
5266 
5267     /* If the static ctor appears within a template instantiation,
5268      * it could get called multiple times by the module constructors
5269      * for different modules. Thus, protect it with a gate.
5270      */
5271     if (isInstantiated() && semanticRun < PASSsemantic)
5272     {
5273         /* Add this prefix to the function:
5274          *      static int gate;
5275          *      if (--gate != 0) return;
5276          * Increment gate during constructor execution.
5277          * Note that this is not thread safe; should not have threads
5278          * during static destruction.
5279          */
5280         VarDeclaration *v = new VarDeclaration(Loc(), Type::tint32, Id::gate, NULL);
5281         v->storage_class = STCtemp | (isSharedStaticDtorDeclaration() ? STCstatic : STCtls);
5282         Statements *sa = new Statements();
5283         Statement *s = new ExpStatement(Loc(), v);
5284         sa->push(s);
5285         Expression *e = new IdentifierExp(Loc(), v->ident);
5286         e = new AddAssignExp(Loc(), e, new IntegerExp(-1));
5287         e = new EqualExp(TOKnotequal, Loc(), e, new IntegerExp(0));
5288         s = new IfStatement(Loc(), NULL, e, new ReturnStatement(Loc(), NULL), NULL, Loc());
5289         sa->push(s);
5290         if (fbody)
5291             sa->push(fbody);
5292         fbody = new CompoundStatement(Loc(), sa);
5293         vgate = v;
5294     }
5295 
5296     FuncDeclaration::semantic(sc);
5297 
5298     // We're going to need ModuleInfo
5299     Module *m = getModule();
5300     if (!m)
5301         m = sc->_module;
5302     if (m)
5303     {
5304         m->needmoduleinfo = 1;
5305         //printf("module2 %s needs moduleinfo\n", m->toChars());
5306     }
5307 }
5308 
isThis()5309 AggregateDeclaration *StaticDtorDeclaration::isThis()
5310 {
5311     return NULL;
5312 }
5313 
isVirtual()5314 bool StaticDtorDeclaration::isVirtual()
5315 {
5316     return false;
5317 }
5318 
hasStaticCtorOrDtor()5319 bool StaticDtorDeclaration::hasStaticCtorOrDtor()
5320 {
5321     return true;
5322 }
5323 
addPreInvariant()5324 bool StaticDtorDeclaration::addPreInvariant()
5325 {
5326     return false;
5327 }
5328 
addPostInvariant()5329 bool StaticDtorDeclaration::addPostInvariant()
5330 {
5331     return false;
5332 }
5333 
5334 /********************************* SharedStaticDtorDeclaration ****************************/
5335 
SharedStaticDtorDeclaration(Loc loc,Loc endloc,StorageClass stc)5336 SharedStaticDtorDeclaration::SharedStaticDtorDeclaration(Loc loc, Loc endloc, StorageClass stc)
5337     : StaticDtorDeclaration(loc, endloc, "_sharedStaticDtor", stc)
5338 {
5339 }
5340 
syntaxCopy(Dsymbol * s)5341 Dsymbol *SharedStaticDtorDeclaration::syntaxCopy(Dsymbol *s)
5342 {
5343     assert(!s);
5344     SharedStaticDtorDeclaration *sdd = new SharedStaticDtorDeclaration(loc, endloc, storage_class);
5345     return FuncDeclaration::syntaxCopy(sdd);
5346 }
5347 
5348 /********************************* InvariantDeclaration ****************************/
5349 
InvariantDeclaration(Loc loc,Loc endloc,StorageClass stc,Identifier * id)5350 InvariantDeclaration::InvariantDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id)
5351     : FuncDeclaration(loc, endloc,
5352                       id ? id : Identifier::generateId("__invariant"),
5353                       stc, NULL)
5354 {
5355 }
5356 
syntaxCopy(Dsymbol * s)5357 Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s)
5358 {
5359     assert(!s);
5360     InvariantDeclaration *id = new InvariantDeclaration(loc, endloc, storage_class);
5361     return FuncDeclaration::syntaxCopy(id);
5362 }
5363 
semantic(Scope * sc)5364 void InvariantDeclaration::semantic(Scope *sc)
5365 {
5366     if (semanticRun >= PASSsemanticdone)
5367         return;
5368     if (_scope)
5369     {
5370         sc = _scope;
5371         _scope = NULL;
5372     }
5373 
5374     parent = sc->parent;
5375     Dsymbol *p = parent->pastMixin();
5376     AggregateDeclaration *ad = p->isAggregateDeclaration();
5377     if (!ad)
5378     {
5379         ::error(loc, "invariant can only be a member of aggregate, not %s %s",
5380             p->kind(), p->toChars());
5381         type = Type::terror;
5382         errors = true;
5383         return;
5384     }
5385     if (ident != Id::classInvariant &&
5386         semanticRun < PASSsemantic &&
5387         !ad->isUnionDeclaration()           // users are on their own with union fields
5388        )
5389         ad->invs.push(this);
5390     if (!type)
5391         type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class);
5392 
5393     sc = sc->push();
5394     sc->stc &= ~STCstatic;              // not a static invariant
5395     sc->stc |= STCconst;                // invariant() is always const
5396     sc->flags = (sc->flags & ~SCOPEcontract) | SCOPEinvariant;
5397     sc->linkage = LINKd;
5398 
5399     FuncDeclaration::semantic(sc);
5400 
5401     sc->pop();
5402 }
5403 
isVirtual()5404 bool InvariantDeclaration::isVirtual()
5405 {
5406     return false;
5407 }
5408 
addPreInvariant()5409 bool InvariantDeclaration::addPreInvariant()
5410 {
5411     return false;
5412 }
5413 
addPostInvariant()5414 bool InvariantDeclaration::addPostInvariant()
5415 {
5416     return false;
5417 }
5418 
5419 /********************************* UnitTestDeclaration ****************************/
5420 
5421 /*******************************
5422  * Generate unique unittest function Id so we can have multiple
5423  * instances per module.
5424  */
5425 
unitTestId(Loc loc)5426 static Identifier *unitTestId(Loc loc)
5427 {
5428     OutBuffer buf;
5429     buf.printf("__unittestL%u_", loc.linnum);
5430     return Identifier::generateId(buf.peekString());
5431 }
5432 
UnitTestDeclaration(Loc loc,Loc endloc,StorageClass stc,char * codedoc)5433 UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc, StorageClass stc, char *codedoc)
5434     : FuncDeclaration(loc, endloc, unitTestId(loc), stc, NULL)
5435 {
5436     this->codedoc = codedoc;
5437 }
5438 
syntaxCopy(Dsymbol * s)5439 Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s)
5440 {
5441     assert(!s);
5442     UnitTestDeclaration *utd = new UnitTestDeclaration(loc, endloc, storage_class, codedoc);
5443     return FuncDeclaration::syntaxCopy(utd);
5444 }
5445 
semantic(Scope * sc)5446 void UnitTestDeclaration::semantic(Scope *sc)
5447 {
5448     if (semanticRun >= PASSsemanticdone)
5449         return;
5450     if (_scope)
5451     {
5452         sc = _scope;
5453         _scope = NULL;
5454     }
5455 
5456     protection = sc->protection;
5457 
5458     parent = sc->parent;
5459     Dsymbol *p = parent->pastMixin();
5460     if (!p->isScopeDsymbol())
5461     {
5462         ::error(loc, "unittest can only be a member of module/aggregate/template, not %s %s",
5463             p->kind(), p->toChars());
5464         type = Type::terror;
5465         errors = true;
5466         return;
5467     }
5468 
5469     if (global.params.useUnitTests)
5470     {
5471         if (!type)
5472             type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class);
5473         Scope *sc2 = sc->push();
5474         sc2->linkage = LINKd;
5475         FuncDeclaration::semantic(sc2);
5476         sc2->pop();
5477     }
5478 }
5479 
isThis()5480 AggregateDeclaration *UnitTestDeclaration::isThis()
5481 {
5482     return NULL;
5483 }
5484 
isVirtual()5485 bool UnitTestDeclaration::isVirtual()
5486 {
5487     return false;
5488 }
5489 
addPreInvariant()5490 bool UnitTestDeclaration::addPreInvariant()
5491 {
5492     return false;
5493 }
5494 
addPostInvariant()5495 bool UnitTestDeclaration::addPostInvariant()
5496 {
5497     return false;
5498 }
5499 
5500 /********************************* NewDeclaration ****************************/
5501 
NewDeclaration(Loc loc,Loc endloc,StorageClass stc,Parameters * fparams,int varargs)5502 NewDeclaration::NewDeclaration(Loc loc, Loc endloc, StorageClass stc, Parameters *fparams, int varargs)
5503     : FuncDeclaration(loc, endloc, Id::classNew, STCstatic | stc, NULL)
5504 {
5505     this->parameters = fparams;
5506     this->varargs = varargs;
5507 }
5508 
syntaxCopy(Dsymbol * s)5509 Dsymbol *NewDeclaration::syntaxCopy(Dsymbol *s)
5510 {
5511     assert(!s);
5512     NewDeclaration *f = new NewDeclaration(loc, endloc,
5513         storage_class, Parameter::arraySyntaxCopy(parameters), varargs);
5514     return FuncDeclaration::syntaxCopy(f);
5515 }
5516 
semantic(Scope * sc)5517 void NewDeclaration::semantic(Scope *sc)
5518 {
5519     //printf("NewDeclaration::semantic()\n");
5520     if (semanticRun >= PASSsemanticdone)
5521         return;
5522     if (_scope)
5523     {
5524         sc = _scope;
5525         _scope = NULL;
5526     }
5527 
5528     parent = sc->parent;
5529     Dsymbol *p = parent->pastMixin();
5530     if (!p->isAggregateDeclaration())
5531     {
5532         ::error(loc, "allocator can only be a member of aggregate, not %s %s",
5533             p->kind(), p->toChars());
5534         type = Type::terror;
5535         errors = true;
5536         return;
5537     }
5538     Type *tret = Type::tvoid->pointerTo();
5539     if (!type)
5540         type = new TypeFunction(parameters, tret, varargs, LINKd, storage_class);
5541 
5542     type = type->semantic(loc, sc);
5543 
5544     // Check that there is at least one argument of type size_t
5545     TypeFunction *tf = type->toTypeFunction();
5546     if (Parameter::dim(tf->parameters) < 1)
5547     {
5548         error("at least one argument of type size_t expected");
5549     }
5550     else
5551     {
5552         Parameter *fparam = Parameter::getNth(tf->parameters, 0);
5553         if (!fparam->type->equals(Type::tsize_t))
5554             error("first argument must be type size_t, not %s", fparam->type->toChars());
5555     }
5556 
5557     FuncDeclaration::semantic(sc);
5558 }
5559 
kind()5560 const char *NewDeclaration::kind() const
5561 {
5562     return "allocator";
5563 }
5564 
isVirtual()5565 bool NewDeclaration::isVirtual()
5566 {
5567     return false;
5568 }
5569 
addPreInvariant()5570 bool NewDeclaration::addPreInvariant()
5571 {
5572     return false;
5573 }
5574 
addPostInvariant()5575 bool NewDeclaration::addPostInvariant()
5576 {
5577     return false;
5578 }
5579 
5580 /********************************* DeleteDeclaration ****************************/
5581 
DeleteDeclaration(Loc loc,Loc endloc,StorageClass stc,Parameters * fparams)5582 DeleteDeclaration::DeleteDeclaration(Loc loc, Loc endloc, StorageClass stc, Parameters *fparams)
5583     : FuncDeclaration(loc, endloc, Id::classDelete, STCstatic | stc, NULL)
5584 {
5585     this->parameters = fparams;
5586 }
5587 
syntaxCopy(Dsymbol * s)5588 Dsymbol *DeleteDeclaration::syntaxCopy(Dsymbol *s)
5589 {
5590     assert(!s);
5591     DeleteDeclaration *f = new DeleteDeclaration(loc, endloc,
5592             storage_class, Parameter::arraySyntaxCopy(parameters));
5593     return FuncDeclaration::syntaxCopy(f);
5594 }
5595 
semantic(Scope * sc)5596 void DeleteDeclaration::semantic(Scope *sc)
5597 {
5598     //printf("DeleteDeclaration::semantic()\n");
5599     if (semanticRun >= PASSsemanticdone)
5600         return;
5601     if (_scope)
5602     {
5603         sc = _scope;
5604         _scope = NULL;
5605     }
5606 
5607     parent = sc->parent;
5608     Dsymbol *p = parent->pastMixin();
5609     if (!p->isAggregateDeclaration())
5610     {
5611         ::error(loc, "deallocator can only be a member of aggregate, not %s %s",
5612             p->kind(), p->toChars());
5613         type = Type::terror;
5614         errors = true;
5615         return;
5616     }
5617     if (!type)
5618         type = new TypeFunction(parameters, Type::tvoid, 0, LINKd, storage_class);
5619 
5620     type = type->semantic(loc, sc);
5621 
5622     // Check that there is only one argument of type void*
5623     TypeFunction *tf = type->toTypeFunction();
5624     if (Parameter::dim(tf->parameters) != 1)
5625     {
5626         error("one argument of type void* expected");
5627     }
5628     else
5629     {
5630         Parameter *fparam = Parameter::getNth(tf->parameters, 0);
5631         if (!fparam->type->equals(Type::tvoid->pointerTo()))
5632             error("one argument of type void* expected, not %s", fparam->type->toChars());
5633     }
5634 
5635     FuncDeclaration::semantic(sc);
5636 }
5637 
kind()5638 const char *DeleteDeclaration::kind() const
5639 {
5640     return "deallocator";
5641 }
5642 
isDelete()5643 bool DeleteDeclaration::isDelete()
5644 {
5645     return true;
5646 }
5647 
isVirtual()5648 bool DeleteDeclaration::isVirtual()
5649 {
5650     return false;
5651 }
5652 
addPreInvariant()5653 bool DeleteDeclaration::addPreInvariant()
5654 {
5655     return false;
5656 }
5657 
addPostInvariant()5658 bool DeleteDeclaration::addPostInvariant()
5659 {
5660     return false;
5661 }
5662