Home | History | Annotate | Line # | Download | only in dmd
semantic3.d revision 1.1.1.1
      1  1.1  mrg /**
      2  1.1  mrg  * Performs the semantic3 stage, which deals with function bodies.
      3  1.1  mrg  *
      4  1.1  mrg  * Copyright:   Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
      5  1.1  mrg  * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
      6  1.1  mrg  * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
      7  1.1  mrg  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/semantic3.d, _semantic3.d)
      8  1.1  mrg  * Documentation:  https://dlang.org/phobos/dmd_semantic3.html
      9  1.1  mrg  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/semantic3.d
     10  1.1  mrg  */
     11  1.1  mrg 
     12  1.1  mrg module dmd.semantic3;
     13  1.1  mrg 
     14  1.1  mrg import core.stdc.stdio;
     15  1.1  mrg import core.stdc.string;
     16  1.1  mrg 
     17  1.1  mrg import dmd.aggregate;
     18  1.1  mrg import dmd.aliasthis;
     19  1.1  mrg import dmd.arraytypes;
     20  1.1  mrg import dmd.astcodegen;
     21  1.1  mrg import dmd.astenums;
     22  1.1  mrg import dmd.attrib;
     23  1.1  mrg import dmd.blockexit;
     24  1.1  mrg import dmd.clone;
     25  1.1  mrg import dmd.ctorflow;
     26  1.1  mrg import dmd.dcast;
     27  1.1  mrg import dmd.dclass;
     28  1.1  mrg import dmd.declaration;
     29  1.1  mrg import dmd.denum;
     30  1.1  mrg import dmd.dimport;
     31  1.1  mrg import dmd.dinterpret;
     32  1.1  mrg import dmd.dmodule;
     33  1.1  mrg import dmd.dscope;
     34  1.1  mrg import dmd.dstruct;
     35  1.1  mrg import dmd.dsymbol;
     36  1.1  mrg import dmd.dsymbolsem;
     37  1.1  mrg import dmd.dtemplate;
     38  1.1  mrg import dmd.dversion;
     39  1.1  mrg import dmd.errors;
     40  1.1  mrg import dmd.escape;
     41  1.1  mrg import dmd.expression;
     42  1.1  mrg import dmd.expressionsem;
     43  1.1  mrg import dmd.func;
     44  1.1  mrg import dmd.globals;
     45  1.1  mrg import dmd.id;
     46  1.1  mrg import dmd.identifier;
     47  1.1  mrg import dmd.init;
     48  1.1  mrg import dmd.initsem;
     49  1.1  mrg import dmd.hdrgen;
     50  1.1  mrg import dmd.mtype;
     51  1.1  mrg import dmd.nogc;
     52  1.1  mrg import dmd.nspace;
     53  1.1  mrg import dmd.ob;
     54  1.1  mrg import dmd.objc;
     55  1.1  mrg import dmd.opover;
     56  1.1  mrg import dmd.parse;
     57  1.1  mrg import dmd.root.filename;
     58  1.1  mrg import dmd.common.outbuffer;
     59  1.1  mrg import dmd.root.rmem;
     60  1.1  mrg import dmd.root.rootobject;
     61  1.1  mrg import dmd.root.utf;
     62  1.1  mrg import dmd.sideeffect;
     63  1.1  mrg import dmd.statementsem;
     64  1.1  mrg import dmd.staticassert;
     65  1.1  mrg import dmd.tokens;
     66  1.1  mrg import dmd.semantic2;
     67  1.1  mrg import dmd.statement;
     68  1.1  mrg import dmd.target;
     69  1.1  mrg import dmd.templateparamsem;
     70  1.1  mrg import dmd.typesem;
     71  1.1  mrg import dmd.visitor;
     72  1.1  mrg 
     73  1.1  mrg enum LOG = false;
     74  1.1  mrg 
     75  1.1  mrg 
     76  1.1  mrg /*************************************
     77  1.1  mrg  * Does semantic analysis on function bodies.
     78  1.1  mrg  */
     79  1.1  mrg extern(C++) void semantic3(Dsymbol dsym, Scope* sc)
     80  1.1  mrg {
     81  1.1  mrg     scope v = new Semantic3Visitor(sc);
     82  1.1  mrg     dsym.accept(v);
     83  1.1  mrg }
     84  1.1  mrg 
     85  1.1  mrg private extern(C++) final class Semantic3Visitor : Visitor
     86  1.1  mrg {
     87  1.1  mrg     alias visit = Visitor.visit;
     88  1.1  mrg 
     89  1.1  mrg     Scope* sc;
     90  1.1  mrg     this(Scope* sc)
     91  1.1  mrg     {
     92  1.1  mrg         this.sc = sc;
     93  1.1  mrg     }
     94  1.1  mrg 
     95  1.1  mrg     override void visit(Dsymbol) {}
     96  1.1  mrg 
     97  1.1  mrg     override void visit(TemplateInstance tempinst)
     98  1.1  mrg     {
     99  1.1  mrg         static if (LOG)
    100  1.1  mrg         {
    101  1.1  mrg             printf("TemplateInstance.semantic3('%s'), semanticRun = %d\n", tempinst.toChars(), tempinst.semanticRun);
    102  1.1  mrg         }
    103  1.1  mrg         //if (toChars()[0] == 'D') *(char*)0=0;
    104  1.1  mrg         if (tempinst.semanticRun >= PASS.semantic3)
    105  1.1  mrg             return;
    106  1.1  mrg         tempinst.semanticRun = PASS.semantic3;
    107  1.1  mrg         if (tempinst.errors || !tempinst.members)
    108  1.1  mrg             return;
    109  1.1  mrg 
    110  1.1  mrg         TemplateDeclaration tempdecl = tempinst.tempdecl.isTemplateDeclaration();
    111  1.1  mrg         assert(tempdecl);
    112  1.1  mrg 
    113  1.1  mrg         sc = tempdecl._scope;
    114  1.1  mrg         sc = sc.push(tempinst.argsym);
    115  1.1  mrg         sc = sc.push(tempinst);
    116  1.1  mrg         sc.tinst = tempinst;
    117  1.1  mrg         sc.minst = tempinst.minst;
    118  1.1  mrg 
    119  1.1  mrg         int needGagging = (tempinst.gagged && !global.gag);
    120  1.1  mrg         uint olderrors = global.errors;
    121  1.1  mrg         int oldGaggedErrors = -1; // dead-store to prevent spurious warning
    122  1.1  mrg         /* If this is a gagged instantiation, gag errors.
    123  1.1  mrg          * Future optimisation: If the results are actually needed, errors
    124  1.1  mrg          * would already be gagged, so we don't really need to run semantic
    125  1.1  mrg          * on the members.
    126  1.1  mrg          */
    127  1.1  mrg         if (needGagging)
    128  1.1  mrg             oldGaggedErrors = global.startGagging();
    129  1.1  mrg 
    130  1.1  mrg         for (size_t i = 0; i < tempinst.members.dim; i++)
    131  1.1  mrg         {
    132  1.1  mrg             Dsymbol s = (*tempinst.members)[i];
    133  1.1  mrg             s.semantic3(sc);
    134  1.1  mrg             if (tempinst.gagged && global.errors != olderrors)
    135  1.1  mrg                 break;
    136  1.1  mrg         }
    137  1.1  mrg 
    138  1.1  mrg         if (global.errors != olderrors)
    139  1.1  mrg         {
    140  1.1  mrg             if (!tempinst.errors)
    141  1.1  mrg             {
    142  1.1  mrg                 if (!tempdecl.literal)
    143  1.1  mrg                     tempinst.error(tempinst.loc, "error instantiating");
    144  1.1  mrg                 if (tempinst.tinst)
    145  1.1  mrg                     tempinst.tinst.printInstantiationTrace();
    146  1.1  mrg             }
    147  1.1  mrg             tempinst.errors = true;
    148  1.1  mrg         }
    149  1.1  mrg         if (needGagging)
    150  1.1  mrg             global.endGagging(oldGaggedErrors);
    151  1.1  mrg 
    152  1.1  mrg         sc = sc.pop();
    153  1.1  mrg         sc.pop();
    154  1.1  mrg     }
    155  1.1  mrg 
    156  1.1  mrg     override void visit(TemplateMixin tmix)
    157  1.1  mrg     {
    158  1.1  mrg         if (tmix.semanticRun >= PASS.semantic3)
    159  1.1  mrg             return;
    160  1.1  mrg         tmix.semanticRun = PASS.semantic3;
    161  1.1  mrg         static if (LOG)
    162  1.1  mrg         {
    163  1.1  mrg             printf("TemplateMixin.semantic3('%s')\n", tmix.toChars());
    164  1.1  mrg         }
    165  1.1  mrg         if (!tmix.members)
    166  1.1  mrg             return;
    167  1.1  mrg 
    168  1.1  mrg         sc = sc.push(tmix.argsym);
    169  1.1  mrg         sc = sc.push(tmix);
    170  1.1  mrg         for (size_t i = 0; i < tmix.members.dim; i++)
    171  1.1  mrg         {
    172  1.1  mrg             Dsymbol s = (*tmix.members)[i];
    173  1.1  mrg             s.semantic3(sc);
    174  1.1  mrg         }
    175  1.1  mrg         sc = sc.pop();
    176  1.1  mrg         sc.pop();
    177  1.1  mrg     }
    178  1.1  mrg 
    179  1.1  mrg     override void visit(Module mod)
    180  1.1  mrg     {
    181  1.1  mrg         //printf("Module::semantic3('%s'): parent = %p\n", toChars(), parent);
    182  1.1  mrg         if (mod.semanticRun != PASS.semantic2done)
    183  1.1  mrg             return;
    184  1.1  mrg         mod.semanticRun = PASS.semantic3;
    185  1.1  mrg         // Note that modules get their own scope, from scratch.
    186  1.1  mrg         // This is so regardless of where in the syntax a module
    187  1.1  mrg         // gets imported, it is unaffected by context.
    188  1.1  mrg         Scope* sc = Scope.createGlobal(mod); // create root scope
    189  1.1  mrg         //printf("Module = %p\n", sc.scopesym);
    190  1.1  mrg         if (mod.members)
    191  1.1  mrg         {
    192  1.1  mrg             // Pass 3 semantic routines: do initializers and function bodies
    193  1.1  mrg             for (size_t i = 0; i < mod.members.dim; i++)
    194  1.1  mrg             {
    195  1.1  mrg                 Dsymbol s = (*mod.members)[i];
    196  1.1  mrg                 //printf("Module %s: %s.semantic3()\n", toChars(), s.toChars());
    197  1.1  mrg                 s.semantic3(sc);
    198  1.1  mrg 
    199  1.1  mrg                 mod.runDeferredSemantic2();
    200  1.1  mrg             }
    201  1.1  mrg         }
    202  1.1  mrg         if (mod.userAttribDecl)
    203  1.1  mrg         {
    204  1.1  mrg             mod.userAttribDecl.semantic3(sc);
    205  1.1  mrg         }
    206  1.1  mrg         sc = sc.pop();
    207  1.1  mrg         sc.pop();
    208  1.1  mrg         mod.semanticRun = PASS.semantic3done;
    209  1.1  mrg     }
    210  1.1  mrg 
    211  1.1  mrg     override void visit(FuncDeclaration funcdecl)
    212  1.1  mrg     {
    213  1.1  mrg         //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", funcdecl.kind(), funcdecl.toChars(), sc);
    214  1.1  mrg         /* Determine if function should add `return 0;`
    215  1.1  mrg          */
    216  1.1  mrg         bool addReturn0()
    217  1.1  mrg         {
    218  1.1  mrg             //printf("addReturn0()\n");
    219  1.1  mrg             auto f = funcdecl.type.isTypeFunction();
    220  1.1  mrg 
    221  1.1  mrg             // C11 5.1.2.2.3
    222  1.1  mrg             if (sc.flags & SCOPE.Cfile && funcdecl.isCMain() && f.next.ty == Tint32)
    223  1.1  mrg                 return true;
    224  1.1  mrg 
    225  1.1  mrg             return f.next.ty == Tvoid &&
    226  1.1  mrg                 (funcdecl.isMain() || global.params.betterC && funcdecl.isCMain());
    227  1.1  mrg         }
    228  1.1  mrg 
    229  1.1  mrg         VarDeclaration _arguments = null;
    230  1.1  mrg 
    231  1.1  mrg         if (!funcdecl.parent)
    232  1.1  mrg         {
    233  1.1  mrg             if (global.errors)
    234  1.1  mrg                 return;
    235  1.1  mrg             //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
    236  1.1  mrg             assert(0);
    237  1.1  mrg         }
    238  1.1  mrg         if (funcdecl.errors || isError(funcdecl.parent))
    239  1.1  mrg         {
    240  1.1  mrg             funcdecl.errors = true;
    241  1.1  mrg 
    242  1.1  mrg             // Mark that the return type could not be inferred
    243  1.1  mrg             if (funcdecl.inferRetType)
    244  1.1  mrg             {
    245  1.1  mrg                 assert(funcdecl.type);
    246  1.1  mrg                 auto tf = funcdecl.type.isTypeFunction();
    247  1.1  mrg 
    248  1.1  mrg                 // Only change the return type s.t. other analysis is
    249  1.1  mrg                 // still possible e.g. missmatched parameter types
    250  1.1  mrg                 if (tf && !tf.next)
    251  1.1  mrg                     tf.next = Type.terror;
    252  1.1  mrg             }
    253  1.1  mrg             return;
    254  1.1  mrg         }
    255  1.1  mrg         //printf("FuncDeclaration::semantic3('%s.%s', %p, sc = %p, loc = %s)\n", funcdecl.parent.toChars(), funcdecl.toChars(), funcdecl, sc, funcdecl.loc.toChars());
    256  1.1  mrg         //fflush(stdout);
    257  1.1  mrg         //printf("storage class = x%x %x\n", sc.stc, storage_class);
    258  1.1  mrg         //{ static int x; if (++x == 2) *(char*)0=0; }
    259  1.1  mrg         //printf("\tlinkage = %d\n", sc.linkage);
    260  1.1  mrg 
    261  1.1  mrg         if (funcdecl.ident == Id.assign && !funcdecl.inuse)
    262  1.1  mrg         {
    263  1.1  mrg             if (funcdecl.storage_class & STC.inference)
    264  1.1  mrg             {
    265  1.1  mrg                 /* https://issues.dlang.org/show_bug.cgi?id=15044
    266  1.1  mrg                  * For generated opAssign function, any errors
    267  1.1  mrg                  * from its body need to be gagged.
    268  1.1  mrg                  */
    269  1.1  mrg                 uint oldErrors = global.startGagging();
    270  1.1  mrg                 ++funcdecl.inuse;
    271  1.1  mrg                 funcdecl.semantic3(sc);
    272  1.1  mrg                 --funcdecl.inuse;
    273  1.1  mrg                 if (global.endGagging(oldErrors))   // if errors happened
    274  1.1  mrg                 {
    275  1.1  mrg                     // Disable generated opAssign, because some members forbid identity assignment.
    276  1.1  mrg                     funcdecl.storage_class |= STC.disable;
    277  1.1  mrg                     funcdecl.fbody = null;   // remove fbody which contains the error
    278  1.1  mrg                     funcdecl.flags &= ~FUNCFLAG.semantic3Errors;
    279  1.1  mrg                 }
    280  1.1  mrg                 return;
    281  1.1  mrg             }
    282  1.1  mrg         }
    283  1.1  mrg 
    284  1.1  mrg         //printf(" sc.incontract = %d\n", (sc.flags & SCOPE.contract));
    285  1.1  mrg         if (funcdecl.semanticRun >= PASS.semantic3)
    286  1.1  mrg             return;
    287  1.1  mrg         funcdecl.semanticRun = PASS.semantic3;
    288  1.1  mrg         funcdecl.flags &= ~FUNCFLAG.semantic3Errors;
    289  1.1  mrg 
    290  1.1  mrg         if (!funcdecl.type || funcdecl.type.ty != Tfunction)
    291  1.1  mrg             return;
    292  1.1  mrg         TypeFunction f = cast(TypeFunction)funcdecl.type;
    293  1.1  mrg         if (!funcdecl.inferRetType && f.next.ty == Terror)
    294  1.1  mrg             return;
    295  1.1  mrg 
    296  1.1  mrg         if (!funcdecl.fbody && funcdecl.inferRetType && !f.next)
    297  1.1  mrg         {
    298  1.1  mrg             funcdecl.error("has no function body with return type inference");
    299  1.1  mrg             return;
    300  1.1  mrg         }
    301  1.1  mrg 
    302  1.1  mrg         uint oldErrors = global.errors;
    303  1.1  mrg         auto fds = FuncDeclSem3(funcdecl,sc);
    304  1.1  mrg 
    305  1.1  mrg         fds.checkInContractOverrides();
    306  1.1  mrg 
    307  1.1  mrg         // Remember whether we need to generate an 'out' contract.
    308  1.1  mrg         immutable bool needEnsure = FuncDeclaration.needsFensure(funcdecl);
    309  1.1  mrg 
    310  1.1  mrg         if (funcdecl.fbody || funcdecl.frequires || needEnsure)
    311  1.1  mrg         {
    312  1.1  mrg             /* Symbol table into which we place parameters and nested functions,
    313  1.1  mrg              * solely to diagnose name collisions.
    314  1.1  mrg              */
    315  1.1  mrg             funcdecl.localsymtab = new DsymbolTable();
    316  1.1  mrg 
    317  1.1  mrg             // Establish function scope
    318  1.1  mrg             auto ss = new ScopeDsymbol(funcdecl.loc, null);
    319  1.1  mrg             // find enclosing scope symbol, might skip symbol-less CTFE and/or FuncExp scopes
    320  1.1  mrg             ss.parent = sc.inner().scopesym;
    321  1.1  mrg             ss.endlinnum = funcdecl.endloc.linnum;
    322  1.1  mrg             Scope* sc2 = sc.push(ss);
    323  1.1  mrg             sc2.func = funcdecl;
    324  1.1  mrg             sc2.parent = funcdecl;
    325  1.1  mrg             sc2.ctorflow.callSuper = CSX.none;
    326  1.1  mrg             sc2.sbreak = null;
    327  1.1  mrg             sc2.scontinue = null;
    328  1.1  mrg             sc2.sw = null;
    329  1.1  mrg             sc2.fes = funcdecl.fes;
    330  1.1  mrg             sc2.linkage = funcdecl.isCsymbol() ? LINK.c : LINK.d;
    331  1.1  mrg             sc2.stc &= STC.flowThruFunction;
    332  1.1  mrg             sc2.visibility = Visibility(Visibility.Kind.public_);
    333  1.1  mrg             sc2.explicitVisibility = 0;
    334  1.1  mrg             sc2.aligndecl = null;
    335  1.1  mrg             if (funcdecl.ident != Id.require && funcdecl.ident != Id.ensure)
    336  1.1  mrg                 sc2.flags = sc.flags & ~SCOPE.contract;
    337  1.1  mrg             sc2.flags &= ~SCOPE.compile;
    338  1.1  mrg             sc2.tf = null;
    339  1.1  mrg             sc2.os = null;
    340  1.1  mrg             sc2.inLoop = false;
    341  1.1  mrg             sc2.userAttribDecl = null;
    342  1.1  mrg             if (sc2.intypeof == 1)
    343  1.1  mrg                 sc2.intypeof = 2;
    344  1.1  mrg             sc2.ctorflow.fieldinit = null;
    345  1.1  mrg 
    346  1.1  mrg             /* Note: When a lambda is defined immediately under aggregate member
    347  1.1  mrg              * scope, it should be contextless due to prevent interior pointers.
    348  1.1  mrg              * e.g.
    349  1.1  mrg              *      // dg points 'this' - its interior pointer
    350  1.1  mrg              *      class C { int x; void delegate() dg = (){ this.x = 1; }; }
    351  1.1  mrg              *
    352  1.1  mrg              * However, lambdas could be used inside typeof, in order to check
    353  1.1  mrg              * some expressions validity at compile time. For such case the lambda
    354  1.1  mrg              * body can access aggregate instance members.
    355  1.1  mrg              * e.g.
    356  1.1  mrg              *      class C { int x; static assert(is(typeof({ this.x = 1; }))); }
    357  1.1  mrg              *
    358  1.1  mrg              * To properly accept it, mark these lambdas as member functions.
    359  1.1  mrg              */
    360  1.1  mrg             if (auto fld = funcdecl.isFuncLiteralDeclaration())
    361  1.1  mrg             {
    362  1.1  mrg                 if (auto ad = funcdecl.isMember2())
    363  1.1  mrg                 {
    364  1.1  mrg                     if (!sc.intypeof)
    365  1.1  mrg                     {
    366  1.1  mrg                         if (fld.tok == TOK.delegate_)
    367  1.1  mrg                             funcdecl.error("cannot be %s members", ad.kind());
    368  1.1  mrg                         else
    369  1.1  mrg                             fld.tok = TOK.function_;
    370  1.1  mrg                     }
    371  1.1  mrg                     else
    372  1.1  mrg                     {
    373  1.1  mrg                         if (fld.tok != TOK.function_)
    374  1.1  mrg                             fld.tok = TOK.delegate_;
    375  1.1  mrg                     }
    376  1.1  mrg                 }
    377  1.1  mrg             }
    378  1.1  mrg 
    379  1.1  mrg             funcdecl.declareThis(sc2);
    380  1.1  mrg 
    381  1.1  mrg             // Reverts: https://issues.dlang.org/show_bug.cgi?id=5710
    382  1.1  mrg             // No compiler supports this, and there was never any spec for it.
    383  1.1  mrg             // @@@DEPRECATED_2.116@@@
    384  1.1  mrg             // Deprecated in 2.096, can be made an error in 2.116.
    385  1.1  mrg             // The deprecation period is longer than usual as dual-context
    386  1.1  mrg             // functions may be widely used by dmd-compiled projects.
    387  1.1  mrg             // It also gives more time for the implementation of dual-context
    388  1.1  mrg             // functions to be reworked as a frontend-only feature.
    389  1.1  mrg             if (funcdecl.hasDualContext())
    390  1.1  mrg             {
    391  1.1  mrg                 funcdecl.deprecation("function requires a dual-context, which is deprecated");
    392  1.1  mrg                 if (auto ti = sc2.parent ? sc2.parent.isInstantiated() : null)
    393  1.1  mrg                     ti.printInstantiationTrace(Classification.deprecation);
    394  1.1  mrg             }
    395  1.1  mrg 
    396  1.1  mrg             //printf("[%s] ad = %p vthis = %p\n", loc.toChars(), ad, vthis);
    397  1.1  mrg             //if (vthis) printf("\tvthis.type = %s\n", vthis.type.toChars());
    398  1.1  mrg 
    399  1.1  mrg             // Declare hidden variable _arguments[] and _argptr
    400  1.1  mrg             if (f.parameterList.varargs == VarArg.variadic)
    401  1.1  mrg             {
    402  1.1  mrg                 if (f.linkage == LINK.d)
    403  1.1  mrg                 {
    404  1.1  mrg                     // Variadic arguments depend on Typeinfo being defined.
    405  1.1  mrg                     if (!global.params.useTypeInfo || !Type.dtypeinfo || !Type.typeinfotypelist)
    406  1.1  mrg                     {
    407  1.1  mrg                         if (!global.params.useTypeInfo)
    408  1.1  mrg                             funcdecl.error("D-style variadic functions cannot be used with -betterC");
    409  1.1  mrg                         else if (!Type.typeinfotypelist)
    410  1.1  mrg                             funcdecl.error("`object.TypeInfo_Tuple` could not be found, but is implicitly used in D-style variadic functions");
    411  1.1  mrg                         else
    412  1.1  mrg                             funcdecl.error("`object.TypeInfo` could not be found, but is implicitly used in D-style variadic functions");
    413  1.1  mrg                         fatal();
    414  1.1  mrg                     }
    415  1.1  mrg 
    416  1.1  mrg                     // Declare _arguments[]
    417  1.1  mrg                     funcdecl.v_arguments = new VarDeclaration(funcdecl.loc, Type.typeinfotypelist.type, Id._arguments_typeinfo, null);
    418  1.1  mrg                     funcdecl.v_arguments.storage_class |= STC.temp | STC.parameter;
    419  1.1  mrg                     funcdecl.v_arguments.dsymbolSemantic(sc2);
    420  1.1  mrg                     sc2.insert(funcdecl.v_arguments);
    421  1.1  mrg                     funcdecl.v_arguments.parent = funcdecl;
    422  1.1  mrg 
    423  1.1  mrg                     //Type t = Type.dtypeinfo.type.constOf().arrayOf();
    424  1.1  mrg                     Type t = Type.dtypeinfo.type.arrayOf();
    425  1.1  mrg                     _arguments = new VarDeclaration(funcdecl.loc, t, Id._arguments, null);
    426  1.1  mrg                     _arguments.storage_class |= STC.temp;
    427  1.1  mrg                     _arguments.dsymbolSemantic(sc2);
    428  1.1  mrg                     sc2.insert(_arguments);
    429  1.1  mrg                     _arguments.parent = funcdecl;
    430  1.1  mrg                 }
    431  1.1  mrg                 if (f.linkage == LINK.d || f.parameterList.length)
    432  1.1  mrg                 {
    433  1.1  mrg                     // Declare _argptr
    434  1.1  mrg                     Type t = target.va_listType(funcdecl.loc, sc);
    435  1.1  mrg                     // Init is handled in FuncDeclaration_toObjFile
    436  1.1  mrg                     funcdecl.v_argptr = new VarDeclaration(funcdecl.loc, t, Id._argptr, new VoidInitializer(funcdecl.loc));
    437  1.1  mrg                     funcdecl.v_argptr.storage_class |= STC.temp;
    438  1.1  mrg                     funcdecl.v_argptr.dsymbolSemantic(sc2);
    439  1.1  mrg                     sc2.insert(funcdecl.v_argptr);
    440  1.1  mrg                     funcdecl.v_argptr.parent = funcdecl;
    441  1.1  mrg                 }
    442  1.1  mrg             }
    443  1.1  mrg 
    444  1.1  mrg             /* Declare all the function parameters as variables
    445  1.1  mrg              * and install them in parameters[]
    446  1.1  mrg              */
    447  1.1  mrg             if (const nparams = f.parameterList.length)
    448  1.1  mrg             {
    449  1.1  mrg                 /* parameters[] has all the tuples removed, as the back end
    450  1.1  mrg                  * doesn't know about tuples
    451  1.1  mrg                  */
    452  1.1  mrg                 funcdecl.parameters = new VarDeclarations();
    453  1.1  mrg                 funcdecl.parameters.reserve(nparams);
    454  1.1  mrg                 foreach (i, fparam; f.parameterList)
    455  1.1  mrg                 {
    456  1.1  mrg                     Identifier id = fparam.ident;
    457  1.1  mrg                     StorageClass stc = 0;
    458  1.1  mrg                     if (!id)
    459  1.1  mrg                     {
    460  1.1  mrg                         /* Generate identifier for un-named parameter,
    461  1.1  mrg                          * because we need it later on.
    462  1.1  mrg                          */
    463  1.1  mrg                         fparam.ident = id = Identifier.generateId("_param_", i);
    464  1.1  mrg                         stc |= STC.temp;
    465  1.1  mrg                     }
    466  1.1  mrg                     Type vtype = fparam.type;
    467  1.1  mrg                     auto v = new VarDeclaration(funcdecl.loc, vtype, id, null);
    468  1.1  mrg                     //printf("declaring parameter %s of type %s\n", v.toChars(), v.type.toChars());
    469  1.1  mrg                     stc |= STC.parameter;
    470  1.1  mrg                     if (f.parameterList.varargs == VarArg.typesafe && i + 1 == nparams)
    471  1.1  mrg                     {
    472  1.1  mrg                         stc |= STC.variadic;
    473  1.1  mrg                         auto vtypeb = vtype.toBasetype();
    474  1.1  mrg                         if (vtypeb.ty == Tarray || vtypeb.ty == Tclass)
    475  1.1  mrg                         {
    476  1.1  mrg                             /* Since it'll be pointing into the stack for the array
    477  1.1  mrg                              * contents, it needs to be `scope`
    478  1.1  mrg                              */
    479  1.1  mrg                             stc |= STC.scope_;
    480  1.1  mrg                         }
    481  1.1  mrg                     }
    482  1.1  mrg 
    483  1.1  mrg                     if ((funcdecl.flags & FUNCFLAG.inferScope) && !(fparam.storageClass & STC.scope_))
    484  1.1  mrg                         stc |= STC.maybescope;
    485  1.1  mrg 
    486  1.1  mrg                     stc |= fparam.storageClass & (STC.IOR | STC.return_ | STC.scope_ | STC.lazy_ | STC.final_ | STC.TYPECTOR | STC.nodtor | STC.returnScope);
    487  1.1  mrg                     v.storage_class = stc;
    488  1.1  mrg                     v.dsymbolSemantic(sc2);
    489  1.1  mrg                     if (!sc2.insert(v))
    490  1.1  mrg                     {
    491  1.1  mrg                         funcdecl.error("parameter `%s.%s` is already defined", funcdecl.toChars(), v.toChars());
    492  1.1  mrg                         funcdecl.errors = true;
    493  1.1  mrg                     }
    494  1.1  mrg                     else
    495  1.1  mrg                         funcdecl.parameters.push(v);
    496  1.1  mrg                     funcdecl.localsymtab.insert(v);
    497  1.1  mrg                     v.parent = funcdecl;
    498  1.1  mrg                     if (fparam.userAttribDecl)
    499  1.1  mrg                         v.userAttribDecl = fparam.userAttribDecl;
    500  1.1  mrg                 }
    501  1.1  mrg             }
    502  1.1  mrg 
    503  1.1  mrg             // Declare the tuple symbols and put them in the symbol table,
    504  1.1  mrg             // but not in parameters[].
    505  1.1  mrg             if (f.parameterList.parameters)
    506  1.1  mrg             foreach (fparam; *f.parameterList.parameters)
    507  1.1  mrg             {
    508  1.1  mrg                 if (!fparam.ident)
    509  1.1  mrg                     continue; // never used, so ignore
    510  1.1  mrg                 // expand any tuples
    511  1.1  mrg                 if (fparam.type.ty != Ttuple)
    512  1.1  mrg                     continue;
    513  1.1  mrg 
    514  1.1  mrg                 TypeTuple t = cast(TypeTuple)fparam.type;
    515  1.1  mrg                 size_t dim = Parameter.dim(t.arguments);
    516  1.1  mrg                 auto exps = new Objects(dim);
    517  1.1  mrg                 foreach (j; 0 .. dim)
    518  1.1  mrg                 {
    519  1.1  mrg                     Parameter narg = Parameter.getNth(t.arguments, j);
    520  1.1  mrg                     assert(narg.ident);
    521  1.1  mrg                     VarDeclaration v = sc2.search(Loc.initial, narg.ident, null).isVarDeclaration();
    522  1.1  mrg                     assert(v);
    523  1.1  mrg                     (*exps)[j] = new VarExp(v.loc, v);
    524  1.1  mrg                 }
    525  1.1  mrg                 assert(fparam.ident);
    526  1.1  mrg                 auto v = new TupleDeclaration(funcdecl.loc, fparam.ident, exps);
    527  1.1  mrg                 //printf("declaring tuple %s\n", v.toChars());
    528  1.1  mrg                 v.isexp = true;
    529  1.1  mrg                 if (!sc2.insert(v))
    530  1.1  mrg                     funcdecl.error("parameter `%s.%s` is already defined", funcdecl.toChars(), v.toChars());
    531  1.1  mrg                 funcdecl.localsymtab.insert(v);
    532  1.1  mrg                 v.parent = funcdecl;
    533  1.1  mrg             }
    534  1.1  mrg 
    535  1.1  mrg             // Precondition invariant
    536  1.1  mrg             Statement fpreinv = null;
    537  1.1  mrg             if (funcdecl.addPreInvariant())
    538  1.1  mrg             {
    539  1.1  mrg                 Expression e = addInvariant(funcdecl.isThis(), funcdecl.vthis);
    540  1.1  mrg                 if (e)
    541  1.1  mrg                     fpreinv = new ExpStatement(Loc.initial, e);
    542  1.1  mrg             }
    543  1.1  mrg 
    544  1.1  mrg             // Postcondition invariant
    545  1.1  mrg             Statement fpostinv = null;
    546  1.1  mrg             if (funcdecl.addPostInvariant())
    547  1.1  mrg             {
    548  1.1  mrg                 Expression e = addInvariant(funcdecl.isThis(), funcdecl.vthis);
    549  1.1  mrg                 if (e)
    550  1.1  mrg                     fpostinv = new ExpStatement(Loc.initial, e);
    551  1.1  mrg             }
    552  1.1  mrg 
    553  1.1  mrg             // Pre/Postcondition contract
    554  1.1  mrg             if (!funcdecl.fbody)
    555  1.1  mrg                 funcdecl.buildEnsureRequire();
    556  1.1  mrg 
    557  1.1  mrg             Scope* scout = null;
    558  1.1  mrg             if (needEnsure || funcdecl.addPostInvariant())
    559  1.1  mrg             {
    560  1.1  mrg                 /* https://issues.dlang.org/show_bug.cgi?id=3657
    561  1.1  mrg                  * Set the correct end line number for fensure scope.
    562  1.1  mrg                  */
    563  1.1  mrg                 uint fensure_endlin = funcdecl.endloc.linnum;
    564  1.1  mrg                 if (funcdecl.fensure)
    565  1.1  mrg                     if (auto s = funcdecl.fensure.isScopeStatement())
    566  1.1  mrg                         fensure_endlin = s.endloc.linnum;
    567  1.1  mrg 
    568  1.1  mrg                 if ((needEnsure && global.params.useOut == CHECKENABLE.on) || fpostinv)
    569  1.1  mrg                 {
    570  1.1  mrg                     funcdecl.returnLabel = funcdecl.searchLabel(Id.returnLabel);
    571  1.1  mrg                 }
    572  1.1  mrg 
    573  1.1  mrg                 // scope of out contract (need for vresult.semantic)
    574  1.1  mrg                 auto sym = new ScopeDsymbol(funcdecl.loc, null);
    575  1.1  mrg                 sym.parent = sc2.scopesym;
    576  1.1  mrg                 sym.endlinnum = fensure_endlin;
    577  1.1  mrg                 scout = sc2.push(sym);
    578  1.1  mrg             }
    579  1.1  mrg 
    580  1.1  mrg             if (funcdecl.fbody)
    581  1.1  mrg             {
    582  1.1  mrg                 auto sym = new ScopeDsymbol(funcdecl.loc, null);
    583  1.1  mrg                 sym.parent = sc2.scopesym;
    584  1.1  mrg                 sym.endlinnum = funcdecl.endloc.linnum;
    585  1.1  mrg                 sc2 = sc2.push(sym);
    586  1.1  mrg 
    587  1.1  mrg                 auto ad2 = funcdecl.isMemberLocal();
    588  1.1  mrg 
    589  1.1  mrg                 /* If this is a class constructor
    590  1.1  mrg                  */
    591  1.1  mrg                 if (ad2 && funcdecl.isCtorDeclaration())
    592  1.1  mrg                 {
    593  1.1  mrg                     sc2.ctorflow.allocFieldinit(ad2.fields.dim);
    594  1.1  mrg                     foreach (v; ad2.fields)
    595  1.1  mrg                     {
    596  1.1  mrg                         v.ctorinit = 0;
    597  1.1  mrg                     }
    598  1.1  mrg                 }
    599  1.1  mrg 
    600  1.1  mrg                 bool inferRef = (f.isref && (funcdecl.storage_class & STC.auto_));
    601  1.1  mrg 
    602  1.1  mrg                 funcdecl.fbody = funcdecl.fbody.statementSemantic(sc2);
    603  1.1  mrg                 if (!funcdecl.fbody)
    604  1.1  mrg                     funcdecl.fbody = new CompoundStatement(Loc.initial, new Statements());
    605  1.1  mrg 
    606  1.1  mrg                 if (funcdecl.isNaked())
    607  1.1  mrg                 {
    608  1.1  mrg                     fpreinv = null;         // can't accommodate with no stack frame
    609  1.1  mrg                     fpostinv = null;
    610  1.1  mrg                 }
    611  1.1  mrg 
    612  1.1  mrg                 assert(funcdecl.type == f || (funcdecl.type.ty == Tfunction && f.purity == PURE.impure && (cast(TypeFunction)funcdecl.type).purity >= PURE.fwdref));
    613  1.1  mrg                 f = cast(TypeFunction)funcdecl.type;
    614  1.1  mrg 
    615  1.1  mrg                 if (funcdecl.inferRetType)
    616  1.1  mrg                 {
    617  1.1  mrg                     // If no return type inferred yet, then infer a void
    618  1.1  mrg                     if (!f.next)
    619  1.1  mrg                         f.next = Type.tvoid;
    620  1.1  mrg                     if (f.checkRetType(funcdecl.loc))
    621  1.1  mrg                         funcdecl.fbody = new ErrorStatement();
    622  1.1  mrg                     else
    623  1.1  mrg                         funcdecl.checkMain(); // Check main() parameters and return type
    624  1.1  mrg                 }
    625  1.1  mrg 
    626  1.1  mrg                 if (f.next !is null)
    627  1.1  mrg                     f.next.checkComplexTransition(funcdecl.loc, sc);
    628  1.1  mrg 
    629  1.1  mrg                 if (funcdecl.returns && !funcdecl.fbody.isErrorStatement())
    630  1.1  mrg                 {
    631  1.1  mrg                     for (size_t i = 0; i < funcdecl.returns.dim;)
    632  1.1  mrg                     {
    633  1.1  mrg                         Expression exp = (*funcdecl.returns)[i].exp;
    634  1.1  mrg                         if (exp.op == EXP.variable && (cast(VarExp)exp).var == funcdecl.vresult)
    635  1.1  mrg                         {
    636  1.1  mrg                             if (addReturn0())
    637  1.1  mrg                                 exp.type = Type.tint32;
    638  1.1  mrg                             else
    639  1.1  mrg                                 exp.type = f.next;
    640  1.1  mrg                             // Remove `return vresult;` from returns
    641  1.1  mrg                             funcdecl.returns.remove(i);
    642  1.1  mrg                             continue;
    643  1.1  mrg                         }
    644  1.1  mrg                         if (inferRef && f.isref && !exp.type.constConv(f.next)) // https://issues.dlang.org/show_bug.cgi?id=13336
    645  1.1  mrg                             f.isref = false;
    646  1.1  mrg                         i++;
    647  1.1  mrg                     }
    648  1.1  mrg                 }
    649  1.1  mrg                 if (f.isref) // Function returns a reference
    650  1.1  mrg                 {
    651  1.1  mrg                     if (funcdecl.storage_class & STC.auto_)
    652  1.1  mrg                         funcdecl.storage_class &= ~STC.auto_;
    653  1.1  mrg                 }
    654  1.1  mrg 
    655  1.1  mrg                 // handle NRVO
    656  1.1  mrg                 if (!target.isReturnOnStack(f, funcdecl.needThis()) || !funcdecl.checkNRVO())
    657  1.1  mrg                     funcdecl.flags &= ~FUNCFLAG.NRVO;
    658  1.1  mrg 
    659  1.1  mrg                 if (funcdecl.fbody.isErrorStatement())
    660  1.1  mrg                 {
    661  1.1  mrg                 }
    662  1.1  mrg                 else if (funcdecl.isStaticCtorDeclaration())
    663  1.1  mrg                 {
    664  1.1  mrg                     /* It's a static constructor. Ensure that all
    665  1.1  mrg                      * ctor consts were initialized.
    666  1.1  mrg                      */
    667  1.1  mrg                     ScopeDsymbol pd = funcdecl.toParent().isScopeDsymbol();
    668  1.1  mrg                     for (size_t i = 0; i < pd.members.dim; i++)
    669  1.1  mrg                     {
    670  1.1  mrg                         Dsymbol s = (*pd.members)[i];
    671  1.1  mrg                         s.checkCtorConstInit();
    672  1.1  mrg                     }
    673  1.1  mrg                 }
    674  1.1  mrg                 else if (ad2 && funcdecl.isCtorDeclaration())
    675  1.1  mrg                 {
    676  1.1  mrg                     ClassDeclaration cd = ad2.isClassDeclaration();
    677  1.1  mrg 
    678  1.1  mrg                     // Verify that all the ctorinit fields got initialized
    679  1.1  mrg                     if (!(sc2.ctorflow.callSuper & CSX.this_ctor))
    680  1.1  mrg                     {
    681  1.1  mrg                         foreach (i, v; ad2.fields)
    682  1.1  mrg                         {
    683  1.1  mrg                             if (v.isThisDeclaration())
    684  1.1  mrg                                 continue;
    685  1.1  mrg                             if (v.ctorinit == 0)
    686  1.1  mrg                             {
    687  1.1  mrg                                 /* Current bugs in the flow analysis:
    688  1.1  mrg                                  * 1. union members should not produce error messages even if
    689  1.1  mrg                                  *    not assigned to
    690  1.1  mrg                                  * 2. structs should recognize delegating opAssign calls as well
    691  1.1  mrg                                  *    as delegating calls to other constructors
    692  1.1  mrg                                  */
    693  1.1  mrg                                 if (v.isCtorinit() && !v.type.isMutable() && cd)
    694  1.1  mrg                                     funcdecl.error("missing initializer for %s field `%s`", MODtoChars(v.type.mod), v.toChars());
    695  1.1  mrg                                 else if (v.storage_class & STC.nodefaultctor)
    696  1.1  mrg                                     error(funcdecl.loc, "field `%s` must be initialized in constructor", v.toChars());
    697  1.1  mrg                                 else if (v.type.needsNested())
    698  1.1  mrg                                     error(funcdecl.loc, "field `%s` must be initialized in constructor, because it is nested struct", v.toChars());
    699  1.1  mrg                             }
    700  1.1  mrg                             else
    701  1.1  mrg                             {
    702  1.1  mrg                                 bool mustInit = (v.storage_class & STC.nodefaultctor || v.type.needsNested());
    703  1.1  mrg                                 if (mustInit && !(sc2.ctorflow.fieldinit[i].csx & CSX.this_ctor))
    704  1.1  mrg                                 {
    705  1.1  mrg                                     funcdecl.error("field `%s` must be initialized but skipped", v.toChars());
    706  1.1  mrg                                 }
    707  1.1  mrg                             }
    708  1.1  mrg                         }
    709  1.1  mrg                     }
    710  1.1  mrg                     sc2.ctorflow.freeFieldinit();
    711  1.1  mrg 
    712  1.1  mrg                     if (cd && !(sc2.ctorflow.callSuper & CSX.any_ctor) && cd.baseClass && cd.baseClass.ctor)
    713  1.1  mrg                     {
    714  1.1  mrg                         sc2.ctorflow.callSuper = CSX.none;
    715  1.1  mrg 
    716  1.1  mrg                         // Insert implicit super() at start of fbody
    717  1.1  mrg                         Type tthis = ad2.type.addMod(funcdecl.vthis.type.mod);
    718  1.1  mrg                         FuncDeclaration fd = resolveFuncCall(Loc.initial, sc2, cd.baseClass.ctor, null, tthis, null, FuncResolveFlag.quiet);
    719  1.1  mrg                         if (!fd)
    720  1.1  mrg                         {
    721  1.1  mrg                             funcdecl.error("no match for implicit `super()` call in constructor");
    722  1.1  mrg                         }
    723  1.1  mrg                         else if (fd.storage_class & STC.disable)
    724  1.1  mrg                         {
    725  1.1  mrg                             funcdecl.error("cannot call `super()` implicitly because it is annotated with `@disable`");
    726  1.1  mrg                         }
    727  1.1  mrg                         else
    728  1.1  mrg                         {
    729  1.1  mrg                             Expression e1 = new SuperExp(Loc.initial);
    730  1.1  mrg                             Expression e = new CallExp(Loc.initial, e1);
    731  1.1  mrg                             e = e.expressionSemantic(sc2);
    732  1.1  mrg                             Statement s = new ExpStatement(Loc.initial, e);
    733  1.1  mrg                             funcdecl.fbody = new CompoundStatement(Loc.initial, s, funcdecl.fbody);
    734  1.1  mrg                         }
    735  1.1  mrg                     }
    736  1.1  mrg                     //printf("ctorflow.callSuper = x%x\n", sc2.ctorflow.callSuper);
    737  1.1  mrg                 }
    738  1.1  mrg 
    739  1.1  mrg                 /* https://issues.dlang.org/show_bug.cgi?id=17502
    740  1.1  mrg                  * Wait until after the return type has been inferred before
    741  1.1  mrg                  * generating the contracts for this function, and merging contracts
    742  1.1  mrg                  * from overrides.
    743  1.1  mrg                  *
    744  1.1  mrg                  * https://issues.dlang.org/show_bug.cgi?id=17893
    745  1.1  mrg                  * However should take care to generate this before inferered
    746  1.1  mrg                  * function attributes are applied, such as 'nothrow'.
    747  1.1  mrg                  *
    748  1.1  mrg                  * This was originally at the end of the first semantic pass, but
    749  1.1  mrg                  * required a fix-up to be done here for the '__result' variable
    750  1.1  mrg                  * type of __ensure() inside auto functions, but this didn't work
    751  1.1  mrg                  * if the out parameter was implicit.
    752  1.1  mrg                  */
    753  1.1  mrg                 funcdecl.buildEnsureRequire();
    754  1.1  mrg 
    755  1.1  mrg                 // Check for errors related to 'nothrow'.
    756  1.1  mrg                 const blockexit = funcdecl.fbody.blockExit(funcdecl, f.isnothrow);
    757  1.1  mrg                 if (f.isnothrow && blockexit & BE.throw_)
    758  1.1  mrg                     error(funcdecl.loc, "%s `%s` may throw but is marked as `nothrow`", funcdecl.kind(), funcdecl.toPrettyChars());
    759  1.1  mrg 
    760  1.1  mrg                 if (!(blockexit & (BE.throw_ | BE.halt) || funcdecl.flags & FUNCFLAG.hasCatches))
    761  1.1  mrg                 {
    762  1.1  mrg                     /* Don't generate unwind tables for this function
    763  1.1  mrg                      * https://issues.dlang.org/show_bug.cgi?id=17997
    764  1.1  mrg                      */
    765  1.1  mrg                     funcdecl.flags |= FUNCFLAG.noEH;
    766  1.1  mrg                 }
    767  1.1  mrg 
    768  1.1  mrg                 if (funcdecl.flags & FUNCFLAG.nothrowInprocess)
    769  1.1  mrg                 {
    770  1.1  mrg                     if (funcdecl.type == f)
    771  1.1  mrg                         f = cast(TypeFunction)f.copy();
    772  1.1  mrg                     f.isnothrow = !(blockexit & BE.throw_);
    773  1.1  mrg                 }
    774  1.1  mrg 
    775  1.1  mrg                 if (funcdecl.fbody.isErrorStatement())
    776  1.1  mrg                 {
    777  1.1  mrg                 }
    778  1.1  mrg                 else if (ad2 && funcdecl.isCtorDeclaration())
    779  1.1  mrg                 {
    780  1.1  mrg                     /* Append:
    781  1.1  mrg                      *  return this;
    782  1.1  mrg                      * to function body
    783  1.1  mrg                      */
    784  1.1  mrg                     if (blockexit & BE.fallthru)
    785  1.1  mrg                     {
    786  1.1  mrg                         Statement s = new ReturnStatement(funcdecl.loc, null);
    787  1.1  mrg                         s = s.statementSemantic(sc2);
    788  1.1  mrg                         funcdecl.fbody = new CompoundStatement(funcdecl.loc, funcdecl.fbody, s);
    789  1.1  mrg                         funcdecl.hasReturnExp |= (funcdecl.hasReturnExp & 1 ? 16 : 1);
    790  1.1  mrg                     }
    791  1.1  mrg                 }
    792  1.1  mrg                 else if (funcdecl.fes)
    793  1.1  mrg                 {
    794  1.1  mrg                     // For foreach(){} body, append a return 0;
    795  1.1  mrg                     if (blockexit & BE.fallthru)
    796  1.1  mrg                     {
    797  1.1  mrg                         Expression e = IntegerExp.literal!0;
    798  1.1  mrg                         Statement s = new ReturnStatement(Loc.initial, e);
    799  1.1  mrg                         funcdecl.fbody = new CompoundStatement(Loc.initial, funcdecl.fbody, s);
    800  1.1  mrg                         funcdecl.hasReturnExp |= (funcdecl.hasReturnExp & 1 ? 16 : 1);
    801  1.1  mrg                     }
    802  1.1  mrg                     assert(!funcdecl.returnLabel);
    803  1.1  mrg                 }
    804  1.1  mrg                 else if (f.next.toBasetype().ty == Tnoreturn)
    805  1.1  mrg                 {
    806  1.1  mrg                     // Fallthrough despite being declared as noreturn? return is already rejected when evaluating the ReturnStatement
    807  1.1  mrg                     if (blockexit & BE.fallthru)
    808  1.1  mrg                     {
    809  1.1  mrg                         funcdecl.error("is typed as `%s` but does return", f.next.toChars());
    810  1.1  mrg                         funcdecl.loc.errorSupplemental("`noreturn` functions must either throw, abort or loop indefinitely");
    811  1.1  mrg                     }
    812  1.1  mrg                 }
    813  1.1  mrg                 else
    814  1.1  mrg                 {
    815  1.1  mrg                     const(bool) inlineAsm = (funcdecl.hasReturnExp & 8) != 0;
    816  1.1  mrg                     if ((blockexit & BE.fallthru) && f.next.ty != Tvoid && !inlineAsm && !(sc.flags & SCOPE.Cfile))
    817  1.1  mrg                     {
    818  1.1  mrg                         if (!funcdecl.hasReturnExp)
    819  1.1  mrg                             funcdecl.error("has no `return` statement, but is expected to return a value of type `%s`", f.next.toChars());
    820  1.1  mrg                         else
    821  1.1  mrg                             funcdecl.error("no `return exp;` or `assert(0);` at end of function");
    822  1.1  mrg                     }
    823  1.1  mrg                 }
    824  1.1  mrg 
    825  1.1  mrg                 if (funcdecl.returns)
    826  1.1  mrg                 {
    827  1.1  mrg                     bool implicit0 = addReturn0();
    828  1.1  mrg                     Type tret = implicit0 ? Type.tint32 : f.next;
    829  1.1  mrg                     assert(tret.ty != Tvoid);
    830  1.1  mrg                     if (funcdecl.vresult || funcdecl.returnLabel)
    831  1.1  mrg                         funcdecl.buildResultVar(scout ? scout : sc2, tret);
    832  1.1  mrg 
    833  1.1  mrg                     /* Cannot move this loop into NrvoWalker, because
    834  1.1  mrg                      * returns[i] may be in the nested delegate for foreach-body.
    835  1.1  mrg                      */
    836  1.1  mrg                     for (size_t i = 0; i < funcdecl.returns.dim; i++)
    837  1.1  mrg                     {
    838  1.1  mrg                         ReturnStatement rs = (*funcdecl.returns)[i];
    839  1.1  mrg                         Expression exp = rs.exp;
    840  1.1  mrg                         if (exp.op == EXP.error)
    841  1.1  mrg                             continue;
    842  1.1  mrg                         if (tret.ty == Terror)
    843  1.1  mrg                         {
    844  1.1  mrg                             // https://issues.dlang.org/show_bug.cgi?id=13702
    845  1.1  mrg                             exp = checkGC(sc2, exp);
    846  1.1  mrg                             continue;
    847  1.1  mrg                         }
    848  1.1  mrg 
    849  1.1  mrg                         /* If the expression in the return statement (exp) cannot be implicitly
    850  1.1  mrg                          * converted to the return type (tret) of the function and if the
    851  1.1  mrg                          * type of the expression is type isolated, then it may be possible
    852  1.1  mrg                          * that a promotion to `immutable` or `inout` (through a cast) will
    853  1.1  mrg                          * match the return type.
    854  1.1  mrg                          */
    855  1.1  mrg                         if (!exp.implicitConvTo(tret) && funcdecl.isTypeIsolated(exp.type))
    856  1.1  mrg                         {
    857  1.1  mrg                             /* https://issues.dlang.org/show_bug.cgi?id=20073
    858  1.1  mrg                              *
    859  1.1  mrg                              * The problem is that if the type of the returned expression (exp.type)
    860  1.1  mrg                              * is an aggregated declaration with an alias this, the alias this may be
    861  1.1  mrg                              * used for the conversion testing without it being an isolated type.
    862  1.1  mrg                              *
    863  1.1  mrg                              * To make sure this does not happen, we can test here the implicit conversion
    864  1.1  mrg                              * only for the aggregated declaration type by using `implicitConvToWithoutAliasThis`.
    865  1.1  mrg                              * The implicit conversion with alias this is taken care of later.
    866  1.1  mrg                              */
    867  1.1  mrg                             AggregateDeclaration aggDecl = isAggregate(exp.type);
    868  1.1  mrg                             TypeStruct tstruct;
    869  1.1  mrg                             TypeClass tclass;
    870  1.1  mrg                             bool hasAliasThis;
    871  1.1  mrg                             if (aggDecl && aggDecl.aliasthis)
    872  1.1  mrg                             {
    873  1.1  mrg                                 hasAliasThis = true;
    874  1.1  mrg                                 tclass = exp.type.isTypeClass();
    875  1.1  mrg                                 if (!tclass)
    876  1.1  mrg                                     tstruct = exp.type.isTypeStruct();
    877  1.1  mrg                                 assert(tclass || tstruct);
    878  1.1  mrg                             }
    879  1.1  mrg                             if (hasAliasThis)
    880  1.1  mrg                             {
    881  1.1  mrg                                 if (tclass)
    882  1.1  mrg                                 {
    883  1.1  mrg                                     if ((cast(TypeClass)(exp.type.immutableOf())).implicitConvToWithoutAliasThis(tret))
    884  1.1  mrg                                         exp = exp.castTo(sc2, exp.type.immutableOf());
    885  1.1  mrg                                     else if ((cast(TypeClass)(exp.type.wildOf())).implicitConvToWithoutAliasThis(tret))
    886  1.1  mrg                                         exp = exp.castTo(sc2, exp.type.wildOf());
    887  1.1  mrg                                 }
    888  1.1  mrg                                 else
    889  1.1  mrg                                 {
    890  1.1  mrg                                     if ((cast(TypeStruct)exp.type.immutableOf()).implicitConvToWithoutAliasThis(tret))
    891  1.1  mrg                                         exp = exp.castTo(sc2, exp.type.immutableOf());
    892  1.1  mrg                                     else if ((cast(TypeStruct)exp.type.immutableOf()).implicitConvToWithoutAliasThis(tret))
    893  1.1  mrg                                         exp = exp.castTo(sc2, exp.type.wildOf());
    894  1.1  mrg                                 }
    895  1.1  mrg                             }
    896  1.1  mrg                             else
    897  1.1  mrg                             {
    898  1.1  mrg                                 if (exp.type.immutableOf().implicitConvTo(tret))
    899  1.1  mrg                                     exp = exp.castTo(sc2, exp.type.immutableOf());
    900  1.1  mrg                                 else if (exp.type.wildOf().implicitConvTo(tret))
    901  1.1  mrg                                     exp = exp.castTo(sc2, exp.type.wildOf());
    902  1.1  mrg                             }
    903  1.1  mrg                         }
    904  1.1  mrg 
    905  1.1  mrg                         const hasCopyCtor = exp.type.ty == Tstruct && (cast(TypeStruct)exp.type).sym.hasCopyCtor;
    906  1.1  mrg                         // if a copy constructor is present, the return type conversion will be handled by it
    907  1.1  mrg                         if (!(hasCopyCtor && exp.isLvalue()))
    908  1.1  mrg                         {
    909  1.1  mrg                             if (f.isref && !MODimplicitConv(exp.type.mod, tret.mod) && !tret.isTypeSArray())
    910  1.1  mrg                                 error(exp.loc, "expression `%s` of type `%s` is not implicitly convertible to return type `ref %s`",
    911  1.1  mrg                                       exp.toChars(), exp.type.toChars(), tret.toChars());
    912  1.1  mrg                             else
    913  1.1  mrg                                 exp = exp.implicitCastTo(sc2, tret);
    914  1.1  mrg                         }
    915  1.1  mrg 
    916  1.1  mrg                         if (f.isref)
    917  1.1  mrg                         {
    918  1.1  mrg                             // Function returns a reference
    919  1.1  mrg                             exp = exp.toLvalue(sc2, exp);
    920  1.1  mrg                             checkReturnEscapeRef(sc2, exp, false);
    921  1.1  mrg                             exp = exp.optimize(WANTvalue, /*keepLvalue*/ true);
    922  1.1  mrg                         }
    923  1.1  mrg                         else
    924  1.1  mrg                         {
    925  1.1  mrg                             exp = exp.optimize(WANTvalue);
    926  1.1  mrg 
    927  1.1  mrg                             /* https://issues.dlang.org/show_bug.cgi?id=10789
    928  1.1  mrg                              * If NRVO is not possible, all returned lvalues should call their postblits.
    929  1.1  mrg                              */
    930  1.1  mrg                             if (!funcdecl.isNRVO())
    931  1.1  mrg                                 exp = doCopyOrMove(sc2, exp, f.next);
    932  1.1  mrg 
    933  1.1  mrg                             if (tret.hasPointers())
    934  1.1  mrg                                 checkReturnEscape(sc2, exp, false);
    935  1.1  mrg                         }
    936  1.1  mrg 
    937  1.1  mrg                         exp = checkGC(sc2, exp);
    938  1.1  mrg 
    939  1.1  mrg                         if (funcdecl.vresult)
    940  1.1  mrg                         {
    941  1.1  mrg                             // Create: return vresult = exp;
    942  1.1  mrg                             exp = new BlitExp(rs.loc, funcdecl.vresult, exp);
    943  1.1  mrg                             exp.type = funcdecl.vresult.type;
    944  1.1  mrg 
    945  1.1  mrg                             if (rs.caseDim)
    946  1.1  mrg                                 exp = Expression.combine(exp, new IntegerExp(rs.caseDim));
    947  1.1  mrg                         }
    948  1.1  mrg                         else if (funcdecl.tintro && !tret.equals(funcdecl.tintro.nextOf()))
    949  1.1  mrg                         {
    950  1.1  mrg                             exp = exp.implicitCastTo(sc2, funcdecl.tintro.nextOf());
    951  1.1  mrg                         }
    952  1.1  mrg                         rs.exp = exp;
    953  1.1  mrg                     }
    954  1.1  mrg                 }
    955  1.1  mrg                 if (funcdecl.nrvo_var || funcdecl.returnLabel)
    956  1.1  mrg                 {
    957  1.1  mrg                     scope NrvoWalker nw = new NrvoWalker();
    958  1.1  mrg                     nw.fd = funcdecl;
    959  1.1  mrg                     nw.sc = sc2;
    960  1.1  mrg                     nw.visitStmt(funcdecl.fbody);
    961  1.1  mrg                 }
    962  1.1  mrg 
    963  1.1  mrg                 sc2 = sc2.pop();
    964  1.1  mrg             }
    965  1.1  mrg 
    966  1.1  mrg             if (global.params.inclusiveInContracts)
    967  1.1  mrg             {
    968  1.1  mrg                 funcdecl.frequire = funcdecl.mergeFrequireInclusivePreview(
    969  1.1  mrg                     funcdecl.frequire, funcdecl.fdrequireParams);
    970  1.1  mrg             }
    971  1.1  mrg             else
    972  1.1  mrg             {
    973  1.1  mrg                 funcdecl.frequire = funcdecl.mergeFrequire(funcdecl.frequire, funcdecl.fdrequireParams);
    974  1.1  mrg             }
    975  1.1  mrg             funcdecl.fensure = funcdecl.mergeFensure(funcdecl.fensure, Id.result, funcdecl.fdensureParams);
    976  1.1  mrg 
    977  1.1  mrg             Statement freq = funcdecl.frequire;
    978  1.1  mrg             Statement fens = funcdecl.fensure;
    979  1.1  mrg 
    980  1.1  mrg             /* Do the semantic analysis on the [in] preconditions and
    981  1.1  mrg              * [out] postconditions.
    982  1.1  mrg              */
    983  1.1  mrg             if (freq)
    984  1.1  mrg             {
    985  1.1  mrg                 /* frequire is composed of the [in] contracts
    986  1.1  mrg                  */
    987  1.1  mrg                 auto sym = new ScopeDsymbol(funcdecl.loc, null);
    988  1.1  mrg                 sym.parent = sc2.scopesym;
    989  1.1  mrg                 sym.endlinnum = funcdecl.endloc.linnum;
    990  1.1  mrg                 sc2 = sc2.push(sym);
    991  1.1  mrg                 sc2.flags = (sc2.flags & ~SCOPE.contract) | SCOPE.require;
    992  1.1  mrg 
    993  1.1  mrg                 // BUG: need to error if accessing out parameters
    994  1.1  mrg                 // BUG: need to disallow returns and throws
    995  1.1  mrg                 // BUG: verify that all in and ref parameters are read
    996  1.1  mrg                 freq = freq.statementSemantic(sc2);
    997  1.1  mrg                 freq.blockExit(funcdecl, false);
    998  1.1  mrg 
    999  1.1  mrg                 funcdecl.flags &= ~FUNCFLAG.noEH;
   1000  1.1  mrg 
   1001  1.1  mrg                 sc2 = sc2.pop();
   1002  1.1  mrg 
   1003  1.1  mrg                 if (global.params.useIn == CHECKENABLE.off)
   1004  1.1  mrg                     freq = null;
   1005  1.1  mrg             }
   1006  1.1  mrg             if (fens)
   1007  1.1  mrg             {
   1008  1.1  mrg                 /* fensure is composed of the [out] contracts
   1009  1.1  mrg                  */
   1010  1.1  mrg                 if (f.next.ty == Tvoid && funcdecl.fensures)
   1011  1.1  mrg                 {
   1012  1.1  mrg                     foreach (e; *funcdecl.fensures)
   1013  1.1  mrg                     {
   1014  1.1  mrg                         if (e.id)
   1015  1.1  mrg                         {
   1016  1.1  mrg                             funcdecl.error(e.ensure.loc, "`void` functions have no result");
   1017  1.1  mrg                             //fens = null;
   1018  1.1  mrg                         }
   1019  1.1  mrg                     }
   1020  1.1  mrg                 }
   1021  1.1  mrg 
   1022  1.1  mrg                 sc2 = scout; //push
   1023  1.1  mrg                 sc2.flags = (sc2.flags & ~SCOPE.contract) | SCOPE.ensure;
   1024  1.1  mrg 
   1025  1.1  mrg                 // BUG: need to disallow returns and throws
   1026  1.1  mrg 
   1027  1.1  mrg                 if (funcdecl.fensure && f.next.ty != Tvoid)
   1028  1.1  mrg                     funcdecl.buildResultVar(scout, f.next);
   1029  1.1  mrg 
   1030  1.1  mrg                 fens = fens.statementSemantic(sc2);
   1031  1.1  mrg                 fens.blockExit(funcdecl, false);
   1032  1.1  mrg 
   1033  1.1  mrg                 funcdecl.flags &= ~FUNCFLAG.noEH;
   1034  1.1  mrg 
   1035  1.1  mrg                 sc2 = sc2.pop();
   1036  1.1  mrg 
   1037  1.1  mrg                 if (global.params.useOut == CHECKENABLE.off)
   1038  1.1  mrg                     fens = null;
   1039  1.1  mrg             }
   1040  1.1  mrg             if (funcdecl.fbody && funcdecl.fbody.isErrorStatement())
   1041  1.1  mrg             {
   1042  1.1  mrg             }
   1043  1.1  mrg             else
   1044  1.1  mrg             {
   1045  1.1  mrg                 auto a = new Statements();
   1046  1.1  mrg                 // Merge in initialization of 'out' parameters
   1047  1.1  mrg                 if (funcdecl.parameters)
   1048  1.1  mrg                 {
   1049  1.1  mrg                     for (size_t i = 0; i < funcdecl.parameters.dim; i++)
   1050  1.1  mrg                     {
   1051  1.1  mrg                         VarDeclaration v = (*funcdecl.parameters)[i];
   1052  1.1  mrg                         if (v.storage_class & STC.out_)
   1053  1.1  mrg                         {
   1054  1.1  mrg                             if (!v._init)
   1055  1.1  mrg                             {
   1056  1.1  mrg                                 v.error("Zero-length `out` parameters are not allowed.");
   1057  1.1  mrg                                 return;
   1058  1.1  mrg                             }
   1059  1.1  mrg                             ExpInitializer ie = v._init.isExpInitializer();
   1060  1.1  mrg                             assert(ie);
   1061  1.1  mrg                             if (auto iec = ie.exp.isConstructExp())
   1062  1.1  mrg                             {
   1063  1.1  mrg                                 // construction occurred in parameter processing
   1064  1.1  mrg                                 auto ec = new AssignExp(iec.loc, iec.e1, iec.e2);
   1065  1.1  mrg                                 ec.type = iec.type;
   1066  1.1  mrg                                 ie.exp = ec;
   1067  1.1  mrg                             }
   1068  1.1  mrg                             a.push(new ExpStatement(Loc.initial, ie.exp));
   1069  1.1  mrg                         }
   1070  1.1  mrg                     }
   1071  1.1  mrg                 }
   1072  1.1  mrg 
   1073  1.1  mrg                 if (_arguments)
   1074  1.1  mrg                 {
   1075  1.1  mrg                     /* Advance to elements[] member of TypeInfo_Tuple with:
   1076  1.1  mrg                      *  _arguments = v_arguments.elements;
   1077  1.1  mrg                      */
   1078  1.1  mrg                     Expression e = new VarExp(Loc.initial, funcdecl.v_arguments);
   1079  1.1  mrg                     e = new DotIdExp(Loc.initial, e, Id.elements);
   1080  1.1  mrg                     e = new ConstructExp(Loc.initial, _arguments, e);
   1081  1.1  mrg                     e = e.expressionSemantic(sc2);
   1082  1.1  mrg 
   1083  1.1  mrg                     _arguments._init = new ExpInitializer(Loc.initial, e);
   1084  1.1  mrg                     auto de = new DeclarationExp(Loc.initial, _arguments);
   1085  1.1  mrg                     a.push(new ExpStatement(Loc.initial, de));
   1086  1.1  mrg                 }
   1087  1.1  mrg 
   1088  1.1  mrg                 // Merge contracts together with body into one compound statement
   1089  1.1  mrg 
   1090  1.1  mrg                 if (freq || fpreinv)
   1091  1.1  mrg                 {
   1092  1.1  mrg                     if (!freq)
   1093  1.1  mrg                         freq = fpreinv;
   1094  1.1  mrg                     else if (fpreinv)
   1095  1.1  mrg                         freq = new CompoundStatement(Loc.initial, freq, fpreinv);
   1096  1.1  mrg 
   1097  1.1  mrg                     a.push(freq);
   1098  1.1  mrg                 }
   1099  1.1  mrg 
   1100  1.1  mrg                 if (funcdecl.fbody)
   1101  1.1  mrg                     a.push(funcdecl.fbody);
   1102  1.1  mrg 
   1103  1.1  mrg                 if (fens || fpostinv)
   1104  1.1  mrg                 {
   1105  1.1  mrg                     if (!fens)
   1106  1.1  mrg                         fens = fpostinv;
   1107  1.1  mrg                     else if (fpostinv)
   1108  1.1  mrg                         fens = new CompoundStatement(Loc.initial, fpostinv, fens);
   1109  1.1  mrg 
   1110  1.1  mrg                     auto ls = new LabelStatement(Loc.initial, Id.returnLabel, fens);
   1111  1.1  mrg                     funcdecl.returnLabel.statement = ls;
   1112  1.1  mrg                     a.push(funcdecl.returnLabel.statement);
   1113  1.1  mrg 
   1114  1.1  mrg                     if (f.next.ty != Tvoid && funcdecl.vresult)
   1115  1.1  mrg                     {
   1116  1.1  mrg                         // Create: return vresult;
   1117  1.1  mrg                         Expression e = new VarExp(Loc.initial, funcdecl.vresult);
   1118  1.1  mrg                         if (funcdecl.tintro)
   1119  1.1  mrg                         {
   1120  1.1  mrg                             e = e.implicitCastTo(sc, funcdecl.tintro.nextOf());
   1121  1.1  mrg                             e = e.expressionSemantic(sc);
   1122  1.1  mrg                         }
   1123  1.1  mrg                         auto s = new ReturnStatement(Loc.initial, e);
   1124  1.1  mrg                         a.push(s);
   1125  1.1  mrg                     }
   1126  1.1  mrg                 }
   1127  1.1  mrg                 if (addReturn0())
   1128  1.1  mrg                 {
   1129  1.1  mrg                     // Add a return 0; statement
   1130  1.1  mrg                     Statement s = new ReturnStatement(Loc.initial, IntegerExp.literal!0);
   1131  1.1  mrg                     a.push(s);
   1132  1.1  mrg                 }
   1133  1.1  mrg 
   1134  1.1  mrg                 Statement sbody = new CompoundStatement(Loc.initial, a);
   1135  1.1  mrg 
   1136  1.1  mrg                 /* Append destructor calls for parameters as finally blocks.
   1137  1.1  mrg                  */
   1138  1.1  mrg                 if (funcdecl.parameters)
   1139  1.1  mrg                 {
   1140  1.1  mrg                     // check if callee destroys arguments
   1141  1.1  mrg                     const bool paramsNeedDtor = target.isCalleeDestroyingArgs(f);
   1142  1.1  mrg 
   1143  1.1  mrg                     foreach (v; *funcdecl.parameters)
   1144  1.1  mrg                     {
   1145  1.1  mrg                         if (v.isReference() || (v.storage_class & STC.lazy_))
   1146  1.1  mrg                             continue;
   1147  1.1  mrg                         if (v.needsScopeDtor())
   1148  1.1  mrg                         {
   1149  1.1  mrg                             v.storage_class |= STC.nodtor;
   1150  1.1  mrg                             if (!paramsNeedDtor)
   1151  1.1  mrg                                 continue;
   1152  1.1  mrg 
   1153  1.1  mrg                             // same with ExpStatement.scopeCode()
   1154  1.1  mrg                             Statement s = new DtorExpStatement(Loc.initial, v.edtor, v);
   1155  1.1  mrg 
   1156  1.1  mrg                             s = s.statementSemantic(sc2);
   1157  1.1  mrg 
   1158  1.1  mrg                             immutable bool isnothrow = f.isnothrow && !(funcdecl.flags & FUNCFLAG.nothrowInprocess);
   1159  1.1  mrg                             const blockexit = s.blockExit(funcdecl, isnothrow);
   1160  1.1  mrg                             if (blockexit & BE.throw_)
   1161  1.1  mrg                             {
   1162  1.1  mrg                                 funcdecl.flags &= ~FUNCFLAG.noEH;
   1163  1.1  mrg                                 if (isnothrow)
   1164  1.1  mrg                                     error(funcdecl.loc, "%s `%s` may throw but is marked as `nothrow`", funcdecl.kind(), funcdecl.toPrettyChars());
   1165  1.1  mrg                                 else if (funcdecl.flags & FUNCFLAG.nothrowInprocess)
   1166  1.1  mrg                                     f.isnothrow = false;
   1167  1.1  mrg                             }
   1168  1.1  mrg 
   1169  1.1  mrg                             if (sbody.blockExit(funcdecl, f.isnothrow) == BE.fallthru)
   1170  1.1  mrg                                 sbody = new CompoundStatement(Loc.initial, sbody, s);
   1171  1.1  mrg                             else
   1172  1.1  mrg                                 sbody = new TryFinallyStatement(Loc.initial, sbody, s);
   1173  1.1  mrg                         }
   1174  1.1  mrg                     }
   1175  1.1  mrg                 }
   1176  1.1  mrg                 // from this point on all possible 'throwers' are checked
   1177  1.1  mrg                 funcdecl.flags &= ~FUNCFLAG.nothrowInprocess;
   1178  1.1  mrg 
   1179  1.1  mrg                 if (funcdecl.isSynchronized())
   1180  1.1  mrg                 {
   1181  1.1  mrg                     /* Wrap the entire function body in a synchronized statement
   1182  1.1  mrg                      */
   1183  1.1  mrg                     ClassDeclaration cd = funcdecl.toParentDecl().isClassDeclaration();
   1184  1.1  mrg                     if (cd)
   1185  1.1  mrg                     {
   1186  1.1  mrg                         if (target.libraryObjectMonitors(funcdecl, sbody))
   1187  1.1  mrg                         {
   1188  1.1  mrg                             Expression vsync;
   1189  1.1  mrg                             if (funcdecl.isStatic())
   1190  1.1  mrg                             {
   1191  1.1  mrg                                 // The monitor is in the ClassInfo
   1192  1.1  mrg                                 vsync = new DotIdExp(funcdecl.loc, symbolToExp(cd, funcdecl.loc, sc2, false), Id.classinfo);
   1193  1.1  mrg                             }
   1194  1.1  mrg                             else
   1195  1.1  mrg                             {
   1196  1.1  mrg                                 // 'this' is the monitor
   1197  1.1  mrg                                 vsync = new VarExp(funcdecl.loc, funcdecl.vthis);
   1198  1.1  mrg                                 if (funcdecl.hasDualContext())
   1199  1.1  mrg                                 {
   1200  1.1  mrg                                     vsync = new PtrExp(funcdecl.loc, vsync);
   1201  1.1  mrg                                     vsync = new IndexExp(funcdecl.loc, vsync, IntegerExp.literal!0);
   1202  1.1  mrg                                 }
   1203  1.1  mrg                             }
   1204  1.1  mrg                             sbody = new PeelStatement(sbody); // don't redo semantic()
   1205  1.1  mrg                             sbody = new SynchronizedStatement(funcdecl.loc, vsync, sbody);
   1206  1.1  mrg                             sbody = sbody.statementSemantic(sc2);
   1207  1.1  mrg                         }
   1208  1.1  mrg                     }
   1209  1.1  mrg                     else
   1210  1.1  mrg                     {
   1211  1.1  mrg                         funcdecl.error("synchronized function `%s` must be a member of a class", funcdecl.toChars());
   1212  1.1  mrg                     }
   1213  1.1  mrg                 }
   1214  1.1  mrg 
   1215  1.1  mrg                 // If declaration has no body, don't set sbody to prevent incorrect codegen.
   1216  1.1  mrg                 if (funcdecl.fbody || funcdecl.allowsContractWithoutBody())
   1217  1.1  mrg                     funcdecl.fbody = sbody;
   1218  1.1  mrg             }
   1219  1.1  mrg 
   1220  1.1  mrg             // Check for undefined labels
   1221  1.1  mrg             if (funcdecl.labtab)
   1222  1.1  mrg                 foreach (keyValue; funcdecl.labtab.tab.asRange)
   1223  1.1  mrg                 {
   1224  1.1  mrg                     //printf("  KV: %s = %s\n", keyValue.key.toChars(), keyValue.value.toChars());
   1225  1.1  mrg                     LabelDsymbol label = cast(LabelDsymbol)keyValue.value;
   1226  1.1  mrg                     if (!label.statement && (!label.deleted || label.iasm))
   1227  1.1  mrg                     {
   1228  1.1  mrg                         funcdecl.error(label.loc, "label `%s` is undefined", label.toChars());
   1229  1.1  mrg                     }
   1230  1.1  mrg                 }
   1231  1.1  mrg 
   1232  1.1  mrg             // Fix up forward-referenced gotos
   1233  1.1  mrg             if (funcdecl.gotos && !funcdecl.isCsymbol())
   1234  1.1  mrg             {
   1235  1.1  mrg                 for (size_t i = 0; i < funcdecl.gotos.dim; ++i)
   1236  1.1  mrg                 {
   1237  1.1  mrg                     (*funcdecl.gotos)[i].checkLabel();
   1238  1.1  mrg                 }
   1239  1.1  mrg             }
   1240  1.1  mrg 
   1241  1.1  mrg             if (funcdecl.isNaked() && (funcdecl.fensures || funcdecl.frequires))
   1242  1.1  mrg                 funcdecl.error("naked assembly functions with contracts are not supported");
   1243  1.1  mrg 
   1244  1.1  mrg             sc2.ctorflow.callSuper = CSX.none;
   1245  1.1  mrg             sc2.pop();
   1246  1.1  mrg         }
   1247  1.1  mrg 
   1248  1.1  mrg         if (funcdecl.checkClosure())
   1249  1.1  mrg         {
   1250  1.1  mrg             // We should be setting errors here instead of relying on the global error count.
   1251  1.1  mrg             //errors = true;
   1252  1.1  mrg         }
   1253  1.1  mrg 
   1254  1.1  mrg         /* If function survived being marked as impure, then it is pure
   1255  1.1  mrg          */
   1256  1.1  mrg         if (funcdecl.flags & FUNCFLAG.purityInprocess)
   1257  1.1  mrg         {
   1258  1.1  mrg             funcdecl.flags &= ~FUNCFLAG.purityInprocess;
   1259  1.1  mrg             if (funcdecl.type == f)
   1260  1.1  mrg                 f = cast(TypeFunction)f.copy();
   1261  1.1  mrg             f.purity = PURE.fwdref;
   1262  1.1  mrg         }
   1263  1.1  mrg 
   1264  1.1  mrg         if (funcdecl.flags & FUNCFLAG.safetyInprocess)
   1265  1.1  mrg         {
   1266  1.1  mrg             funcdecl.flags &= ~FUNCFLAG.safetyInprocess;
   1267  1.1  mrg             if (funcdecl.type == f)
   1268  1.1  mrg                 f = cast(TypeFunction)f.copy();
   1269  1.1  mrg             f.trust = TRUST.safe;
   1270  1.1  mrg         }
   1271  1.1  mrg 
   1272  1.1  mrg         if (funcdecl.flags & FUNCFLAG.nogcInprocess)
   1273  1.1  mrg         {
   1274  1.1  mrg             funcdecl.flags &= ~FUNCFLAG.nogcInprocess;
   1275  1.1  mrg             if (funcdecl.type == f)
   1276  1.1  mrg                 f = cast(TypeFunction)f.copy();
   1277  1.1  mrg             f.isnogc = true;
   1278  1.1  mrg         }
   1279  1.1  mrg 
   1280  1.1  mrg         if (funcdecl.flags & FUNCFLAG.returnInprocess)
   1281  1.1  mrg         {
   1282  1.1  mrg             funcdecl.flags &= ~FUNCFLAG.returnInprocess;
   1283  1.1  mrg             if (funcdecl.storage_class & STC.return_)
   1284  1.1  mrg             {
   1285  1.1  mrg                 if (funcdecl.type == f)
   1286  1.1  mrg                     f = cast(TypeFunction)f.copy();
   1287  1.1  mrg                 f.isreturn = true;
   1288  1.1  mrg                 f.isreturnscope = cast(bool) (funcdecl.storage_class & STC.returnScope);
   1289  1.1  mrg                 if (funcdecl.storage_class & STC.returninferred)
   1290  1.1  mrg                     f.isreturninferred = true;
   1291  1.1  mrg             }
   1292  1.1  mrg         }
   1293  1.1  mrg 
   1294  1.1  mrg         funcdecl.flags &= ~FUNCFLAG.inferScope;
   1295  1.1  mrg 
   1296  1.1  mrg         // Eliminate maybescope's
   1297  1.1  mrg         {
   1298  1.1  mrg             // Create and fill array[] with maybe candidates from the `this` and the parameters
   1299  1.1  mrg             VarDeclaration[10] tmp = void;
   1300  1.1  mrg             size_t dim = (funcdecl.vthis !is null) + (funcdecl.parameters ? funcdecl.parameters.dim : 0);
   1301  1.1  mrg 
   1302  1.1  mrg             import dmd.common.string : SmallBuffer;
   1303  1.1  mrg             auto sb = SmallBuffer!VarDeclaration(dim, tmp[]);
   1304  1.1  mrg             VarDeclaration[] array = sb[];
   1305  1.1  mrg 
   1306  1.1  mrg             size_t n = 0;
   1307  1.1  mrg             if (funcdecl.vthis)
   1308  1.1  mrg                 array[n++] = funcdecl.vthis;
   1309  1.1  mrg             if (funcdecl.parameters)
   1310  1.1  mrg             {
   1311  1.1  mrg                 foreach (v; *funcdecl.parameters)
   1312  1.1  mrg                 {
   1313  1.1  mrg                     array[n++] = v;
   1314  1.1  mrg                 }
   1315  1.1  mrg             }
   1316  1.1  mrg             eliminateMaybeScopes(array[0 .. n]);
   1317  1.1  mrg         }
   1318  1.1  mrg 
   1319  1.1  mrg         // Infer STC.scope_
   1320  1.1  mrg         if (funcdecl.parameters && !funcdecl.errors)
   1321  1.1  mrg         {
   1322  1.1  mrg             assert(f.parameterList.length == funcdecl.parameters.dim);
   1323  1.1  mrg             foreach (u, p; f.parameterList)
   1324  1.1  mrg             {
   1325  1.1  mrg                 auto v = (*funcdecl.parameters)[u];
   1326  1.1  mrg                 if (v.storage_class & STC.maybescope)
   1327  1.1  mrg                 {
   1328  1.1  mrg                     //printf("Inferring scope for %s\n", v.toChars());
   1329  1.1  mrg                     notMaybeScope(v);
   1330  1.1  mrg                     v.storage_class |= STC.scope_ | STC.scopeinferred;
   1331  1.1  mrg                     p.storageClass |= STC.scope_ | STC.scopeinferred;
   1332  1.1  mrg                     assert(!(p.storageClass & STC.maybescope));
   1333  1.1  mrg                 }
   1334  1.1  mrg             }
   1335  1.1  mrg         }
   1336  1.1  mrg 
   1337  1.1  mrg         if (funcdecl.vthis && funcdecl.vthis.storage_class & STC.maybescope)
   1338  1.1  mrg         {
   1339  1.1  mrg             notMaybeScope(funcdecl.vthis);
   1340  1.1  mrg             funcdecl.vthis.storage_class |= STC.scope_ | STC.scopeinferred;
   1341  1.1  mrg             f.isScopeQual = true;
   1342  1.1  mrg             f.isscopeinferred = true;
   1343  1.1  mrg         }
   1344  1.1  mrg 
   1345  1.1  mrg         // reset deco to apply inference result to mangled name
   1346  1.1  mrg         if (f != funcdecl.type)
   1347  1.1  mrg             f.deco = null;
   1348  1.1  mrg 
   1349  1.1  mrg         // Do semantic type AFTER pure/nothrow inference.
   1350  1.1  mrg         if (!f.deco && funcdecl.ident != Id.xopEquals && funcdecl.ident != Id.xopCmp)
   1351  1.1  mrg         {
   1352  1.1  mrg             sc = sc.push();
   1353  1.1  mrg             if (funcdecl.isCtorDeclaration()) // https://issues.dlang.org/show_bug.cgi?id=#15665
   1354  1.1  mrg                 f.isctor = true;
   1355  1.1  mrg             sc.stc = 0;
   1356  1.1  mrg             sc.linkage = funcdecl._linkage; // https://issues.dlang.org/show_bug.cgi?id=8496
   1357  1.1  mrg             funcdecl.type = f.typeSemantic(funcdecl.loc, sc);
   1358  1.1  mrg             sc = sc.pop();
   1359  1.1  mrg         }
   1360  1.1  mrg 
   1361  1.1  mrg         // Do live analysis
   1362  1.1  mrg         if (global.params.useDIP1021 && funcdecl.fbody && funcdecl.type.ty != Terror &&
   1363  1.1  mrg             funcdecl.type.isTypeFunction().islive)
   1364  1.1  mrg         {
   1365  1.1  mrg             oblive(funcdecl);
   1366  1.1  mrg         }
   1367  1.1  mrg 
   1368  1.1  mrg         /* If this function had instantiated with gagging, error reproduction will be
   1369  1.1  mrg          * done by TemplateInstance::semantic.
   1370  1.1  mrg          * Otherwise, error gagging should be temporarily ungagged by functionSemantic3.
   1371  1.1  mrg          */
   1372  1.1  mrg         funcdecl.semanticRun = PASS.semantic3done;
   1373  1.1  mrg         if ((global.errors != oldErrors) || (funcdecl.fbody && funcdecl.fbody.isErrorStatement()))
   1374  1.1  mrg             funcdecl.flags |= FUNCFLAG.semantic3Errors;
   1375  1.1  mrg         else
   1376  1.1  mrg             funcdecl.flags &= ~FUNCFLAG.semantic3Errors;
   1377  1.1  mrg         if (funcdecl.type.ty == Terror)
   1378  1.1  mrg             funcdecl.errors = true;
   1379  1.1  mrg         //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent.toChars(), toChars(), sc, loc.toChars());
   1380  1.1  mrg         //fflush(stdout);
   1381  1.1  mrg     }
   1382  1.1  mrg 
   1383  1.1  mrg     override void visit(CtorDeclaration ctor)
   1384  1.1  mrg     {
   1385  1.1  mrg         //printf("CtorDeclaration()\n%s\n", ctor.fbody.toChars());
   1386  1.1  mrg         if (ctor.semanticRun >= PASS.semantic3)
   1387  1.1  mrg             return;
   1388  1.1  mrg 
   1389  1.1  mrg         /* If any of the fields of the aggregate have a destructor, add
   1390  1.1  mrg          *   scope (failure) { this.fieldDtor(); }
   1391  1.1  mrg          * as the first statement of the constructor (unless the constructor
   1392  1.1  mrg          * doesn't define a body - @disable, extern)
   1393  1.1  mrg          *.It is not necessary to add it after
   1394  1.1  mrg          * each initialization of a field, because destruction of .init constructed
   1395  1.1  mrg          * structs should be benign.
   1396  1.1  mrg          * https://issues.dlang.org/show_bug.cgi?id=14246
   1397  1.1  mrg          */
   1398  1.1  mrg         AggregateDeclaration ad = ctor.isMemberDecl();
   1399  1.1  mrg         if (!ctor.fbody || !ad || !ad.fieldDtor || !global.params.dtorFields || global.params.betterC || ctor.type.toTypeFunction.isnothrow)
   1400  1.1  mrg             return visit(cast(FuncDeclaration)ctor);
   1401  1.1  mrg 
   1402  1.1  mrg         /* Generate:
   1403  1.1  mrg          *   this.fieldDtor()
   1404  1.1  mrg          */
   1405  1.1  mrg         Expression e = new ThisExp(ctor.loc);
   1406  1.1  mrg         e.type = ad.type.mutableOf();
   1407  1.1  mrg         e = new DotVarExp(ctor.loc, e, ad.fieldDtor, false);
   1408  1.1  mrg         auto ce = new CallExp(ctor.loc, e);
   1409  1.1  mrg         auto sexp = new ExpStatement(ctor.loc, ce);
   1410  1.1  mrg         auto ss = new ScopeStatement(ctor.loc, sexp, ctor.loc);
   1411  1.1  mrg 
   1412  1.1  mrg         // @@@DEPRECATED_2.106@@@
   1413  1.1  mrg         // Allow negligible attribute violations to allow for a smooth
   1414  1.1  mrg         // transition. Remove this after the usual deprecation period
   1415  1.1  mrg         // after 2.106.
   1416  1.1  mrg         if (global.params.dtorFields == FeatureState.default_)
   1417  1.1  mrg         {
   1418  1.1  mrg             auto ctf = cast(TypeFunction) ctor.type;
   1419  1.1  mrg             auto dtf = cast(TypeFunction) ad.fieldDtor.type;
   1420  1.1  mrg 
   1421  1.1  mrg             const ngErr = ctf.isnogc && !dtf.isnogc;
   1422  1.1  mrg             const puErr = ctf.purity && !dtf.purity;
   1423  1.1  mrg             const saErr = ctf.trust == TRUST.safe && dtf.trust <= TRUST.system;
   1424  1.1  mrg 
   1425  1.1  mrg             if (ngErr || puErr || saErr)
   1426  1.1  mrg             {
   1427  1.1  mrg                 // storage_class is apparently not set for dtor & ctor
   1428  1.1  mrg                 OutBuffer ob;
   1429  1.1  mrg                 stcToBuffer(&ob,
   1430  1.1  mrg                     (ngErr ? STC.nogc : 0) |
   1431  1.1  mrg                     (puErr ? STC.pure_ : 0) |
   1432  1.1  mrg                     (saErr ? STC.system : 0)
   1433  1.1  mrg                 );
   1434  1.1  mrg                 ctor.loc.deprecation("`%s` has stricter attributes than its destructor (`%s`)", ctor.toPrettyChars(), ob.peekChars());
   1435  1.1  mrg                 ctor.loc.deprecationSupplemental("The destructor will be called if an exception is thrown");
   1436  1.1  mrg                 ctor.loc.deprecationSupplemental("Either make the constructor `nothrow` or adjust the field destructors");
   1437  1.1  mrg 
   1438  1.1  mrg                 ce.ignoreAttributes = true;
   1439  1.1  mrg             }
   1440  1.1  mrg         }
   1441  1.1  mrg 
   1442  1.1  mrg         version (all)
   1443  1.1  mrg         {
   1444  1.1  mrg             /* Generate:
   1445  1.1  mrg              *   try { ctor.fbody; }
   1446  1.1  mrg              *   catch (Exception __o)
   1447  1.1  mrg              *   { this.fieldDtor(); throw __o; }
   1448  1.1  mrg              * This differs from the alternate scope(failure) version in that an Exception
   1449  1.1  mrg              * is caught rather than a Throwable. This enables the optimization whereby
   1450  1.1  mrg              * the try-catch can be removed if ctor.fbody is nothrow. (nothrow only
   1451  1.1  mrg              * applies to Exception.)
   1452  1.1  mrg              */
   1453  1.1  mrg             Identifier id = Identifier.generateId("__o");
   1454  1.1  mrg             auto ts = new ThrowStatement(ctor.loc, new IdentifierExp(ctor.loc, id));
   1455  1.1  mrg             auto handler = new CompoundStatement(ctor.loc, ss, ts);
   1456  1.1  mrg 
   1457  1.1  mrg             auto catches = new Catches();
   1458  1.1  mrg             auto ctch = new Catch(ctor.loc, getException(), id, handler);
   1459  1.1  mrg             catches.push(ctch);
   1460  1.1  mrg 
   1461  1.1  mrg             ctor.fbody = new TryCatchStatement(ctor.loc, ctor.fbody, catches);
   1462  1.1  mrg         }
   1463  1.1  mrg         else
   1464  1.1  mrg         {
   1465  1.1  mrg             /* Generate:
   1466  1.1  mrg              *   scope (failure) { this.fieldDtor(); }
   1467  1.1  mrg              * Hopefully we can use this version someday when scope(failure) catches
   1468  1.1  mrg              * Exception instead of Throwable.
   1469  1.1  mrg              */
   1470  1.1  mrg             auto s = new ScopeGuardStatement(ctor.loc, TOK.onScopeFailure, ss);
   1471  1.1  mrg             ctor.fbody = new CompoundStatement(ctor.loc, s, ctor.fbody);
   1472  1.1  mrg         }
   1473  1.1  mrg         visit(cast(FuncDeclaration)ctor);
   1474  1.1  mrg     }
   1475  1.1  mrg 
   1476  1.1  mrg 
   1477  1.1  mrg     override void visit(Nspace ns)
   1478  1.1  mrg     {
   1479  1.1  mrg         if (ns.semanticRun >= PASS.semantic3)
   1480  1.1  mrg             return;
   1481  1.1  mrg         ns.semanticRun = PASS.semantic3;
   1482  1.1  mrg         static if (LOG)
   1483  1.1  mrg         {
   1484  1.1  mrg             printf("Nspace::semantic3('%s')\n", ns.toChars());
   1485  1.1  mrg         }
   1486  1.1  mrg         if (!ns.members)
   1487  1.1  mrg             return;
   1488  1.1  mrg 
   1489  1.1  mrg         sc = sc.push(ns);
   1490  1.1  mrg         sc.linkage = LINK.cpp;
   1491  1.1  mrg         foreach (s; *ns.members)
   1492  1.1  mrg         {
   1493  1.1  mrg             s.semantic3(sc);
   1494  1.1  mrg         }
   1495  1.1  mrg         sc.pop();
   1496  1.1  mrg     }
   1497  1.1  mrg 
   1498  1.1  mrg     override void visit(AttribDeclaration ad)
   1499  1.1  mrg     {
   1500  1.1  mrg         Dsymbols* d = ad.include(sc);
   1501  1.1  mrg         if (!d)
   1502  1.1  mrg             return;
   1503  1.1  mrg 
   1504  1.1  mrg         Scope* sc2 = ad.newScope(sc);
   1505  1.1  mrg         for (size_t i = 0; i < d.dim; i++)
   1506  1.1  mrg         {
   1507  1.1  mrg             Dsymbol s = (*d)[i];
   1508  1.1  mrg             s.semantic3(sc2);
   1509  1.1  mrg         }
   1510  1.1  mrg         if (sc2 != sc)
   1511  1.1  mrg             sc2.pop();
   1512  1.1  mrg     }
   1513  1.1  mrg 
   1514  1.1  mrg     override void visit(AggregateDeclaration ad)
   1515  1.1  mrg     {
   1516  1.1  mrg         //printf("AggregateDeclaration::semantic3(sc=%p, %s) type = %s, errors = %d\n", sc, toChars(), type.toChars(), errors);
   1517  1.1  mrg         if (!ad.members)
   1518  1.1  mrg             return;
   1519  1.1  mrg 
   1520  1.1  mrg         StructDeclaration sd = ad.isStructDeclaration();
   1521  1.1  mrg         if (!sc) // from runDeferredSemantic3 for TypeInfo generation
   1522  1.1  mrg         {
   1523  1.1  mrg             assert(sd);
   1524  1.1  mrg             sd.semanticTypeInfoMembers();
   1525  1.1  mrg             return;
   1526  1.1  mrg         }
   1527  1.1  mrg 
   1528  1.1  mrg         auto sc2 = ad.newScope(sc);
   1529  1.1  mrg 
   1530  1.1  mrg         for (size_t i = 0; i < ad.members.dim; i++)
   1531  1.1  mrg         {
   1532  1.1  mrg             Dsymbol s = (*ad.members)[i];
   1533  1.1  mrg             s.semantic3(sc2);
   1534  1.1  mrg         }
   1535  1.1  mrg 
   1536  1.1  mrg         sc2.pop();
   1537  1.1  mrg 
   1538  1.1  mrg         // don't do it for unused deprecated types
   1539  1.1  mrg         // or error ypes
   1540  1.1  mrg         if (!ad.getRTInfo && Type.rtinfo && (!ad.isDeprecated() || global.params.useDeprecated != DiagnosticReporting.error) && (ad.type && ad.type.ty != Terror))
   1541  1.1  mrg         {
   1542  1.1  mrg             // Evaluate: RTinfo!type
   1543  1.1  mrg             auto tiargs = new Objects();
   1544  1.1  mrg             tiargs.push(ad.type);
   1545  1.1  mrg             auto ti = new TemplateInstance(ad.loc, Type.rtinfo, tiargs);
   1546  1.1  mrg 
   1547  1.1  mrg             Scope* sc3 = ti.tempdecl._scope.startCTFE();
   1548  1.1  mrg             sc3.tinst = sc.tinst;
   1549  1.1  mrg             sc3.minst = sc.minst;
   1550  1.1  mrg             if (ad.isDeprecated())
   1551  1.1  mrg                 sc3.stc |= STC.deprecated_;
   1552  1.1  mrg 
   1553  1.1  mrg             ti.dsymbolSemantic(sc3);
   1554  1.1  mrg             ti.semantic2(sc3);
   1555  1.1  mrg             ti.semantic3(sc3);
   1556  1.1  mrg             auto e = symbolToExp(ti.toAlias(), Loc.initial, sc3, false);
   1557  1.1  mrg 
   1558  1.1  mrg             sc3.endCTFE();
   1559  1.1  mrg 
   1560  1.1  mrg             e = e.ctfeInterpret();
   1561  1.1  mrg             ad.getRTInfo = e;
   1562  1.1  mrg         }
   1563  1.1  mrg         if (sd)
   1564  1.1  mrg             sd.semanticTypeInfoMembers();
   1565  1.1  mrg         ad.semanticRun = PASS.semantic3done;
   1566  1.1  mrg     }
   1567  1.1  mrg }
   1568  1.1  mrg 
   1569  1.1  mrg private struct FuncDeclSem3
   1570  1.1  mrg {
   1571  1.1  mrg     // The FuncDeclaration subject to Semantic analysis
   1572  1.1  mrg     FuncDeclaration funcdecl;
   1573  1.1  mrg 
   1574  1.1  mrg     // Scope of analysis
   1575  1.1  mrg     Scope* sc;
   1576  1.1  mrg     this(FuncDeclaration fd,Scope* s)
   1577  1.1  mrg     {
   1578  1.1  mrg         funcdecl = fd;
   1579  1.1  mrg         sc = s;
   1580  1.1  mrg     }
   1581  1.1  mrg 
   1582  1.1  mrg     /* Checks that the overriden functions (if any) have in contracts if
   1583  1.1  mrg      * funcdecl has an in contract.
   1584  1.1  mrg      */
   1585  1.1  mrg     void checkInContractOverrides()
   1586  1.1  mrg     {
   1587  1.1  mrg         if (funcdecl.frequires)
   1588  1.1  mrg         {
   1589  1.1  mrg             for (size_t i = 0; i < funcdecl.foverrides.dim; i++)
   1590  1.1  mrg             {
   1591  1.1  mrg                 FuncDeclaration fdv = funcdecl.foverrides[i];
   1592  1.1  mrg                 if (fdv.fbody && !fdv.frequires)
   1593  1.1  mrg                 {
   1594  1.1  mrg                     funcdecl.error("cannot have an in contract when overridden function `%s` does not have an in contract", fdv.toPrettyChars());
   1595  1.1  mrg                     break;
   1596  1.1  mrg                 }
   1597  1.1  mrg             }
   1598  1.1  mrg         }
   1599  1.1  mrg     }
   1600  1.1  mrg }
   1601  1.1  mrg 
   1602  1.1  mrg extern (C++) void semanticTypeInfoMembers(StructDeclaration sd)
   1603  1.1  mrg {
   1604  1.1  mrg     if (sd.xeq &&
   1605  1.1  mrg         sd.xeq._scope &&
   1606  1.1  mrg         sd.xeq.semanticRun < PASS.semantic3done)
   1607  1.1  mrg     {
   1608  1.1  mrg         uint errors = global.startGagging();
   1609  1.1  mrg         sd.xeq.semantic3(sd.xeq._scope);
   1610  1.1  mrg         if (global.endGagging(errors))
   1611  1.1  mrg             sd.xeq = sd.xerreq;
   1612  1.1  mrg     }
   1613  1.1  mrg 
   1614  1.1  mrg     if (sd.xcmp &&
   1615  1.1  mrg         sd.xcmp._scope &&
   1616  1.1  mrg         sd.xcmp.semanticRun < PASS.semantic3done)
   1617  1.1  mrg     {
   1618  1.1  mrg         uint errors = global.startGagging();
   1619  1.1  mrg         sd.xcmp.semantic3(sd.xcmp._scope);
   1620  1.1  mrg         if (global.endGagging(errors))
   1621  1.1  mrg             sd.xcmp = sd.xerrcmp;
   1622  1.1  mrg     }
   1623  1.1  mrg 
   1624  1.1  mrg     FuncDeclaration ftostr = search_toString(sd);
   1625  1.1  mrg     if (ftostr &&
   1626  1.1  mrg         ftostr._scope &&
   1627  1.1  mrg         ftostr.semanticRun < PASS.semantic3done)
   1628  1.1  mrg     {
   1629  1.1  mrg         ftostr.semantic3(ftostr._scope);
   1630  1.1  mrg     }
   1631  1.1  mrg 
   1632  1.1  mrg     if (sd.xhash &&
   1633  1.1  mrg         sd.xhash._scope &&
   1634  1.1  mrg         sd.xhash.semanticRun < PASS.semantic3done)
   1635  1.1  mrg     {
   1636  1.1  mrg         sd.xhash.semantic3(sd.xhash._scope);
   1637  1.1  mrg     }
   1638  1.1  mrg 
   1639  1.1  mrg     if (sd.postblit &&
   1640  1.1  mrg         sd.postblit._scope &&
   1641  1.1  mrg         sd.postblit.semanticRun < PASS.semantic3done)
   1642  1.1  mrg     {
   1643  1.1  mrg         sd.postblit.semantic3(sd.postblit._scope);
   1644  1.1  mrg     }
   1645  1.1  mrg 
   1646  1.1  mrg     if (sd.dtor &&
   1647  1.1  mrg         sd.dtor._scope &&
   1648  1.1  mrg         sd.dtor.semanticRun < PASS.semantic3done)
   1649  1.1  mrg     {
   1650  1.1  mrg         sd.dtor.semantic3(sd.dtor._scope);
   1651  1.1  mrg     }
   1652  1.1  mrg }
   1653