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