1
2/* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
4 * written by Walter Bright
5 * http://www.digitalmars.com
6 * Distributed under the Boost Software License, Version 1.0.
7 * http://www.boost.org/LICENSE_1_0.txt
8 */
9
10#include "root/dsystem.h"
11#include "root/rmem.h"
12#include "root/checkedint.h"
13
14#include "errors.h"
15#include "statement.h"
16#include "attrib.h"
17#include "expression.h"
18#include "cond.h"
19#include "init.h"
20#include "staticassert.h"
21#include "module.h"
22#include "scope.h"
23#include "declaration.h"
24#include "aggregate.h"
25#include "id.h"
26#include "enum.h"
27#include "template.h"
28#include "import.h"
29#include "target.h"
30#include "visitor.h"
31
32StorageClass mergeFuncAttrs(StorageClass s1, FuncDeclaration *f);
33bool checkReturnEscapeRef(Scope *sc, Expression *e, bool gag);
34bool checkThrowEscape(Scope *sc, Expression *e, bool gag);
35LabelStatement *checkLabeledLoop(Scope *sc, Statement *statement);
36Identifier *fixupLabelName(Scope *sc, Identifier *ident);
37FuncDeclaration *isFuncAddress(Expression *e, bool *hasOverloads = NULL);
38VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e);
39Expression *checkAssignmentAsCondition(Expression *e);
40TypeIdentifier *getThrowable();
41
42Expression *semantic(Expression *e, Scope *sc);
43Statement *semantic(Statement *s, Scope *sc);
44void semantic(Catch *c, Scope *sc);
45Statement *semanticNoScope(Statement *s, Scope *sc);
46Statement *semanticScope(Statement *s, Scope *sc, Statement *sbreak, Statement *scontinue);
47int blockExit(Statement *s, FuncDeclaration *func, bool mustNotThrow);
48
49class StatementSemanticVisitor : public Visitor
50{
51public:
52    Statement *result;
53    Scope *sc;
54
55    StatementSemanticVisitor(Scope *sc)
56    {
57        this->result = NULL;
58        this->sc = sc;
59    }
60
61private:
62    void setError()
63    {
64        result = new ErrorStatement();
65    }
66
67public:
68    void visit(Statement *s)
69    {
70        result = s;
71    }
72
73    void visit(ErrorStatement *s)
74    {
75        result = s;
76    }
77
78    void visit(PeelStatement *s)
79    {
80        /* "peel" off this wrapper, and don't run semantic()
81         * on the result.
82         */
83        result = s->s;
84    }
85
86    void visit(ExpStatement *s)
87    {
88        if (s->exp)
89        {
90            //printf("ExpStatement::semantic() %s\n", s->exp->toChars());
91
92            // Allow CommaExp in ExpStatement because return isn't used
93            if (s->exp->op == TOKcomma)
94                ((CommaExp *)s->exp)->allowCommaExp = true;
95
96            s->exp = semantic(s->exp, sc);
97            s->exp = resolveProperties(sc, s->exp);
98            s->exp = s->exp->addDtorHook(sc);
99            if (checkNonAssignmentArrayOp(s->exp))
100                s->exp = new ErrorExp();
101            if (FuncDeclaration *f = isFuncAddress(s->exp))
102            {
103                if (f->checkForwardRef(s->exp->loc))
104                    s->exp = new ErrorExp();
105            }
106            if (discardValue(s->exp))
107                s->exp = new ErrorExp();
108
109            s->exp = s->exp->optimize(WANTvalue);
110            s->exp = checkGC(sc, s->exp);
111            if (s->exp->op == TOKerror)
112                return setError();
113        }
114        result = s;
115    }
116
117    void visit(CompileStatement *cs)
118    {
119        //printf("CompileStatement::semantic() %s\n", cs->exp->toChars());
120        Statements *a = cs->flatten(sc);
121        if (!a)
122            return;
123        Statement *s = new CompoundStatement(cs->loc, a);
124        result = semantic(s, sc);
125    }
126
127    void visit(CompoundStatement *cs)
128    {
129        //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", cs, sc);
130        for (size_t i = 0; i < cs->statements->dim; )
131        {
132            Statement *s = (*cs->statements)[i];
133            if (s)
134            {
135                Statements *flt = s->flatten(sc);
136                if (flt)
137                {
138                    cs->statements->remove(i);
139                    cs->statements->insert(i, flt);
140                    continue;
141                }
142                s = semantic(s, sc);
143                (*cs->statements)[i] = s;
144                if (s)
145                {
146                    Statement *sentry;
147                    Statement *sexception;
148                    Statement *sfinally;
149
150                    (*cs->statements)[i] = s->scopeCode(sc, &sentry, &sexception, &sfinally);
151                    if (sentry)
152                    {
153                        sentry = semantic(sentry, sc);
154                        cs->statements->insert(i, sentry);
155                        i++;
156                    }
157                    if (sexception)
158                        sexception = semantic(sexception, sc);
159                    if (sexception)
160                    {
161                        if (i + 1 == cs->statements->dim && !sfinally)
162                        {
163                        }
164                        else
165                        {
166                            /* Rewrite:
167                             *      s; s1; s2;
168                             * As:
169                             *      s;
170                             *      try { s1; s2; }
171                             *      catch (Throwable __o)
172                             *      { sexception; throw __o; }
173                             */
174                            Statements *a = new Statements();
175                            for (size_t j = i + 1; j < cs->statements->dim; j++)
176                            {
177                                a->push((*cs->statements)[j]);
178                            }
179                            Statement *body = new CompoundStatement(Loc(), a);
180                            body = new ScopeStatement(Loc(), body, Loc());
181
182                            Identifier *id = Identifier::generateId("__o");
183
184                            Statement *handler = new PeelStatement(sexception);
185                            if (blockExit(sexception, sc->func, false) & BEfallthru)
186                            {
187                                ThrowStatement *ts = new ThrowStatement(Loc(), new IdentifierExp(Loc(), id));
188                                ts->internalThrow = true;
189                                handler = new CompoundStatement(Loc(), handler, ts);
190                            }
191
192                            Catches *catches = new Catches();
193                            Catch *ctch = new Catch(Loc(), getThrowable(), id, handler);
194                            ctch->internalCatch = true;
195                            catches->push(ctch);
196
197                            s = new TryCatchStatement(Loc(), body, catches);
198                            if (sfinally)
199                                s = new TryFinallyStatement(Loc(), s, sfinally);
200                            s = semantic(s, sc);
201
202                            cs->statements->setDim(i + 1);
203                            cs->statements->push(s);
204                            break;
205                        }
206                    }
207                    else if (sfinally)
208                    {
209                        if (0 && i + 1 == cs->statements->dim)
210                        {
211                            cs->statements->push(sfinally);
212                        }
213                        else
214                        {
215                            /* Rewrite:
216                             *      s; s1; s2;
217                             * As:
218                             *      s; try { s1; s2; } finally { sfinally; }
219                             */
220                            Statements *a = new Statements();
221                            for (size_t j = i + 1; j < cs->statements->dim; j++)
222                            {
223                                a->push((*cs->statements)[j]);
224                            }
225                            Statement *body = new CompoundStatement(Loc(), a);
226                            s = new TryFinallyStatement(Loc(), body, sfinally);
227                            s = semantic(s, sc);
228                            cs->statements->setDim(i + 1);
229                            cs->statements->push(s);
230                            break;
231                        }
232                    }
233                }
234                else
235                {
236                    /* Remove NULL statements from the list.
237                    */
238                    cs->statements->remove(i);
239                    continue;
240                }
241            }
242            i++;
243        }
244        for (size_t i = 0; i < cs->statements->dim; ++i)
245        {
246        Lagain:
247            Statement *s = (*cs->statements)[i];
248            if (!s)
249                continue;
250
251            Statement *se = s->isErrorStatement();
252            if (se)
253            {
254                result = se;
255                return;
256            }
257
258            /* Bugzilla 11653: 'semantic' may return another CompoundStatement
259             * (eg. CaseRangeStatement), so flatten it here.
260             */
261            Statements *flt = s->flatten(sc);
262            if (flt)
263            {
264                cs->statements->remove(i);
265                cs->statements->insert(i, flt);
266                if (cs->statements->dim <= i)
267                    break;
268                goto Lagain;
269            }
270        }
271        if (cs->statements->dim == 1)
272        {
273            result = (*cs->statements)[0];
274            return;
275        }
276        result = cs;
277    }
278
279    void visit(UnrolledLoopStatement *uls)
280    {
281        //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", uls, sc);
282        Scope *scd = sc->push();
283        scd->sbreak = uls;
284        scd->scontinue = uls;
285
286        Statement *serror = NULL;
287        for (size_t i = 0; i < uls->statements->dim; i++)
288        {
289            Statement *s = (*uls->statements)[i];
290            if (s)
291            {
292                //printf("[%d]: %s\n", i, s->toChars());
293                s = semantic(s, scd);
294                (*uls->statements)[i] = s;
295
296                if (s && !serror)
297                    serror = s->isErrorStatement();
298            }
299        }
300
301        scd->pop();
302        result = serror ? serror : uls;
303    }
304
305    void visit(ScopeStatement *ss)
306    {
307        //printf("ScopeStatement::semantic(sc = %p)\n", sc);
308        if (ss->statement)
309        {
310            ScopeDsymbol *sym = new ScopeDsymbol();
311            sym->parent = sc->scopesym;
312            sym->endlinnum = ss->endloc.linnum;
313            sc = sc->push(sym);
314
315            Statements *a = ss->statement->flatten(sc);
316            if (a)
317            {
318                ss->statement = new CompoundStatement(ss->loc, a);
319            }
320
321            ss->statement = semantic(ss->statement, sc);
322            if (ss->statement)
323            {
324                if (ss->statement->isErrorStatement())
325                {
326                    sc->pop();
327                    result = ss->statement;
328                    return;
329                }
330
331                Statement *sentry;
332                Statement *sexception;
333                Statement *sfinally;
334
335                ss->statement = ss->statement->scopeCode(sc, &sentry, &sexception, &sfinally);
336                assert(!sentry);
337                assert(!sexception);
338                if (sfinally)
339                {
340                    //printf("adding sfinally\n");
341                    sfinally = semantic(sfinally, sc);
342                    ss->statement = new CompoundStatement(ss->loc, ss->statement, sfinally);
343                }
344            }
345
346            sc->pop();
347        }
348        result = ss;
349    }
350
351    void visit(ForwardingStatement *ss)
352    {
353        assert(ss->sym);
354        for (Scope *csc = sc; !ss->sym->forward; csc = csc->enclosing)
355        {
356            assert(csc);
357            ss->sym->forward = csc->scopesym;
358        }
359        sc = sc->push(ss->sym);
360        sc->sbreak = ss;
361        sc->scontinue = ss;
362        ss->statement = semantic(ss->statement, sc);
363        sc = sc->pop();
364        result = ss->statement;
365    }
366
367    void visit(WhileStatement *ws)
368    {
369        /* Rewrite as a for(;condition;) loop
370         */
371        Statement *s = new ForStatement(ws->loc, NULL, ws->condition, NULL, ws->_body, ws->endloc);
372        s = semantic(s, sc);
373        result = s;
374    }
375
376    void visit(DoStatement *ds)
377    {
378        sc->noctor++;
379        if (ds->_body)
380            ds->_body = semanticScope(ds->_body, sc, ds, ds);
381        sc->noctor--;
382
383        if (ds->condition->op == TOKdotid)
384            ((DotIdExp *)ds->condition)->noderef = true;
385
386        // check in syntax level
387        ds->condition = checkAssignmentAsCondition(ds->condition);
388
389        ds->condition = semantic(ds->condition, sc);
390        ds->condition = resolveProperties(sc, ds->condition);
391        if (checkNonAssignmentArrayOp(ds->condition))
392            ds->condition = new ErrorExp();
393        ds->condition = ds->condition->optimize(WANTvalue);
394        ds->condition = checkGC(sc, ds->condition);
395
396        ds->condition = ds->condition->toBoolean(sc);
397
398        if (ds->condition->op == TOKerror)
399            return setError();
400
401        if (ds->_body && ds->_body->isErrorStatement())
402        {
403            result = ds->_body;
404            return;
405        }
406
407        result = ds;
408    }
409
410    void visit(ForStatement *fs)
411    {
412        //printf("ForStatement::semantic %s\n", toChars());
413
414        if (fs->_init)
415        {
416            /* Rewrite:
417             *  for (auto v1 = i1, v2 = i2; condition; increment) { ... }
418             * to:
419             *  { auto v1 = i1, v2 = i2; for (; condition; increment) { ... } }
420             * then lowered to:
421             *  auto v1 = i1;
422             *  try {
423             *    auto v2 = i2;
424             *    try {
425             *      for (; condition; increment) { ... }
426             *    } finally { v2.~this(); }
427             *  } finally { v1.~this(); }
428             */
429            Statements *ainit = new Statements();
430            ainit->push(fs->_init);
431            fs->_init = NULL;
432            ainit->push(fs);
433            Statement *s = new CompoundStatement(fs->loc, ainit);
434            s = new ScopeStatement(fs->loc, s, fs->endloc);
435            s = semantic(s, sc);
436            if (!s->isErrorStatement())
437            {
438                if (LabelStatement *ls = checkLabeledLoop(sc, fs))
439                    ls->gotoTarget = fs;
440                fs->relatedLabeled = s;
441            }
442            result = s;
443            return;
444        }
445        assert(fs->_init == NULL);
446
447        ScopeDsymbol *sym = new ScopeDsymbol();
448        sym->parent = sc->scopesym;
449        sym->endlinnum = fs->endloc.linnum;
450        sc = sc->push(sym);
451
452        sc->noctor++;
453        if (fs->condition)
454        {
455            if (fs->condition->op == TOKdotid)
456                ((DotIdExp *)fs->condition)->noderef = true;
457
458            // check in syntax level
459            fs->condition = checkAssignmentAsCondition(fs->condition);
460
461            fs->condition = semantic(fs->condition, sc);
462            fs->condition = resolveProperties(sc, fs->condition);
463            if (checkNonAssignmentArrayOp(fs->condition))
464                fs->condition = new ErrorExp();
465            fs->condition = fs->condition->optimize(WANTvalue);
466            fs->condition = checkGC(sc, fs->condition);
467            fs->condition = fs->condition->toBoolean(sc);
468        }
469        if (fs->increment)
470        {
471            if (fs->increment->op == TOKcomma)
472                ((CommaExp *)fs->increment)->allowCommaExp = true;
473            fs->increment = semantic(fs->increment, sc);
474            fs->increment = resolveProperties(sc, fs->increment);
475            if (checkNonAssignmentArrayOp(fs->increment))
476                fs->increment = new ErrorExp();
477            fs->increment = fs->increment->optimize(WANTvalue);
478            fs->increment = checkGC(sc, fs->increment);
479        }
480
481        sc->sbreak = fs;
482        sc->scontinue = fs;
483        if (fs->_body)
484            fs->_body = semanticNoScope(fs->_body, sc);
485        sc->noctor--;
486
487        sc->pop();
488
489        if ((fs->condition && fs->condition->op == TOKerror) ||
490            (fs->increment && fs->increment->op == TOKerror) ||
491            (fs->_body && fs->_body->isErrorStatement()))
492            return setError();
493
494        result = fs;
495    }
496
497    /***********************
498     * Declares a unrolled `foreach` loop variable or a `static foreach` variable.
499     *
500     * Params:
501     *     storageClass = The storage class of the variable.
502     *     type = The declared type of the variable.
503     *     ident = The name of the variable.
504     *     e = The initializer of the variable (i.e. the current element of the looped over aggregate).
505     *     t = The type of the initializer.
506     * Returns:
507     *     `true` iff the declaration was successful.
508     */
509    bool declareVariable(ForeachStatement *fs, Type *paramtype, TupleExp *te,
510        bool needExpansion, bool isStatic, Statements *statements, Dsymbols *declarations,
511        StorageClass storageClass, Type *type, Identifier *ident, Expression *e, Type *t)
512    {
513        Loc loc = fs->loc;
514        if (storageClass & (STCout | STClazy) ||
515            (storageClass & STCref && !te))
516        {
517            fs->error("no storage class for value %s", ident->toChars());
518            return false;
519        }
520        Declaration *var;
521        if (e)
522        {
523            Type *tb = e->type->toBasetype();
524            Dsymbol *ds = NULL;
525            if (!(storageClass & STCmanifest))
526            {
527                if ((isStatic || tb->ty == Tfunction || tb->ty == Tsarray || storageClass & STCalias) && e->op == TOKvar)
528                    ds = ((VarExp *)e)->var;
529                else if (e->op == TOKtemplate)
530                    ds = ((TemplateExp *)e)->td;
531                else if (e->op == TOKscope)
532                    ds = ((ScopeExp *)e)->sds;
533                else if (e->op == TOKfunction)
534                {
535                    FuncExp *fe = (FuncExp *)e;
536                    ds = fe->td ? (Dsymbol *)fe->td : fe->fd;
537                }
538            }
539            else if (storageClass & STCalias)
540            {
541                fs->error("foreach loop variable cannot be both enum and alias");
542                return false;
543            }
544
545            if (ds)
546            {
547                var = new AliasDeclaration(loc, ident, ds);
548                if (storageClass & STCref)
549                {
550                    fs->error("symbol %s cannot be ref", ds->toChars());
551                    return false;
552                }
553                if (paramtype)
554                {
555                    fs->error("cannot specify element type for symbol %s", ds->toChars());
556                    return false;
557                }
558            }
559            else if (e->op == TOKtype)
560            {
561                var = new AliasDeclaration(loc, ident, e->type);
562                if (paramtype)
563                {
564                    fs->error("cannot specify element type for type %s", e->type->toChars());
565                    return false;
566                }
567            }
568            else
569            {
570                e = resolveProperties(sc, e);
571                Initializer *ie = new ExpInitializer(Loc(), e);
572                VarDeclaration *v = new VarDeclaration(loc, type, ident, ie);
573                if (storageClass & STCref)
574                    v->storage_class |= STCref | STCforeach;
575                if (isStatic || storageClass & STCmanifest || e->isConst() ||
576                    e->op == TOKstring ||
577                    e->op == TOKstructliteral ||
578                    e->op == TOKarrayliteral)
579                {
580                    if (v->storage_class & STCref)
581                    {
582                        if (!isStatic || !needExpansion)
583                        {
584                            fs->error("constant value %s cannot be ref", ie->toChars());
585                        }
586                        else
587                        {
588                            fs->error("constant value %s cannot be ref", ident->toChars());
589                        }
590                        return false;
591                    }
592                    else
593                        v->storage_class |= STCmanifest;
594                }
595                var = v;
596            }
597        }
598        else
599        {
600            var = new AliasDeclaration(loc, ident, t);
601            if (paramtype)
602            {
603                fs->error("cannot specify element type for symbol %s", fs->toChars());
604                return false;
605            }
606        }
607        if (isStatic)
608            var->storage_class |= STClocal;
609        if (statements)
610            statements->push(new ExpStatement(loc, var));
611        else if (declarations)
612            declarations->push(var);
613        else
614            assert(0);
615        return true;
616    }
617
618    bool makeTupleForeachBody(ForeachStatement *fs, size_t k,
619        Type *paramtype, TupleExp *te, TypeTuple *tuple,
620        bool needExpansion, bool isStatic, bool isDecl,
621        Statements *statements, Dsymbols *declarations, Dsymbols *dbody)
622    {
623        Loc loc = fs->loc;
624        Expression *e = NULL;
625        Type *t = NULL;
626        if (te)
627            e = (*te->exps)[k];
628        else
629            t = Parameter::getNth(tuple->arguments, k)->type;
630        Parameter *p = (*fs->parameters)[0];
631        Statements *stmts = (isDecl) ? NULL : new Statements();
632        Dsymbols *decls = (isDecl) ? new Dsymbols() : NULL;
633
634        size_t dim = fs->parameters->dim;
635        if (!needExpansion && dim == 2)
636        {
637            // Declare key
638            if (p->storageClass & (STCout | STCref | STClazy))
639            {
640                fs->error("no storage class for key %s", p->ident->toChars());
641                return false;
642            }
643            if (isStatic)
644            {
645                if (!p->type)
646                {
647                    p->type = Type::tsize_t;
648                }
649            }
650            p->type = p->type->semantic(loc, sc);
651
652            if (!p->type->isintegral())
653            {
654                fs->error("foreach: key cannot be of non-integral type `%s`",
655                          p->type->toChars());
656                return false;
657            }
658
659            unsigned length = te ? te->exps->dim : tuple->arguments->dim;
660            IntRange dimrange = IntRange(SignExtendedNumber(length)).cast(Type::tsize_t);
661            // https://issues.dlang.org/show_bug.cgi?id=12504
662            dimrange.imax = SignExtendedNumber(dimrange.imax.value-1);
663            if (!IntRange::fromType(p->type).contains(dimrange))
664            {
665                fs->error("index type `%s` cannot cover index range 0..%llu",
666			  p->type->toChars(), (ulonglong)length);
667                return false;
668            }
669            Initializer *ie = new ExpInitializer(Loc(), new IntegerExp(k));
670            VarDeclaration *var = new VarDeclaration(loc, p->type, p->ident, ie);
671            var->storage_class |= STCmanifest;
672            if (isStatic)
673                var->storage_class |= STClocal;
674            if (!isDecl)
675                stmts->push(new ExpStatement(loc, var));
676            else
677                decls->push(var);
678            p = (*fs->parameters)[1];  // value
679        }
680
681        if (!isStatic || !needExpansion)
682        {
683            // Declare value
684            if (!declareVariable(fs, paramtype, te, needExpansion, isStatic, stmts, decls,
685                                 p->storageClass, p->type, p->ident, e, t))
686            {
687                return false;
688            }
689        }
690        else
691        {
692            // expand tuples into multiple `static foreach` variables.
693            assert(e && !t);
694            Identifier *ident = Identifier::generateId("__value");
695            declareVariable(fs, paramtype, te, needExpansion, isStatic, stmts, decls,
696                            0, e->type, ident, e, NULL);
697            Identifier *field = Identifier::idPool("tuple");
698            Expression *access = new DotIdExp(loc, e, field);
699            access = semantic(access, sc);
700            if (!tuple)
701                return false;
702            //printf("%s\n", tuple->toChars());
703            for (size_t l = 0; l < dim; l++)
704            {
705                Parameter *cp = (*fs->parameters)[l];
706                Expression *init_ = new IndexExp(loc, access, new IntegerExp(loc, l, Type::tsize_t));
707                init_ = semantic(init_, sc);
708                assert(init_->type);
709                declareVariable(fs, paramtype, te, needExpansion, isStatic, stmts, decls,
710                                p->storageClass, init_->type, cp->ident, init_, NULL);
711            }
712        }
713        Statement *fwdstmt = NULL;
714        Dsymbol *fwddecl = NULL;
715        if (!isDecl)
716        {
717            if (fs->_body)
718                stmts->push(fs->_body->syntaxCopy());
719            fwdstmt = new CompoundStatement(loc, stmts);
720        }
721        else
722        {
723            decls->append(Dsymbol::arraySyntaxCopy(dbody));
724        }
725        if (!isStatic)
726        {
727            fwdstmt = new ScopeStatement(loc, fwdstmt, fs->endloc);
728        }
729        else if (!isDecl)
730        {
731            fwdstmt = new ForwardingStatement(loc, fwdstmt);
732        }
733        else
734        {
735            fwddecl = new ForwardingAttribDeclaration(decls);
736        }
737
738        if (statements)
739            statements->push(fwdstmt);
740        else if (declarations)
741            declarations->push(fwddecl);
742        else
743            assert(0);
744        return true;
745    }
746
747    /*******************
748     * Type check and unroll `foreach` over an expression tuple as well
749     * as `static foreach` statements and `static foreach`
750     * declarations. For `static foreach` statements and `static
751     * foreach` declarations, the visitor interface is used (and the
752     * result is written into the `result` field.) For `static
753     * foreach` declarations, the resulting Dsymbols* are returned
754     * directly.
755     *
756     * The unrolled body is wrapped into a
757     *  - UnrolledLoopStatement, for `foreach` over an expression tuple.
758     *  - ForwardingStatement, for `static foreach` statements.
759     *  - ForwardingAttribDeclaration, for `static foreach` declarations.
760     *
761     * `static foreach` variables are declared as `STClocal`, such
762     * that they are inserted into the local symbol tables of the
763     * forwarding constructs instead of forwarded. For `static
764     * foreach` with multiple foreach loop variables whose aggregate
765     * has been lowered into a sequence of tuples, this function
766     * expands the tuples into multiple `STClocal` `static foreach`
767     * variables.
768     */
769    bool makeTupleForeach(ForeachStatement *fs, bool needExpansion, bool isStatic, bool isDecl,
770                          Statements *statements, Dsymbols *declarations, Dsymbols *dbody)
771    {
772        Loc loc = fs->loc;
773        size_t dim = fs->parameters->dim;
774        if (!needExpansion && (dim < 1 || dim > 2))
775        {
776            fs->error("only one (value) or two (key,value) arguments for tuple foreach");
777            return false;
778        }
779
780        Type *paramtype = (*fs->parameters)[dim-1]->type;
781        if (paramtype)
782        {
783            paramtype = paramtype->semantic(loc, sc);
784            if (paramtype->ty == Terror)
785                return false;
786        }
787
788        Type *tab = fs->aggr->type->toBasetype();
789        TypeTuple *tuple = (TypeTuple *)tab;
790        //printf("aggr: op = %d, %s\n", fs->aggr->op, fs->aggr->toChars());
791        size_t n;
792        TupleExp *te = NULL;
793        if (fs->aggr->op == TOKtuple)       // expression tuple
794        {
795            te = (TupleExp *)fs->aggr;
796            n = te->exps->dim;
797        }
798        else if (fs->aggr->op == TOKtype)   // type tuple
799        {
800            n = Parameter::dim(tuple->arguments);
801        }
802        else
803            assert(0);
804        for (size_t j = 0; j < n; j++)
805        {
806            size_t k = (fs->op == TOKforeach) ? j : n - 1 - j;
807            if (!makeTupleForeachBody(fs, k, paramtype, te, tuple,
808                                      needExpansion, isStatic, isDecl,
809                                      statements, declarations, dbody))
810                return false;
811        }
812        return true;
813    }
814
815    Dsymbols *makeTupleForeachStaticDecl(ForeachStatement *fs, Dsymbols *dbody, bool needExpansion)
816    {
817        assert(sc);
818        Dsymbols *declarations = new Dsymbols();
819        if (!makeTupleForeach(fs, needExpansion, true, true, NULL, declarations, dbody))
820            return NULL;
821
822        return declarations;
823    }
824
825    void makeTupleForeachStatic(ForeachStatement *fs, bool needExpansion)
826    {
827        Loc loc = fs->loc;
828        assert(sc);
829        Statements *statements = new Statements();
830        if (!makeTupleForeach(fs, needExpansion, true, false, statements, NULL, NULL))
831            return setError();
832
833        result = new CompoundStatement(loc, statements);
834    }
835
836    void visit(ForeachStatement *fs)
837    {
838        //printf("ForeachStatement::semantic() %p\n", fs);
839        ScopeDsymbol *sym;
840        Statement *s = fs;
841        Loc loc = fs->loc;
842        size_t dim = fs->parameters->dim;
843        TypeAArray *taa = NULL;
844        Dsymbol *sapply = NULL;
845
846        Type *tn = NULL;
847        Type *tnv = NULL;
848
849        fs->func = sc->func;
850        if (fs->func->fes)
851            fs->func = fs->func->fes->func;
852
853        VarDeclaration *vinit = NULL;
854        fs->aggr = semantic(fs->aggr, sc);
855        fs->aggr = resolveProperties(sc, fs->aggr);
856        fs->aggr = fs->aggr->optimize(WANTvalue);
857        if (fs->aggr->op == TOKerror)
858            return setError();
859
860        Expression *oaggr = fs->aggr;
861        if (fs->aggr->type && fs->aggr->type->toBasetype()->ty == Tstruct &&
862            ((TypeStruct *)(fs->aggr->type->toBasetype()))->sym->dtor &&
863            fs->aggr->op != TOKtype && !fs->aggr->isLvalue())
864        {
865            // Bugzilla 14653: Extend the life of rvalue aggregate till the end of foreach.
866            vinit = copyToTemp(STCrvalue, "__aggr", fs->aggr);
867            vinit->semantic(sc);
868            fs->aggr = new VarExp(fs->aggr->loc, vinit);
869        }
870
871        if (!inferAggregate(fs, sc, sapply))
872        {
873            const char *msg = "";
874            if (fs->aggr->type && isAggregate(fs->aggr->type))
875            {
876                msg = ", define opApply(), range primitives, or use .tupleof";
877            }
878            fs->error("invalid foreach aggregate %s%s", oaggr->toChars(), msg);
879            return setError();
880        }
881
882        Dsymbol* sapplyOld = sapply;  // 'sapply' will be NULL if and after 'inferApplyArgTypes' errors
883
884        /* Check for inference errors
885        */
886        if (!inferApplyArgTypes(fs, sc, sapply))
887        {
888            /**
889              Try and extract the parameter count of the opApply callback function, e.g.:
890              int opApply(int delegate(int, float)) => 2 args
891              */
892            bool foundMismatch = false;
893            size_t foreachParamCount = 0;
894            if (sapplyOld)
895            {
896                if (FuncDeclaration *fd = sapplyOld->isFuncDeclaration())
897                {
898                    int fvarargs;  // ignored (opApply shouldn't take variadics)
899                    Parameters *fparameters = fd->getParameters(&fvarargs);
900
901                    if (Parameter::dim(fparameters) == 1)
902                    {
903                        // first param should be the callback function
904                        Parameter *fparam = Parameter::getNth(fparameters, 0);
905                        if ((fparam->type->ty == Tpointer || fparam->type->ty == Tdelegate) &&
906                            fparam->type->nextOf()->ty == Tfunction)
907                        {
908                            TypeFunction *tf = (TypeFunction *)fparam->type->nextOf();
909                            foreachParamCount = Parameter::dim(tf->parameters);
910                            foundMismatch = true;
911                        }
912                    }
913                }
914            }
915
916            //printf("dim = %d, parameters->dim = %d\n", dim, fs->parameters->dim);
917            if (foundMismatch && dim != foreachParamCount)
918            {
919                const char *plural = foreachParamCount > 1 ? "s" : "";
920                fs->error("cannot infer argument types, expected %d argument%s, not %d",
921                          foreachParamCount, plural, dim);
922            }
923            else
924                fs->error("cannot uniquely infer foreach argument types");
925
926            return setError();
927        }
928
929        Type *tab = fs->aggr->type->toBasetype();
930
931        if (tab->ty == Ttuple)      // don't generate new scope for tuple loops
932        {
933            Statements *statements = new Statements();
934            if (!makeTupleForeach(fs, false, false, false, statements, NULL, NULL))
935                return setError();
936
937            result = new UnrolledLoopStatement(loc, statements);
938            if (LabelStatement *ls = checkLabeledLoop(sc, fs))
939                ls->gotoTarget = result;
940            if (fs->aggr->op == TOKtuple)
941            {
942                TupleExp *te = (TupleExp *)fs->aggr;
943                if (te->e0)
944                    result = new CompoundStatement(loc, new ExpStatement(te->e0->loc, te->e0), result);
945            }
946            if (vinit)
947                result = new CompoundStatement(loc, new ExpStatement(loc, vinit), result);
948            result = semantic(result, sc);
949            return;
950        }
951
952        sym = new ScopeDsymbol();
953        sym->parent = sc->scopesym;
954        sym->endlinnum = fs->endloc.linnum;
955        Scope *sc2 = sc->push(sym);
956
957        sc2->noctor++;
958
959        for (size_t i = 0; i < dim; i++)
960        {
961            Parameter *p = (*fs->parameters)[i];
962            if (p->storageClass & STCmanifest)
963            {
964                fs->error("cannot declare enum loop variables for non-unrolled foreach");
965            }
966            if (p->storageClass & STCalias)
967            {
968                fs->error("cannot declare alias loop variables for non-unrolled foreach");
969            }
970        }
971
972        switch (tab->ty)
973        {
974            case Tarray:
975            case Tsarray:
976                {
977                    if (fs->checkForArgTypes())
978                    {
979                        result = fs;
980                        return;
981                    }
982
983                    if (dim < 1 || dim > 2)
984                    {
985                        fs->error("only one or two arguments for array foreach");
986                        goto Lerror2;
987                    }
988
989                    // Finish semantic on all foreach parameter types.
990                    for (size_t i = 0; i < dim; i++)
991                    {
992                        Parameter *p = (*fs->parameters)[i];
993                        p->type = p->type->semantic(loc, sc2);
994                        p->type = p->type->addStorageClass(p->storageClass);
995                    }
996
997                    tn = tab->nextOf()->toBasetype();
998
999                    if (dim == 2)
1000                    {
1001                        Type *tindex = (*fs->parameters)[0]->type;
1002                        if (!tindex->isintegral())
1003                        {
1004                            fs->error("foreach: key cannot be of non-integral type `%s`",
1005                                      tindex->toChars());
1006                            goto Lerror2;
1007                        }
1008                        /* What cases to deprecate implicit conversions for:
1009                         *  1. foreach aggregate is a dynamic array
1010                         *  2. foreach body is lowered to _aApply (see special case below).
1011                         */
1012                        Type *tv = (*fs->parameters)[1]->type->toBasetype();
1013                        if ((tab->ty == Tarray ||
1014                             (tn->ty != tv->ty &&
1015                              (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar) &&
1016                              (tv->ty == Tchar || tv->ty == Twchar || tv->ty == Tdchar))) &&
1017                            !Type::tsize_t->implicitConvTo(tindex))
1018                        {
1019                            fs->deprecation("foreach: loop index implicitly converted from `size_t` to `%s`",
1020                                            tindex->toChars());
1021                        }
1022                    }
1023
1024                    /* Look for special case of parsing char types out of char type
1025                     * array.
1026                     */
1027                    if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
1028                    {
1029                        int i = (dim == 1) ? 0 : 1;     // index of value
1030                        Parameter *p = (*fs->parameters)[i];
1031                        tnv = p->type->toBasetype();
1032                        if (tnv->ty != tn->ty &&
1033                            (tnv->ty == Tchar || tnv->ty == Twchar || tnv->ty == Tdchar))
1034                        {
1035                            if (p->storageClass & STCref)
1036                            {
1037                                fs->error("foreach: value of UTF conversion cannot be ref");
1038                                goto Lerror2;
1039                            }
1040                            if (dim == 2)
1041                            {
1042                                p = (*fs->parameters)[0];
1043                                if (p->storageClass & STCref)
1044                                {
1045                                    fs->error("foreach: key cannot be ref");
1046                                    goto Lerror2;
1047                                }
1048                            }
1049                            goto Lapply;
1050                        }
1051                    }
1052
1053                    for (size_t i = 0; i < dim; i++)
1054                    {
1055                        // Declare parameterss
1056                        Parameter *p = (*fs->parameters)[i];
1057                        VarDeclaration *var;
1058
1059                        if (dim == 2 && i == 0)
1060                        {
1061                            var = new VarDeclaration(loc, p->type->mutableOf(), Identifier::generateId("__key"), NULL);
1062                            var->storage_class |= STCtemp | STCforeach;
1063                            if (var->storage_class & (STCref | STCout))
1064                                var->storage_class |= STCnodtor;
1065
1066                            fs->key = var;
1067                            if (p->storageClass & STCref)
1068                            {
1069                                if (var->type->constConv(p->type) <= MATCHnomatch)
1070                                {
1071                                    fs->error("key type mismatch, %s to ref %s",
1072                                              var->type->toChars(), p->type->toChars());
1073                                    goto Lerror2;
1074                                }
1075                            }
1076                            if (tab->ty == Tsarray)
1077                            {
1078                                TypeSArray *ta =  (TypeSArray *)tab;
1079                                IntRange dimrange = getIntRange(ta->dim);
1080                                // https://issues.dlang.org/show_bug.cgi?id=12504
1081                                dimrange.imax = SignExtendedNumber(dimrange.imax.value-1);
1082                                if (!IntRange::fromType(var->type).contains(dimrange))
1083                                {
1084                                    fs->error("index type '%s' cannot cover index range 0..%llu", p->type->toChars(), ta->dim->toInteger());
1085                                    goto Lerror2;
1086                                }
1087                                fs->key->range = new IntRange(SignExtendedNumber(0), dimrange.imax);
1088                            }
1089                        }
1090                        else
1091                        {
1092                            var = new VarDeclaration(loc, p->type, p->ident, NULL);
1093                            var->storage_class |= STCforeach;
1094                            var->storage_class |= p->storageClass & (STCin | STCout | STCref | STC_TYPECTOR);
1095                            if (var->storage_class & (STCref | STCout))
1096                                var->storage_class |= STCnodtor;
1097
1098                            fs->value = var;
1099                            if (var->storage_class & STCref)
1100                            {
1101                                if (fs->aggr->checkModifiable(sc2, 1) == 2)
1102                                    var->storage_class |= STCctorinit;
1103
1104                                Type *t = tab->nextOf();
1105                                if (t->constConv(p->type) <= MATCHnomatch)
1106                                {
1107                                    fs->error("argument type mismatch, %s to ref %s",
1108                                              t->toChars(), p->type->toChars());
1109                                    goto Lerror2;
1110                                }
1111                            }
1112                        }
1113                    }
1114
1115                    /* Convert to a ForStatement
1116                     *   foreach (key, value; a) body =>
1117                     *   for (T[] tmp = a[], size_t key; key < tmp.length; ++key)
1118                     *   { T value = tmp[k]; body }
1119                     *
1120                     *   foreach_reverse (key, value; a) body =>
1121                     *   for (T[] tmp = a[], size_t key = tmp.length; key--; )
1122                     *   { T value = tmp[k]; body }
1123                     */
1124                    Identifier *id = Identifier::generateId("__r");
1125                    ExpInitializer *ie = new ExpInitializer(loc, new SliceExp(loc, fs->aggr, NULL, NULL));
1126                    VarDeclaration *tmp;
1127                    if (fs->aggr->op == TOKarrayliteral &&
1128                        !((*fs->parameters)[dim - 1]->storageClass & STCref))
1129                    {
1130                        ArrayLiteralExp *ale = (ArrayLiteralExp *)fs->aggr;
1131                        size_t edim = ale->elements ? ale->elements->dim : 0;
1132                        Type *telem = (*fs->parameters)[dim - 1]->type;
1133
1134                        // Bugzilla 12936: if telem has been specified explicitly,
1135                        // converting array literal elements to telem might make it @nogc.
1136                        fs->aggr = fs->aggr->implicitCastTo(sc, telem->sarrayOf(edim));
1137                        if (fs->aggr->op == TOKerror)
1138                            goto Lerror2;
1139
1140                        // for (T[edim] tmp = a, ...)
1141                        tmp = new VarDeclaration(loc, fs->aggr->type, id, ie);
1142                    }
1143                    else
1144                        tmp = new VarDeclaration(loc, tab->nextOf()->arrayOf(), id, ie);
1145                    tmp->storage_class |= STCtemp;
1146                    tmp->endlinnum = fs->endloc.linnum;
1147
1148                    Expression *tmp_length = new DotIdExp(loc, new VarExp(loc, tmp), Id::length);
1149
1150                    if (!fs->key)
1151                    {
1152                        Identifier *idkey = Identifier::generateId("__key");
1153                        fs->key = new VarDeclaration(loc, Type::tsize_t, idkey, NULL);
1154                        fs->key->storage_class |= STCtemp;
1155                    }
1156                    else if (fs->key->type->ty != Tsize_t)
1157                    {
1158                        tmp_length = new CastExp(loc, tmp_length, fs->key->type);
1159                    }
1160                    if (fs->op == TOKforeach_reverse)
1161                        fs->key->_init = new ExpInitializer(loc, tmp_length);
1162                    else
1163                        fs->key->_init = new ExpInitializer(loc, new IntegerExp(loc, 0, fs->key->type));
1164
1165                    Statements *cs = new Statements();
1166                    if (vinit)
1167                        cs->push(new ExpStatement(loc, vinit));
1168                    cs->push(new ExpStatement(loc, tmp));
1169                    cs->push(new ExpStatement(loc, fs->key));
1170                    Statement *forinit = new CompoundDeclarationStatement(loc, cs);
1171
1172                    Expression *cond;
1173                    if (fs->op == TOKforeach_reverse)
1174                    {
1175                        // key--
1176                        cond = new PostExp(TOKminusminus, loc, new VarExp(loc, fs->key));
1177                    }
1178                    else
1179                    {
1180                        // key < tmp.length
1181                        cond = new CmpExp(TOKlt, loc, new VarExp(loc, fs->key), tmp_length);
1182                    }
1183
1184                    Expression *increment = NULL;
1185                    if (fs->op == TOKforeach)
1186                    {
1187                        // key += 1
1188                        increment = new AddAssignExp(loc, new VarExp(loc, fs->key), new IntegerExp(loc, 1, fs->key->type));
1189                    }
1190
1191                    // T value = tmp[key];
1192                    fs->value->_init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, fs->key)));
1193                    Statement *ds = new ExpStatement(loc, fs->value);
1194
1195                    if (dim == 2)
1196                    {
1197                        Parameter *p = (*fs->parameters)[0];
1198                        if ((p->storageClass & STCref) && p->type->equals(fs->key->type))
1199                        {
1200                            fs->key->range = NULL;
1201                            AliasDeclaration *v = new AliasDeclaration(loc, p->ident, fs->key);
1202                            fs->_body = new CompoundStatement(loc, new ExpStatement(loc, v), fs->_body);
1203                        }
1204                        else
1205                        {
1206                            ExpInitializer *ei = new ExpInitializer(loc, new IdentifierExp(loc, fs->key->ident));
1207                            VarDeclaration *v = new VarDeclaration(loc, p->type, p->ident, ei);
1208                            v->storage_class |= STCforeach | (p->storageClass & STCref);
1209                            fs->_body = new CompoundStatement(loc, new ExpStatement(loc, v), fs->_body);
1210                            if (fs->key->range && !p->type->isMutable())
1211                            {
1212                                /* Limit the range of the key to the specified range
1213                                */
1214                                v->range = new IntRange(fs->key->range->imin, fs->key->range->imax - SignExtendedNumber(1));
1215                            }
1216                        }
1217                    }
1218                    fs->_body = new CompoundStatement(loc, ds, fs->_body);
1219
1220                    s = new ForStatement(loc, forinit, cond, increment, fs->_body, fs->endloc);
1221                    if (LabelStatement *ls = checkLabeledLoop(sc, fs))   // Bugzilla 15450: don't use sc2
1222                        ls->gotoTarget = s;
1223                    s = semantic(s, sc2);
1224                    break;
1225                }
1226
1227            case Taarray:
1228                if (fs->op == TOKforeach_reverse)
1229                    fs->warning("cannot use foreach_reverse with an associative array");
1230                if (fs->checkForArgTypes())
1231                {
1232                    result = fs;
1233                    return;
1234                }
1235
1236                taa = (TypeAArray *)tab;
1237                if (dim < 1 || dim > 2)
1238                {
1239                    fs->error("only one or two arguments for associative array foreach");
1240                    goto Lerror2;
1241                }
1242                goto Lapply;
1243
1244            case Tclass:
1245            case Tstruct:
1246                /* Prefer using opApply, if it exists
1247                */
1248                if (sapply)
1249                    goto Lapply;
1250
1251                {
1252                    /* Look for range iteration, i.e. the properties
1253                     * .empty, .popFront, .popBack, .front and .back
1254                     *    foreach (e; aggr) { ... }
1255                     * translates to:
1256                     *    for (auto __r = aggr[]; !__r.empty; __r.popFront()) {
1257                     *        auto e = __r.front;
1258                     *        ...
1259                     *    }
1260                     */
1261                    AggregateDeclaration *ad = (tab->ty == Tclass)
1262                        ? (AggregateDeclaration *)((TypeClass  *)tab)->sym
1263                        : (AggregateDeclaration *)((TypeStruct *)tab)->sym;
1264                    Identifier *idfront;
1265                    Identifier *idpopFront;
1266                    if (fs->op == TOKforeach)
1267                    {
1268                        idfront = Id::Ffront;
1269                        idpopFront = Id::FpopFront;
1270                    }
1271                    else
1272                    {
1273                        idfront = Id::Fback;
1274                        idpopFront = Id::FpopBack;
1275                    }
1276                    Dsymbol *sfront = ad->search(Loc(), idfront);
1277                    if (!sfront)
1278                        goto Lapply;
1279
1280                    /* Generate a temporary __r and initialize it with the aggregate.
1281                     */
1282                    VarDeclaration *r;
1283                    Statement *init;
1284                    if (vinit && fs->aggr->op == TOKvar && ((VarExp *)fs->aggr)->var == vinit)
1285                    {
1286                        r = vinit;
1287                        init = new ExpStatement(loc, vinit);
1288                    }
1289                    else
1290                    {
1291                        r = copyToTemp(0, "__r", fs->aggr);
1292                        r->semantic(sc);
1293                        init = new ExpStatement(loc, r);
1294                        if (vinit)
1295                            init = new CompoundStatement(loc, new ExpStatement(loc, vinit), init);
1296                    }
1297
1298                    // !__r.empty
1299                    Expression *e = new VarExp(loc, r);
1300                    e = new DotIdExp(loc, e, Id::Fempty);
1301                    Expression *condition = new NotExp(loc, e);
1302
1303                    // __r.idpopFront()
1304                    e = new VarExp(loc, r);
1305                    Expression *increment = new CallExp(loc, new DotIdExp(loc, e, idpopFront));
1306
1307                    /* Declaration statement for e:
1308                     *    auto e = __r.idfront;
1309                     */
1310                    e = new VarExp(loc, r);
1311                    Expression *einit = new DotIdExp(loc, e, idfront);
1312                    Statement *makeargs, *forbody;
1313                    if (dim == 1)
1314                    {
1315                        Parameter *p = (*fs->parameters)[0];
1316                        VarDeclaration *ve = new VarDeclaration(loc, p->type, p->ident, new ExpInitializer(loc, einit));
1317                        ve->storage_class |= STCforeach;
1318                        ve->storage_class |= p->storageClass & (STCin | STCout | STCref | STC_TYPECTOR);
1319
1320                        makeargs = new ExpStatement(loc, ve);
1321                    }
1322                    else
1323                    {
1324                        VarDeclaration *vd = copyToTemp(STCref, "__front", einit);
1325                        vd->semantic(sc);
1326                        makeargs = new ExpStatement(loc, vd);
1327
1328                        Type *tfront = NULL;
1329                        if (FuncDeclaration *fd = sfront->isFuncDeclaration())
1330                        {
1331                            if (!fd->functionSemantic())
1332                                goto Lrangeerr;
1333                            tfront = fd->type;
1334                        }
1335                        else if (TemplateDeclaration *td = sfront->isTemplateDeclaration())
1336                        {
1337                            Expressions a;
1338                            if (FuncDeclaration *f = resolveFuncCall(loc, sc, td, NULL, tab, &a, 1))
1339                                tfront = f->type;
1340                        }
1341                        else if (Declaration *d = sfront->isDeclaration())
1342                        {
1343                            tfront = d->type;
1344                        }
1345                        if (!tfront || tfront->ty == Terror)
1346                            goto Lrangeerr;
1347
1348                        if (tfront->toBasetype()->ty == Tfunction)
1349                            tfront = tfront->toBasetype()->nextOf();
1350                        if (tfront->ty == Tvoid)
1351                        {
1352                            fs->error("%s.front is void and has no value", oaggr->toChars());
1353                            goto Lerror2;
1354                        }
1355
1356                        // Resolve inout qualifier of front type
1357                        tfront = tfront->substWildTo(tab->mod);
1358
1359                        Expression *ve = new VarExp(loc, vd);
1360                        ve->type = tfront;
1361
1362                        Expressions *exps = new Expressions();
1363                        exps->push(ve);
1364                        int pos = 0;
1365                        while (exps->dim < dim)
1366                        {
1367                            pos = expandAliasThisTuples(exps, pos);
1368                            if (pos == -1)
1369                                break;
1370                        }
1371                        if (exps->dim != dim)
1372                        {
1373                            const char *plural = exps->dim > 1 ? "s" : "";
1374                            fs->error("cannot infer argument types, expected %d argument%s, not %d",
1375                                      exps->dim, plural, dim);
1376                            goto Lerror2;
1377                        }
1378
1379                        for (size_t i = 0; i < dim; i++)
1380                        {
1381                            Parameter *p = (*fs->parameters)[i];
1382                            Expression *exp = (*exps)[i];
1383                            if (!p->type)
1384                                p->type = exp->type;
1385                            p->type = p->type->addStorageClass(p->storageClass)->semantic(loc, sc2);
1386                            if (!exp->implicitConvTo(p->type))
1387                                goto Lrangeerr;
1388
1389                            VarDeclaration *var = new VarDeclaration(loc, p->type, p->ident, new ExpInitializer(loc, exp));
1390                            var->storage_class |= STCctfe | STCref | STCforeach;
1391                            makeargs = new CompoundStatement(loc, makeargs, new ExpStatement(loc, var));
1392                        }
1393
1394                    }
1395
1396                    forbody = new CompoundStatement(loc,
1397                                                    makeargs, fs->_body);
1398
1399                    s = new ForStatement(loc, init, condition, increment, forbody, fs->endloc);
1400                    if (LabelStatement *ls = checkLabeledLoop(sc, fs))
1401                        ls->gotoTarget = s;
1402                    s = semantic(s, sc2);
1403                    break;
1404
1405                Lrangeerr:
1406                    fs->error("cannot infer argument types");
1407                    goto Lerror2;
1408                }
1409            case Tdelegate:
1410                if (fs->op == TOKforeach_reverse)
1411                    fs->deprecation("cannot use foreach_reverse with a delegate");
1412            Lapply:
1413                {
1414                    if (fs->checkForArgTypes())
1415                    {
1416                        fs->_body = semanticNoScope(fs->_body, sc2);
1417                        result = fs;
1418                        return;
1419                    }
1420
1421                    TypeFunction *tfld = NULL;
1422                    if (sapply)
1423                    {
1424                        FuncDeclaration *fdapply = sapply->isFuncDeclaration();
1425                        if (fdapply)
1426                        {
1427                            assert(fdapply->type && fdapply->type->ty == Tfunction);
1428                            tfld = (TypeFunction *)fdapply->type->semantic(loc, sc2);
1429                            goto Lget;
1430                        }
1431                        else if (tab->ty == Tdelegate)
1432                        {
1433                            tfld = (TypeFunction *)tab->nextOf();
1434                        Lget:
1435                            //printf("tfld = %s\n", tfld->toChars());
1436                            if (tfld->parameters->dim == 1)
1437                            {
1438                                Parameter *p = Parameter::getNth(tfld->parameters, 0);
1439                                if (p->type && p->type->ty == Tdelegate)
1440                                {
1441                                    Type *t = p->type->semantic(loc, sc2);
1442                                    assert(t->ty == Tdelegate);
1443                                    tfld = (TypeFunction *)t->nextOf();
1444                                }
1445                            }
1446                        }
1447                    }
1448
1449                    /* Turn body into the function literal:
1450                     *  int delegate(ref T param) { body }
1451                     */
1452                    Parameters *params = new Parameters();
1453                    for (size_t i = 0; i < dim; i++)
1454                    {
1455                        Parameter *p = (*fs->parameters)[i];
1456                        StorageClass stc = STCref;
1457                        Identifier *id;
1458
1459                        p->type = p->type->semantic(loc, sc2);
1460                        p->type = p->type->addStorageClass(p->storageClass);
1461                        if (tfld)
1462                        {
1463                            Parameter *prm = Parameter::getNth(tfld->parameters, i);
1464                            //printf("\tprm = %s%s\n", (prm->storageClass&STCref?"ref ":""), prm->ident->toChars());
1465                            stc = prm->storageClass & STCref;
1466                            id = p->ident;    // argument copy is not need.
1467                            if ((p->storageClass & STCref) != stc)
1468                            {
1469                                if (!stc)
1470                                {
1471                                    fs->error("foreach: cannot make %s ref", p->ident->toChars());
1472                                    goto Lerror2;
1473                                }
1474                                goto LcopyArg;
1475                            }
1476                        }
1477                        else if (p->storageClass & STCref)
1478                        {
1479                            // default delegate parameters are marked as ref, then
1480                            // argument copy is not need.
1481                            id = p->ident;
1482                        }
1483                        else
1484                        {
1485                            // Make a copy of the ref argument so it isn't
1486                            // a reference.
1487                        LcopyArg:
1488                            id = Identifier::generateId("__applyArg", (int)i);
1489
1490                            Initializer *ie = new ExpInitializer(Loc(), new IdentifierExp(Loc(), id));
1491                            VarDeclaration *v = new VarDeclaration(Loc(), p->type, p->ident, ie);
1492                            v->storage_class |= STCtemp;
1493                            s = new ExpStatement(Loc(), v);
1494                            fs->_body = new CompoundStatement(loc, s, fs->_body);
1495                        }
1496                        params->push(new Parameter(stc, p->type, id, NULL));
1497                    }
1498                    // Bugzilla 13840: Throwable nested function inside nothrow function is acceptable.
1499                    StorageClass stc = mergeFuncAttrs(STCsafe | STCpure | STCnogc, fs->func);
1500                    tfld = new TypeFunction(params, Type::tint32, 0, LINKd, stc);
1501                    fs->cases = new Statements();
1502                    fs->gotos = new ScopeStatements();
1503                    FuncLiteralDeclaration *fld = new FuncLiteralDeclaration(loc, Loc(), tfld, TOKdelegate, fs);
1504                    fld->fbody = fs->_body;
1505                    Expression *flde = new FuncExp(loc, fld);
1506                    flde = semantic(flde, sc2);
1507                    fld->tookAddressOf = 0;
1508
1509                    // Resolve any forward referenced goto's
1510                    for (size_t i = 0; i < fs->gotos->dim; i++)
1511                    {
1512                        GotoStatement *gs = (GotoStatement *)(*fs->gotos)[i]->statement;
1513                        if (!gs->label->statement)
1514                        {
1515                            // 'Promote' it to this scope, and replace with a return
1516                            fs->cases->push(gs);
1517                            s = new ReturnStatement(Loc(), new IntegerExp(fs->cases->dim + 1));
1518                            (*fs->gotos)[i]->statement = s;
1519                        }
1520                    }
1521
1522                    Expression *e = NULL;
1523                    Expression *ec;
1524                    if (vinit)
1525                    {
1526                        e = new DeclarationExp(loc, vinit);
1527                        e = semantic(e, sc2);
1528                        if (e->op == TOKerror)
1529                            goto Lerror2;
1530                    }
1531
1532                    if (taa)
1533                    {
1534                        // Check types
1535                        Parameter *p = (*fs->parameters)[0];
1536                        bool isRef = (p->storageClass & STCref) != 0;
1537                        Type *ta = p->type;
1538                        if (dim == 2)
1539                        {
1540                            Type *ti = (isRef ? taa->index->addMod(MODconst) : taa->index);
1541                            if (isRef ? !ti->constConv(ta) : !ti->implicitConvTo(ta))
1542                            {
1543                                fs->error("foreach: index must be type %s, not %s", ti->toChars(), ta->toChars());
1544                                goto Lerror2;
1545                            }
1546                            p = (*fs->parameters)[1];
1547                            isRef = (p->storageClass & STCref) != 0;
1548                            ta = p->type;
1549                        }
1550                        Type *taav = taa->nextOf();
1551                        if (isRef ? !taav->constConv(ta) : !taav->implicitConvTo(ta))
1552                        {
1553                            fs->error("foreach: value must be type %s, not %s", taav->toChars(), ta->toChars());
1554                            goto Lerror2;
1555                        }
1556
1557                        /* Call:
1558                         *  extern(C) int _aaApply(void*, in size_t, int delegate(void*))
1559                         *      _aaApply(aggr, keysize, flde)
1560                         *
1561                         *  extern(C) int _aaApply2(void*, in size_t, int delegate(void*, void*))
1562                         *      _aaApply2(aggr, keysize, flde)
1563                         */
1564                        static const char *name[2] = { "_aaApply", "_aaApply2" };
1565                        static FuncDeclaration *fdapply[2] = { NULL, NULL };
1566                        static TypeDelegate *fldeTy[2] = { NULL, NULL };
1567
1568                        unsigned char i = (dim == 2 ? 1 : 0);
1569                        if (!fdapply[i])
1570                        {
1571                            params = new Parameters();
1572                            params->push(new Parameter(0, Type::tvoid->pointerTo(), NULL, NULL));
1573                            params->push(new Parameter(STCin, Type::tsize_t, NULL, NULL));
1574                            Parameters* dgparams = new Parameters;
1575                            dgparams->push(new Parameter(0, Type::tvoidptr, NULL, NULL));
1576                            if (dim == 2)
1577                                dgparams->push(new Parameter(0, Type::tvoidptr, NULL, NULL));
1578                            fldeTy[i] = new TypeDelegate(new TypeFunction(dgparams, Type::tint32, 0, LINKd));
1579                            params->push(new Parameter(0, fldeTy[i], NULL, NULL));
1580                            fdapply[i] = FuncDeclaration::genCfunc(params, Type::tint32, name[i]);
1581                        }
1582
1583                        Expressions *exps = new Expressions();
1584                        exps->push(fs->aggr);
1585                        d_uns64 keysize = taa->index->size();
1586                        if (keysize == SIZE_INVALID)
1587                            goto Lerror2;
1588                        assert(keysize < UINT64_MAX - Target::ptrsize);
1589                        keysize = (keysize + (Target::ptrsize- 1)) & ~(Target::ptrsize - 1);
1590                        // paint delegate argument to the type runtime expects
1591                        if (!fldeTy[i]->equals(flde->type))
1592                        {
1593                            flde = new CastExp(loc, flde, flde->type);
1594                            flde->type = fldeTy[i];
1595                        }
1596                        exps->push(new IntegerExp(Loc(), keysize, Type::tsize_t));
1597                        exps->push(flde);
1598
1599                        ec = new VarExp(Loc(), fdapply[i], false);
1600                        ec = new CallExp(loc, ec, exps);
1601                        ec->type = Type::tint32; // don't run semantic() on ec
1602                    }
1603                    else if (tab->ty == Tarray || tab->ty == Tsarray)
1604                    {
1605                        /* Call:
1606                         *      _aApply(aggr, flde)
1607                         */
1608                        static const char fntab[9][3] =
1609                        { "cc","cw","cd",
1610                            "wc","cc","wd",
1611                            "dc","dw","dd"
1612                        };
1613                        const int BUFFER_LEN = 7+1+2+ sizeof(dim)*3 + 1;
1614                        char fdname[BUFFER_LEN];
1615                        int flag;
1616
1617                        switch (tn->ty)
1618                        {
1619                            case Tchar:         flag = 0; break;
1620                            case Twchar:        flag = 3; break;
1621                            case Tdchar:        flag = 6; break;
1622                            default:            assert(0);
1623                        }
1624                        switch (tnv->ty)
1625                        {
1626                            case Tchar:         flag += 0; break;
1627                            case Twchar:        flag += 1; break;
1628                            case Tdchar:        flag += 2; break;
1629                            default:            assert(0);
1630                        }
1631                        const char *r = (fs->op == TOKforeach_reverse) ? "R" : "";
1632                        int j = sprintf(fdname, "_aApply%s%.*s%llu", r, 2, fntab[flag], (ulonglong)dim);
1633                        assert(j < BUFFER_LEN);
1634
1635                        FuncDeclaration *fdapply;
1636                        TypeDelegate *dgty;
1637                        params = new Parameters();
1638                        params->push(new Parameter(STCin, tn->arrayOf(), NULL, NULL));
1639                        Parameters* dgparams = new Parameters;
1640                        dgparams->push(new Parameter(0, Type::tvoidptr, NULL, NULL));
1641                        if (dim == 2)
1642                            dgparams->push(new Parameter(0, Type::tvoidptr, NULL, NULL));
1643                        dgty = new TypeDelegate(new TypeFunction(dgparams, Type::tint32, 0, LINKd));
1644                        params->push(new Parameter(0, dgty, NULL, NULL));
1645                        fdapply = FuncDeclaration::genCfunc(params, Type::tint32, fdname);
1646
1647                        if (tab->ty == Tsarray)
1648                            fs->aggr = fs->aggr->castTo(sc2, tn->arrayOf());
1649
1650                        // paint delegate argument to the type runtime expects
1651                        if (!dgty->equals(flde->type)) {
1652                            flde = new CastExp(loc, flde, flde->type);
1653                            flde->type = dgty;
1654                        }
1655
1656                        ec = new VarExp(Loc(), fdapply, false);
1657                        ec = new CallExp(loc, ec, fs->aggr, flde);
1658                        ec->type = Type::tint32; // don't run semantic() on ec
1659                    }
1660                    else if (tab->ty == Tdelegate)
1661                    {
1662                        /* Call:
1663                         *      aggr(flde)
1664                         */
1665                        if (fs->aggr->op == TOKdelegate &&
1666                            ((DelegateExp *)fs->aggr)->func->isNested())
1667                        {
1668                            // See Bugzilla 3560
1669                            fs->aggr = ((DelegateExp *)fs->aggr)->e1;
1670                        }
1671                        ec = new CallExp(loc, fs->aggr, flde);
1672                        ec = semantic(ec, sc2);
1673                        if (ec->op == TOKerror)
1674                            goto Lerror2;
1675                        if (ec->type != Type::tint32)
1676                        {
1677                            fs->error("opApply() function for %s must return an int", tab->toChars());
1678                            goto Lerror2;
1679                        }
1680                    }
1681                    else
1682                    {
1683                        if (global.params.vsafe)
1684                            fld->tookAddressOf = 1;  // allocate a closure unless the opApply() uses 'scope'
1685
1686                        assert(tab->ty == Tstruct || tab->ty == Tclass);
1687                        assert(sapply);
1688                        /* Call:
1689                         *  aggr.apply(flde)
1690                         */
1691                        ec = new DotIdExp(loc, fs->aggr, sapply->ident);
1692                        ec = new CallExp(loc, ec, flde);
1693                        ec = semantic(ec, sc2);
1694                        if (ec->op == TOKerror)
1695                            goto Lerror2;
1696                        if (ec->type != Type::tint32)
1697                        {
1698                            fs->error("opApply() function for %s must return an int", tab->toChars());
1699                            goto Lerror2;
1700                        }
1701                    }
1702                    e = Expression::combine(e, ec);
1703
1704                    if (!fs->cases->dim)
1705                    {
1706                        // Easy case, a clean exit from the loop
1707                        e = new CastExp(loc, e, Type::tvoid);   // Bugzilla 13899
1708                        s = new ExpStatement(loc, e);
1709                    }
1710                    else
1711                    {
1712                        // Construct a switch statement around the return value
1713                        // of the apply function.
1714                        Statements *a = new Statements();
1715
1716                        // default: break; takes care of cases 0 and 1
1717                        s = new BreakStatement(Loc(), NULL);
1718                        s = new DefaultStatement(Loc(), s);
1719                        a->push(s);
1720
1721                        // cases 2...
1722                        for (size_t i = 0; i < fs->cases->dim; i++)
1723                        {
1724                            s = (*fs->cases)[i];
1725                            s = new CaseStatement(Loc(), new IntegerExp(i + 2), s);
1726                            a->push(s);
1727                        }
1728
1729                        s = new CompoundStatement(loc, a);
1730                        s = new SwitchStatement(loc, e, s, false);
1731                    }
1732                    s = semantic(s, sc2);
1733                    break;
1734                }
1735            case Terror:
1736            Lerror2:
1737                s = new ErrorStatement();
1738                break;
1739
1740            default:
1741                fs->error("foreach: %s is not an aggregate type", fs->aggr->type->toChars());
1742                goto Lerror2;
1743        }
1744        sc2->noctor--;
1745        sc2->pop();
1746        result = s;
1747    }
1748
1749    void visit(ForeachRangeStatement *fs)
1750    {
1751        //printf("ForeachRangeStatement::semantic() %p\n", fs);
1752        Loc loc = fs->loc;
1753        fs->lwr = semantic(fs->lwr, sc);
1754        fs->lwr = resolveProperties(sc, fs->lwr);
1755        fs->lwr = fs->lwr->optimize(WANTvalue);
1756        if (!fs->lwr->type)
1757        {
1758            fs->error("invalid range lower bound %s", fs->lwr->toChars());
1759        Lerror:
1760            return setError();
1761        }
1762
1763        fs->upr = semantic(fs->upr, sc);
1764        fs->upr = resolveProperties(sc, fs->upr);
1765        fs->upr = fs->upr->optimize(WANTvalue);
1766        if (!fs->upr->type)
1767        {
1768            fs->error("invalid range upper bound %s", fs->upr->toChars());
1769            goto Lerror;
1770        }
1771
1772        if (fs->prm->type)
1773        {
1774            fs->prm->type = fs->prm->type->semantic(loc, sc);
1775            fs->prm->type = fs->prm->type->addStorageClass(fs->prm->storageClass);
1776            fs->lwr = fs->lwr->implicitCastTo(sc, fs->prm->type);
1777
1778            if (fs->upr->implicitConvTo(fs->prm->type) || (fs->prm->storageClass & STCref))
1779            {
1780                fs->upr = fs->upr->implicitCastTo(sc, fs->prm->type);
1781            }
1782            else
1783            {
1784                // See if upr-1 fits in prm->type
1785                Expression *limit = new MinExp(loc, fs->upr, new IntegerExp(1));
1786                limit = semantic(limit, sc);
1787                limit = limit->optimize(WANTvalue);
1788                if (!limit->implicitConvTo(fs->prm->type))
1789                {
1790                    fs->upr = fs->upr->implicitCastTo(sc, fs->prm->type);
1791                }
1792            }
1793        }
1794        else
1795        {
1796            /* Must infer types from lwr and upr
1797            */
1798            Type *tlwr = fs->lwr->type->toBasetype();
1799            if (tlwr->ty == Tstruct || tlwr->ty == Tclass)
1800            {
1801                /* Just picking the first really isn't good enough.
1802                */
1803                fs->prm->type = fs->lwr->type;
1804            }
1805            else if (fs->lwr->type == fs->upr->type)
1806            {
1807                /* Same logic as CondExp ?lwr:upr
1808                */
1809                fs->prm->type = fs->lwr->type;
1810            }
1811            else
1812            {
1813                AddExp ea(loc, fs->lwr, fs->upr);
1814                if (typeCombine(&ea, sc))
1815                    return setError();
1816                fs->prm->type = ea.type;
1817                fs->lwr = ea.e1;
1818                fs->upr = ea.e2;
1819            }
1820            fs->prm->type = fs->prm->type->addStorageClass(fs->prm->storageClass);
1821        }
1822        if (fs->prm->type->ty == Terror ||
1823            fs->lwr->op == TOKerror ||
1824            fs->upr->op == TOKerror)
1825        {
1826            return setError();
1827        }
1828
1829        /* Convert to a for loop:
1830         *  foreach (key; lwr .. upr) =>
1831         *  for (auto key = lwr, auto tmp = upr; key < tmp; ++key)
1832         *
1833         *  foreach_reverse (key; lwr .. upr) =>
1834         *  for (auto tmp = lwr, auto key = upr; key-- > tmp;)
1835         */
1836        ExpInitializer *ie = new ExpInitializer(loc, (fs->op == TOKforeach) ? fs->lwr : fs->upr);
1837        fs->key = new VarDeclaration(loc, fs->upr->type->mutableOf(), Identifier::generateId("__key"), ie);
1838        fs->key->storage_class |= STCtemp;
1839        SignExtendedNumber lower = getIntRange(fs->lwr).imin;
1840        SignExtendedNumber upper = getIntRange(fs->upr).imax;
1841        if (lower <= upper)
1842        {
1843            fs->key->range = new IntRange(lower, upper);
1844        }
1845
1846        Identifier *id = Identifier::generateId("__limit");
1847        ie = new ExpInitializer(loc, (fs->op == TOKforeach) ? fs->upr : fs->lwr);
1848        VarDeclaration *tmp = new VarDeclaration(loc, fs->upr->type, id, ie);
1849        tmp->storage_class |= STCtemp;
1850
1851        Statements *cs = new Statements();
1852        // Keep order of evaluation as lwr, then upr
1853        if (fs->op == TOKforeach)
1854        {
1855            cs->push(new ExpStatement(loc, fs->key));
1856            cs->push(new ExpStatement(loc, tmp));
1857        }
1858        else
1859        {
1860            cs->push(new ExpStatement(loc, tmp));
1861            cs->push(new ExpStatement(loc, fs->key));
1862        }
1863        Statement *forinit = new CompoundDeclarationStatement(loc, cs);
1864
1865        Expression *cond;
1866        if (fs->op == TOKforeach_reverse)
1867        {
1868            cond = new PostExp(TOKminusminus, loc, new VarExp(loc, fs->key));
1869            if (fs->prm->type->isscalar())
1870            {
1871                // key-- > tmp
1872                cond = new CmpExp(TOKgt, loc, cond, new VarExp(loc, tmp));
1873            }
1874            else
1875            {
1876                // key-- != tmp
1877                cond = new EqualExp(TOKnotequal, loc, cond, new VarExp(loc, tmp));
1878            }
1879        }
1880        else
1881        {
1882            if (fs->prm->type->isscalar())
1883            {
1884                // key < tmp
1885                cond = new CmpExp(TOKlt, loc, new VarExp(loc, fs->key), new VarExp(loc, tmp));
1886            }
1887            else
1888            {
1889                // key != tmp
1890                cond = new EqualExp(TOKnotequal, loc, new VarExp(loc, fs->key), new VarExp(loc, tmp));
1891            }
1892        }
1893
1894        Expression *increment = NULL;
1895        if (fs->op == TOKforeach)
1896        {
1897            // key += 1
1898            //increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1));
1899            increment = new PreExp(TOKpreplusplus, loc, new VarExp(loc, fs->key));
1900        }
1901
1902        if ((fs->prm->storageClass & STCref) && fs->prm->type->equals(fs->key->type))
1903        {
1904            fs->key->range = NULL;
1905            AliasDeclaration *v = new AliasDeclaration(loc, fs->prm->ident, fs->key);
1906            fs->_body = new CompoundStatement(loc, new ExpStatement(loc, v), fs->_body);
1907        }
1908        else
1909        {
1910            ie = new ExpInitializer(loc, new CastExp(loc, new VarExp(loc, fs->key), fs->prm->type));
1911            VarDeclaration *v = new VarDeclaration(loc, fs->prm->type, fs->prm->ident, ie);
1912            v->storage_class |= STCtemp | STCforeach | (fs->prm->storageClass & STCref);
1913            fs->_body = new CompoundStatement(loc, new ExpStatement(loc, v), fs->_body);
1914            if (fs->key->range && !fs->prm->type->isMutable())
1915            {
1916                /* Limit the range of the key to the specified range
1917                */
1918                v->range = new IntRange(fs->key->range->imin, fs->key->range->imax - SignExtendedNumber(1));
1919            }
1920        }
1921        if (fs->prm->storageClass & STCref)
1922        {
1923            if (fs->key->type->constConv(fs->prm->type) <= MATCHnomatch)
1924            {
1925                fs->error("prmument type mismatch, %s to ref %s",
1926                          fs->key->type->toChars(), fs->prm->type->toChars());
1927                goto Lerror;
1928            }
1929        }
1930
1931        ForStatement *s = new ForStatement(loc, forinit, cond, increment, fs->_body, fs->endloc);
1932        if (LabelStatement *ls = checkLabeledLoop(sc, fs))
1933            ls->gotoTarget = s;
1934        result = semantic(s, sc);
1935    }
1936
1937    void visit(IfStatement *ifs)
1938    {
1939        // Evaluate at runtime
1940        unsigned cs0 = sc->callSuper;
1941        unsigned cs1;
1942        unsigned *fi0 = sc->saveFieldInit();
1943        unsigned *fi1 = NULL;
1944
1945        // check in syntax level
1946        ifs->condition = checkAssignmentAsCondition(ifs->condition);
1947
1948        ScopeDsymbol *sym = new ScopeDsymbol();
1949        sym->parent = sc->scopesym;
1950        sym->endlinnum = ifs->endloc.linnum;
1951        Scope *scd = sc->push(sym);
1952        if (ifs->prm)
1953        {
1954            /* Declare prm, which we will set to be the
1955             * result of condition.
1956             */
1957            ExpInitializer *ei = new ExpInitializer(ifs->loc, ifs->condition);
1958            ifs->match = new VarDeclaration(ifs->loc, ifs->prm->type, ifs->prm->ident, ei);
1959            ifs->match->parent = sc->func;
1960            ifs->match->storage_class |= ifs->prm->storageClass;
1961            ifs->match->semantic(scd);
1962
1963            DeclarationExp *de = new DeclarationExp(ifs->loc, ifs->match);
1964            VarExp *ve = new VarExp(ifs->loc, ifs->match);
1965            ifs->condition = new CommaExp(ifs->loc, de, ve);
1966            ifs->condition = semantic(ifs->condition, scd);
1967
1968            if (ifs->match->edtor)
1969            {
1970                Statement *sdtor = new DtorExpStatement(ifs->loc, ifs->match->edtor, ifs->match);
1971                sdtor = new OnScopeStatement(ifs->loc, TOKon_scope_exit, sdtor);
1972                ifs->ifbody = new CompoundStatement(ifs->loc, sdtor, ifs->ifbody);
1973                ifs->match->storage_class |= STCnodtor;
1974            }
1975        }
1976        else
1977        {
1978            if (ifs->condition->op == TOKdotid)
1979                ((DotIdExp *)ifs->condition)->noderef = true;
1980
1981            ifs->condition = semantic(ifs->condition, sc);
1982            ifs->condition = resolveProperties(sc, ifs->condition);
1983            ifs->condition = ifs->condition->addDtorHook(sc);
1984        }
1985        if (checkNonAssignmentArrayOp(ifs->condition))
1986            ifs->condition = new ErrorExp();
1987        ifs->condition = checkGC(sc, ifs->condition);
1988
1989        // Convert to boolean after declaring prm so this works:
1990        //  if (S prm = S()) {}
1991        // where S is a struct that defines opCast!bool.
1992        ifs->condition = ifs->condition->toBoolean(sc);
1993
1994        // If we can short-circuit evaluate the if statement, don't do the
1995        // semantic analysis of the skipped code.
1996        // This feature allows a limited form of conditional compilation.
1997        ifs->condition = ifs->condition->optimize(WANTvalue);
1998        ifs->ifbody = semanticNoScope(ifs->ifbody, scd);
1999        scd->pop();
2000
2001        cs1 = sc->callSuper;
2002        fi1 = sc->fieldinit;
2003        sc->callSuper = cs0;
2004        sc->fieldinit = fi0;
2005        if (ifs->elsebody)
2006            ifs->elsebody = semanticScope(ifs->elsebody, sc, NULL, NULL);
2007        sc->mergeCallSuper(ifs->loc, cs1);
2008        sc->mergeFieldInit(ifs->loc, fi1);
2009
2010        if (ifs->condition->op == TOKerror ||
2011            (ifs->ifbody && ifs->ifbody->isErrorStatement()) ||
2012            (ifs->elsebody && ifs->elsebody->isErrorStatement()))
2013        {
2014            return setError();
2015        }
2016        result = ifs;
2017    }
2018
2019    void visit(ConditionalStatement *cs)
2020    {
2021        //printf("ConditionalStatement::semantic()\n");
2022
2023        // If we can short-circuit evaluate the if statement, don't do the
2024        // semantic analysis of the skipped code.
2025        // This feature allows a limited form of conditional compilation.
2026        if (cs->condition->include(sc, NULL))
2027        {
2028            DebugCondition *dc = cs->condition->isDebugCondition();
2029            if (dc)
2030            {
2031                sc = sc->push();
2032                sc->flags |= SCOPEdebug;
2033                cs->ifbody = semantic(cs->ifbody, sc);
2034                sc->pop();
2035            }
2036            else
2037                cs->ifbody = semantic(cs->ifbody, sc);
2038            result = cs->ifbody;
2039        }
2040        else
2041        {
2042            if (cs->elsebody)
2043                cs->elsebody = semantic(cs->elsebody, sc);
2044            result = cs->elsebody;
2045        }
2046    }
2047
2048    void visit(PragmaStatement *ps)
2049    {
2050        // Should be merged with PragmaDeclaration
2051        //printf("PragmaStatement::semantic() %s\n", ps->toChars());
2052        //printf("body = %p\n", ps->_body);
2053        if (ps->ident == Id::msg)
2054        {
2055            if (ps->args)
2056            {
2057                for (size_t i = 0; i < ps->args->dim; i++)
2058                {
2059                    Expression *e = (*ps->args)[i];
2060
2061                    sc = sc->startCTFE();
2062                    e = semantic(e, sc);
2063                    e = resolveProperties(sc, e);
2064                    sc = sc->endCTFE();
2065                    // pragma(msg) is allowed to contain types as well as expressions
2066                    e = ctfeInterpretForPragmaMsg(e);
2067                    if (e->op == TOKerror)
2068                    {
2069                        errorSupplemental(ps->loc, "while evaluating pragma(msg, %s)", (*ps->args)[i]->toChars());
2070                        goto Lerror;
2071                    }
2072                    StringExp *se = e->toStringExp();
2073                    if (se)
2074                    {
2075                        se = se->toUTF8(sc);
2076                        fprintf(stderr, "%.*s", (int)se->len, (char *)se->string);
2077                    }
2078                    else
2079                        fprintf(stderr, "%s", e->toChars());
2080                }
2081                fprintf(stderr, "\n");
2082            }
2083        }
2084        else if (ps->ident == Id::lib)
2085        {
2086            /* Should this be allowed?
2087            */
2088            ps->error("pragma(lib) not allowed as statement");
2089            goto Lerror;
2090        }
2091        else if (ps->ident == Id::startaddress)
2092        {
2093            if (!ps->args || ps->args->dim != 1)
2094                ps->error("function name expected for start address");
2095            else
2096            {
2097                Expression *e = (*ps->args)[0];
2098
2099                sc = sc->startCTFE();
2100                e = semantic(e, sc);
2101                e = resolveProperties(sc, e);
2102                sc = sc->endCTFE();
2103
2104                e = e->ctfeInterpret();
2105                (*ps->args)[0] = e;
2106                Dsymbol *sa = getDsymbol(e);
2107                if (!sa || !sa->isFuncDeclaration())
2108                {
2109                    ps->error("function name expected for start address, not '%s'", e->toChars());
2110                    goto Lerror;
2111                }
2112                if (ps->_body)
2113                {
2114                    ps->_body = semantic(ps->_body, sc);
2115                    if (ps->_body->isErrorStatement())
2116                    {
2117                        result = ps->_body;
2118                        return;
2119                    }
2120                }
2121                result = ps;
2122                return;
2123            }
2124        }
2125        else if (ps->ident == Id::Pinline)
2126        {
2127            PINLINE inlining = PINLINEdefault;
2128            if (!ps->args || ps->args->dim == 0)
2129                inlining = PINLINEdefault;
2130            else if (!ps->args || ps->args->dim != 1)
2131            {
2132                ps->error("boolean expression expected for pragma(inline)");
2133                goto Lerror;
2134            }
2135            else
2136            {
2137                Expression *e = (*ps->args)[0];
2138
2139                if (e->op != TOKint64 || !e->type->equals(Type::tbool))
2140                {
2141                    ps->error("pragma(inline, true or false) expected, not %s", e->toChars());
2142                    goto Lerror;
2143                }
2144
2145                if (e->isBool(true))
2146                    inlining = PINLINEalways;
2147                else if (e->isBool(false))
2148                    inlining = PINLINEnever;
2149
2150                FuncDeclaration *fd = sc->func;
2151                if (!fd)
2152                {
2153                    ps->error("pragma(inline) is not inside a function");
2154                    goto Lerror;
2155                }
2156                fd->inlining = inlining;
2157            }
2158        }
2159        else
2160        {
2161            ps->error("unrecognized pragma(%s)", ps->ident->toChars());
2162            goto Lerror;
2163        }
2164
2165        if (ps->_body)
2166        {
2167            if (ps->ident == Id::msg || ps->ident == Id::startaddress)
2168            {
2169                ps->error("`pragma(%s)` is missing a terminating `;`", ps->ident->toChars());
2170                return setError();
2171            }
2172            ps->_body = semantic(ps->_body, sc);
2173        }
2174        result = ps->_body;
2175        return;
2176
2177    Lerror:
2178        return setError();
2179    }
2180
2181    void visit(StaticAssertStatement *s)
2182    {
2183        s->sa->semantic2(sc);
2184    }
2185
2186    void visit(SwitchStatement *ss)
2187    {
2188        //printf("SwitchStatement::semantic(%p)\n", ss);
2189        ss->tf = sc->tf;
2190        if (ss->cases)
2191        {
2192            result = ss;            // already run
2193            return;
2194        }
2195        bool conditionError = false;
2196        ss->condition = semantic(ss->condition, sc);
2197        ss->condition = resolveProperties(sc, ss->condition);
2198
2199        Type *att = NULL;
2200        TypeEnum *te = NULL;
2201        while (ss->condition->op != TOKerror)
2202        {
2203            // preserve enum type for final switches
2204            if (ss->condition->type->ty == Tenum)
2205                te = (TypeEnum *)ss->condition->type;
2206            if (ss->condition->type->isString())
2207            {
2208                // If it's not an array, cast it to one
2209                if (ss->condition->type->ty != Tarray)
2210                {
2211                    ss->condition = ss->condition->implicitCastTo(sc, ss->condition->type->nextOf()->arrayOf());
2212                }
2213                ss->condition->type = ss->condition->type->constOf();
2214                break;
2215            }
2216            ss->condition = integralPromotions(ss->condition, sc);
2217            if (ss->condition->op != TOKerror && ss->condition->type->isintegral())
2218                break;
2219
2220            AggregateDeclaration *ad = isAggregate(ss->condition->type);
2221            if (ad && ad->aliasthis && ss->condition->type != att)
2222            {
2223                if (!att && ss->condition->type->checkAliasThisRec())
2224                    att = ss->condition->type;
2225                if (Expression *e = resolveAliasThis(sc, ss->condition, true))
2226                {
2227                    ss->condition = e;
2228                    continue;
2229                }
2230            }
2231
2232            if (ss->condition->op != TOKerror)
2233            {
2234                ss->error("'%s' must be of integral or string type, it is a %s",
2235                    ss->condition->toChars(), ss->condition->type->toChars());
2236                conditionError = true;
2237                break;
2238            }
2239        }
2240        if (checkNonAssignmentArrayOp(ss->condition))
2241            ss->condition = new ErrorExp();
2242        ss->condition = ss->condition->optimize(WANTvalue);
2243        ss->condition = checkGC(sc, ss->condition);
2244        if (ss->condition->op == TOKerror)
2245            conditionError = true;
2246
2247        bool needswitcherror = false;
2248
2249        ss->lastVar = sc->lastVar;
2250
2251        sc = sc->push();
2252        sc->sbreak = ss;
2253        sc->sw = ss;
2254
2255        ss->cases = new CaseStatements();
2256        sc->noctor++;       // BUG: should use Scope::mergeCallSuper() for each case instead
2257        ss->_body = semantic(ss->_body, sc);
2258        sc->noctor--;
2259
2260        if (conditionError || (ss->_body && ss->_body->isErrorStatement()))
2261            goto Lerror;
2262
2263        // Resolve any goto case's with exp
2264        for (size_t i = 0; i < ss->gotoCases.dim; i++)
2265        {
2266            GotoCaseStatement *gcs = ss->gotoCases[i];
2267
2268            if (!gcs->exp)
2269            {
2270                gcs->error("no case statement following goto case;");
2271                goto Lerror;
2272            }
2273
2274            for (Scope *scx = sc; scx; scx = scx->enclosing)
2275            {
2276                if (!scx->sw)
2277                    continue;
2278                for (size_t j = 0; j < scx->sw->cases->dim; j++)
2279                {
2280                    CaseStatement *cs = (*scx->sw->cases)[j];
2281
2282                    if (cs->exp->equals(gcs->exp))
2283                    {
2284                        gcs->cs = cs;
2285                        goto Lfoundcase;
2286                    }
2287                }
2288            }
2289            gcs->error("case %s not found", gcs->exp->toChars());
2290            goto Lerror;
2291
2292        Lfoundcase:
2293            ;
2294        }
2295
2296        if (ss->isFinal)
2297        {
2298            Type *t = ss->condition->type;
2299            Dsymbol *ds;
2300            EnumDeclaration *ed = NULL;
2301            if (t && ((ds = t->toDsymbol(sc)) != NULL))
2302                ed = ds->isEnumDeclaration();  // typedef'ed enum
2303            if (!ed && te && ((ds = te->toDsymbol(sc)) != NULL))
2304                ed = ds->isEnumDeclaration();
2305            if (ed)
2306            {
2307                size_t dim = ed->members->dim;
2308                for (size_t i = 0; i < dim; i++)
2309                {
2310                    EnumMember *em = (*ed->members)[i]->isEnumMember();
2311                    if (em)
2312                    {
2313                        for (size_t j = 0; j < ss->cases->dim; j++)
2314                        {
2315                            CaseStatement *cs = (*ss->cases)[j];
2316                            if (cs->exp->equals(em->value()) ||
2317                                (!cs->exp->type->isString() && !em->value()->type->isString() &&
2318                                 cs->exp->toInteger() == em->value()->toInteger()))
2319                                goto L1;
2320                        }
2321                        ss->error("enum member %s not represented in final switch", em->toChars());
2322                        goto Lerror;
2323                    }
2324                L1:
2325                    ;
2326                }
2327            }
2328            else
2329                needswitcherror = true;
2330        }
2331
2332        if (!sc->sw->sdefault && (!ss->isFinal || needswitcherror || global.params.useAssert))
2333        {
2334            ss->hasNoDefault = 1;
2335
2336            if (!ss->isFinal && (!ss->_body || !ss->_body->isErrorStatement()))
2337                ss->error("switch statement without a default; use 'final switch' or add 'default: assert(0);' or add 'default: break;'");
2338
2339            // Generate runtime error if the default is hit
2340            Statements *a = new Statements();
2341            CompoundStatement *cs;
2342            Statement *s;
2343
2344            if (global.params.useSwitchError &&
2345                global.params.checkAction != CHECKACTION_halt)
2346            {
2347                if (global.params.checkAction == CHECKACTION_C)
2348                {
2349                    /* Rewrite as an assert(0) and let e2ir generate
2350                     * the call to the C assert failure function
2351                     */
2352                    s = new ExpStatement(ss->loc, new AssertExp(ss->loc, new IntegerExp(ss->loc, 0, Type::tint32)));
2353                }
2354                else
2355                    s = new SwitchErrorStatement(ss->loc);
2356            }
2357            else
2358                s = new ExpStatement(ss->loc, new HaltExp(ss->loc));
2359
2360            a->reserve(2);
2361            sc->sw->sdefault = new DefaultStatement(ss->loc, s);
2362            a->push(ss->_body);
2363            if (blockExit(ss->_body, sc->func, false) & BEfallthru)
2364                a->push(new BreakStatement(Loc(), NULL));
2365            a->push(sc->sw->sdefault);
2366            cs = new CompoundStatement(ss->loc, a);
2367            ss->_body = cs;
2368        }
2369
2370        if (ss->checkLabel())
2371            goto Lerror;
2372
2373        sc->pop();
2374        result = ss;
2375        return;
2376
2377    Lerror:
2378        sc->pop();
2379        result = new ErrorStatement();
2380    }
2381
2382    void visit(CaseStatement *cs)
2383    {
2384        SwitchStatement *sw = sc->sw;
2385        bool errors = false;
2386
2387        //printf("CaseStatement::semantic() %s\n", cs->toChars());
2388        sc = sc->startCTFE();
2389        cs->exp = semantic(cs->exp, sc);
2390        cs->exp = resolveProperties(sc, cs->exp);
2391        sc = sc->endCTFE();
2392        if (sw)
2393        {
2394            cs->exp = cs->exp->implicitCastTo(sc, sw->condition->type);
2395            cs->exp = cs->exp->optimize(WANTvalue | WANTexpand);
2396
2397            Expression *e = cs->exp;
2398            // Remove all the casts the user and/or implicitCastTo may introduce
2399            // otherwise we'd sometimes fail the check below.
2400            while (e->op == TOKcast)
2401                e = ((CastExp *)e)->e1;
2402
2403            /* This is where variables are allowed as case expressions.
2404             */
2405            if (e->op == TOKvar)
2406            {
2407                VarExp *ve = (VarExp *)e;
2408                VarDeclaration *v = ve->var->isVarDeclaration();
2409                Type *t = cs->exp->type->toBasetype();
2410                if (v && (t->isintegral() || t->ty == Tclass))
2411                {
2412                    /* Flag that we need to do special code generation
2413                     * for this, i.e. generate a sequence of if-then-else
2414                     */
2415                    sw->hasVars = 1;
2416
2417                    /* TODO check if v can be uninitialized at that point.
2418                     */
2419                    if (!v->isConst() && !v->isImmutable())
2420                    {
2421                        cs->deprecation("case variables have to be const or immutable");
2422                    }
2423
2424                    if (sw->isFinal)
2425                    {
2426                        cs->error("case variables not allowed in final switch statements");
2427                        errors = true;
2428                    }
2429
2430                    /* Also check if the VarExp is declared in a scope outside of this one.
2431                     * 'scx' is set to the scope of the switch statement.
2432                     */
2433                    for (Scope *scx = sc; scx; scx = scx->enclosing)
2434                    {
2435                        if (scx->enclosing && scx->enclosing->sw == sw)
2436                            continue;
2437                        assert(scx->sw == sw);
2438
2439                        if (!scx->search(cs->exp->loc, v->ident, NULL))
2440                        {
2441                            cs->error("case variable `%s` declared at %s cannot be declared in switch body",
2442                                v->toChars(), v->loc.toChars());
2443                            errors = true;
2444                        }
2445                        break;
2446                    }
2447                    goto L1;
2448                }
2449            }
2450            else
2451                cs->exp = cs->exp->ctfeInterpret();
2452
2453            if (StringExp *se = cs->exp->toStringExp())
2454                cs->exp = se;
2455            else if (cs->exp->op != TOKint64 && cs->exp->op != TOKerror)
2456            {
2457                cs->error("case must be a string or an integral constant, not %s", cs->exp->toChars());
2458                errors = true;
2459            }
2460
2461        L1:
2462            for (size_t i = 0; i < sw->cases->dim; i++)
2463            {
2464                CaseStatement *cs2 = (*sw->cases)[i];
2465
2466                //printf("comparing '%s' with '%s'\n", cs->exp->toChars(), cs2->exp->toChars());
2467                if (cs2->exp->equals(cs->exp))
2468                {
2469                    cs->error("duplicate case %s in switch statement", cs->exp->toChars());
2470                    errors = true;
2471                    break;
2472                }
2473            }
2474
2475            sw->cases->push(cs);
2476
2477            // Resolve any goto case's with no exp to this case statement
2478            for (size_t i = 0; i < sw->gotoCases.dim; )
2479            {
2480                GotoCaseStatement *gcs = sw->gotoCases[i];
2481
2482                if (!gcs->exp)
2483                {
2484                    gcs->cs = cs;
2485                    sw->gotoCases.remove(i);        // remove from array
2486                    continue;
2487                }
2488                i++;
2489            }
2490
2491            if (sc->sw->tf != sc->tf)
2492            {
2493                cs->error("switch and case are in different finally blocks");
2494                errors = true;
2495            }
2496        }
2497        else
2498        {
2499            cs->error("case not in switch statement");
2500            errors = true;
2501        }
2502        cs->statement = semantic(cs->statement, sc);
2503        if (cs->statement->isErrorStatement())
2504        {
2505            result = cs->statement;
2506            return;
2507        }
2508        if (errors || cs->exp->op == TOKerror)
2509            return setError();
2510
2511        cs->lastVar = sc->lastVar;
2512        result = cs;
2513    }
2514
2515    void visit(CaseRangeStatement *crs)
2516    {
2517        SwitchStatement *sw = sc->sw;
2518        if (sw == NULL)
2519        {
2520            crs->error("case range not in switch statement");
2521            return setError();
2522        }
2523
2524        //printf("CaseRangeStatement::semantic() %s\n", toChars());
2525        bool errors = false;
2526        if (sw->isFinal)
2527        {
2528            crs->error("case ranges not allowed in final switch");
2529            errors = true;
2530        }
2531
2532        sc = sc->startCTFE();
2533        crs->first = semantic(crs->first, sc);
2534        crs->first = resolveProperties(sc, crs->first);
2535        sc = sc->endCTFE();
2536        crs->first = crs->first->implicitCastTo(sc, sw->condition->type);
2537        crs->first = crs->first->ctfeInterpret();
2538
2539        sc = sc->startCTFE();
2540        crs->last = semantic(crs->last, sc);
2541        crs->last = resolveProperties(sc, crs->last);
2542        sc = sc->endCTFE();
2543        crs->last = crs->last->implicitCastTo(sc, sw->condition->type);
2544        crs->last = crs->last->ctfeInterpret();
2545
2546        if (crs->first->op == TOKerror || crs->last->op == TOKerror || errors)
2547        {
2548            if (crs->statement)
2549                semantic(crs->statement, sc);
2550            return setError();
2551        }
2552
2553        uinteger_t fval = crs->first->toInteger();
2554        uinteger_t lval = crs->last->toInteger();
2555
2556
2557        if ( (crs->first->type->isunsigned()  &&  fval > lval) ||
2558             (!crs->first->type->isunsigned()  &&  (sinteger_t)fval > (sinteger_t)lval))
2559        {
2560            crs->error("first case %s is greater than last case %s",
2561                       crs->first->toChars(), crs->last->toChars());
2562            errors = true;
2563            lval = fval;
2564        }
2565
2566        if (lval - fval > 256)
2567        {
2568            crs->error("had %llu cases which is more than 256 cases in case range", lval - fval);
2569            errors = true;
2570            lval = fval + 256;
2571        }
2572
2573        if (errors)
2574            return setError();
2575
2576        /* This works by replacing the CaseRange with an array of Case's.
2577         *
2578         * case a: .. case b: s;
2579         *    =>
2580         * case a:
2581         *   [...]
2582         * case b:
2583         *   s;
2584         */
2585
2586        Statements *statements = new Statements();
2587        for (uinteger_t i = fval; i != lval + 1; i++)
2588        {
2589            Statement *s = crs->statement;
2590            if (i != lval)                          // if not last case
2591                s = new ExpStatement(crs->loc, (Expression *)NULL);
2592            Expression *e = new IntegerExp(crs->loc, i, crs->first->type);
2593            Statement *cs = new CaseStatement(crs->loc, e, s);
2594            statements->push(cs);
2595        }
2596        Statement *s = new CompoundStatement(crs->loc, statements);
2597        s = semantic(s, sc);
2598        result = s;
2599    }
2600
2601    void visit(DefaultStatement *ds)
2602    {
2603        //printf("DefaultStatement::semantic()\n");
2604        bool errors = false;
2605        if (sc->sw)
2606        {
2607            if (sc->sw->sdefault)
2608            {
2609                ds->error("switch statement already has a default");
2610                errors = true;
2611            }
2612            sc->sw->sdefault = ds;
2613
2614            if (sc->sw->tf != sc->tf)
2615            {
2616                ds->error("switch and default are in different finally blocks");
2617                errors = true;
2618            }
2619            if (sc->sw->isFinal)
2620            {
2621                ds->error("default statement not allowed in final switch statement");
2622                errors = true;
2623            }
2624        }
2625        else
2626        {
2627            ds->error("default not in switch statement");
2628            errors = true;
2629        }
2630        ds->statement = semantic(ds->statement, sc);
2631        if (errors || ds->statement->isErrorStatement())
2632            return setError();
2633
2634        ds->lastVar = sc->lastVar;
2635        result = ds;
2636    }
2637
2638    void visit(GotoDefaultStatement *gds)
2639    {
2640        gds->sw = sc->sw;
2641        if (!gds->sw)
2642        {
2643            gds->error("goto default not in switch statement");
2644            return setError();
2645        }
2646        if (gds->sw->isFinal)
2647        {
2648            gds->error("goto default not allowed in final switch statement");
2649            return setError();
2650        }
2651        result = gds;
2652    }
2653
2654    void visit(GotoCaseStatement *gcs)
2655    {
2656        if (!sc->sw)
2657        {
2658            gcs->error("goto case not in switch statement");
2659            return setError();
2660        }
2661
2662        if (gcs->exp)
2663        {
2664            gcs->exp = semantic(gcs->exp, sc);
2665            gcs->exp = gcs->exp->implicitCastTo(sc, sc->sw->condition->type);
2666            gcs->exp = gcs->exp->optimize(WANTvalue);
2667            if (gcs->exp->op == TOKerror)
2668                return setError();
2669        }
2670
2671        sc->sw->gotoCases.push(gcs);
2672        result = gcs;
2673    }
2674
2675    void visit(ReturnStatement *rs)
2676    {
2677        //printf("ReturnStatement::semantic() %s\n", toChars());
2678
2679        FuncDeclaration *fd = sc->parent->isFuncDeclaration();
2680
2681        if (fd->fes)
2682            fd = fd->fes->func;             // fd is now function enclosing foreach
2683
2684        TypeFunction *tf = (TypeFunction *)fd->type;
2685        assert(tf->ty == Tfunction);
2686
2687        if (rs->exp && rs->exp->op == TOKvar && ((VarExp *)rs->exp)->var == fd->vresult)
2688        {
2689            // return vresult;
2690            if (sc->fes)
2691            {
2692                assert(rs->caseDim == 0);
2693                sc->fes->cases->push(rs);
2694                result = new ReturnStatement(Loc(), new IntegerExp(sc->fes->cases->dim + 1));
2695                return;
2696            }
2697            if (fd->returnLabel)
2698            {
2699                GotoStatement *gs = new GotoStatement(rs->loc, Id::returnLabel);
2700                gs->label = fd->returnLabel;
2701                result = gs;
2702                return;
2703            }
2704
2705            if (!fd->returns)
2706                fd->returns = new ReturnStatements();
2707            fd->returns->push(rs);
2708            result = rs;
2709            return;
2710        }
2711
2712        Type *tret = tf->next;
2713        Type *tbret = tret ? tret->toBasetype() : NULL;
2714
2715        bool inferRef = (tf->isref && (fd->storage_class & STCauto));
2716        Expression *e0 = NULL;
2717
2718        bool errors = false;
2719        if (sc->flags & SCOPEcontract)
2720        {
2721            rs->error("return statements cannot be in contracts");
2722            errors = true;
2723        }
2724        if (sc->os && sc->os->tok != TOKon_scope_failure)
2725        {
2726            rs->error("return statements cannot be in %s bodies", Token::toChars(sc->os->tok));
2727            errors = true;
2728        }
2729        if (sc->tf)
2730        {
2731            rs->error("return statements cannot be in finally bodies");
2732            errors = true;
2733        }
2734
2735        if (fd->isCtorDeclaration())
2736        {
2737            if (rs->exp)
2738            {
2739                rs->error("cannot return expression from constructor");
2740                errors = true;
2741            }
2742
2743            // Constructors implicitly do:
2744            //      return this;
2745            rs->exp = new ThisExp(Loc());
2746            rs->exp->type = tret;
2747        }
2748        else if (rs->exp)
2749        {
2750            fd->hasReturnExp |= (fd->hasReturnExp & 1 ? 16 : 1);
2751
2752            FuncLiteralDeclaration *fld = fd->isFuncLiteralDeclaration();
2753            if (tret)
2754                rs->exp = inferType(rs->exp, tret);
2755            else if (fld && fld->treq)
2756                rs->exp = inferType(rs->exp, fld->treq->nextOf()->nextOf());
2757            rs->exp = semantic(rs->exp, sc);
2758
2759            // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
2760            if (rs->exp->op == TOKtype)
2761                rs->exp = resolveAliasThis(sc, rs->exp);
2762
2763            rs->exp = resolveProperties(sc, rs->exp);
2764            if (rs->exp->checkType())
2765                rs->exp = new ErrorExp();
2766            if (FuncDeclaration *f = isFuncAddress(rs->exp))
2767            {
2768                if (fd->inferRetType && f->checkForwardRef(rs->exp->loc))
2769                    rs->exp = new ErrorExp();
2770            }
2771            if (checkNonAssignmentArrayOp(rs->exp))
2772                rs->exp = new ErrorExp();
2773
2774            // Extract side-effect part
2775            rs->exp = Expression::extractLast(rs->exp, &e0);
2776            if (rs->exp->op == TOKcall)
2777                rs->exp = valueNoDtor(rs->exp);
2778
2779            if (e0)
2780                e0 = e0->optimize(WANTvalue);
2781
2782            /* Void-return function can have void typed expression
2783             * on return statement.
2784             */
2785            if ((tbret && tbret->ty == Tvoid) || rs->exp->type->ty == Tvoid)
2786            {
2787                if (rs->exp->type->ty != Tvoid)
2788                {
2789                    rs->error("cannot return non-void from void function");
2790                    errors = true;
2791
2792                    rs->exp = new CastExp(rs->loc, rs->exp, Type::tvoid);
2793                    rs->exp = semantic(rs->exp, sc);
2794                }
2795
2796                /* Replace:
2797                 *      return exp;
2798                 * with:
2799                 *      exp; return;
2800                 */
2801                e0 = Expression::combine(e0, rs->exp);
2802                rs->exp = NULL;
2803            }
2804            if (e0)
2805                e0 = checkGC(sc, e0);
2806        }
2807
2808        if (rs->exp)
2809        {
2810            if (fd->inferRetType)       // infer return type
2811            {
2812                if (!tret)
2813                {
2814                    tf->next = rs->exp->type;
2815                }
2816                else if (tret->ty != Terror && !rs->exp->type->equals(tret))
2817                {
2818                    int m1 = rs->exp->type->implicitConvTo(tret);
2819                    int m2 = tret->implicitConvTo(rs->exp->type);
2820                    //printf("exp->type = %s m2<-->m1 tret %s\n", rs->exp->type->toChars(), tret->toChars());
2821                    //printf("m1 = %d, m2 = %d\n", m1, m2);
2822
2823                    if (m1 && m2)
2824                        ;
2825                    else if (!m1 && m2)
2826                        tf->next = rs->exp->type;
2827                    else if (m1 && !m2)
2828                        ;
2829                    else if (rs->exp->op != TOKerror)
2830                    {
2831                        rs->error("mismatched function return type inference of %s and %s",
2832                                  rs->exp->type->toChars(), tret->toChars());
2833                        errors = true;
2834                        tf->next = Type::terror;
2835                    }
2836                }
2837
2838                tret = tf->next;
2839                tbret = tret->toBasetype();
2840            }
2841
2842            if (inferRef)               // deduce 'auto ref'
2843            {
2844                /* Determine "refness" of function return:
2845                 * if it's an lvalue, return by ref, else return by value
2846                 */
2847                if (rs->exp->isLvalue())
2848                {
2849                    /* May return by ref
2850                    */
2851                    if (checkReturnEscapeRef(sc, rs->exp, true))
2852                        tf->isref = false;  // return by value
2853                }
2854                else
2855                    tf->isref = false;      // return by value
2856
2857                /* The "refness" is determined by all of return statements.
2858                 * This means:
2859                 *    return 3; return x;  // ok, x can be a value
2860                 *    return x; return 3;  // ok, x can be a value
2861                 */
2862            }
2863
2864            // handle NRVO
2865            if (fd->nrvo_can && rs->exp->op == TOKvar)
2866            {
2867                VarExp *ve = (VarExp *)rs->exp;
2868                VarDeclaration *v = ve->var->isVarDeclaration();
2869
2870                if (tf->isref)
2871                {
2872                    // Function returns a reference
2873                    if (!inferRef)
2874                        fd->nrvo_can = 0;
2875                }
2876                else if (!v || v->isOut() || v->isRef())
2877                    fd->nrvo_can = 0;
2878                else if (fd->nrvo_var == NULL)
2879                {
2880                    if (!v->isDataseg() && !v->isParameter() && v->toParent2() == fd)
2881                    {
2882                        //printf("Setting nrvo to %s\n", v->toChars());
2883                        fd->nrvo_var = v;
2884                    }
2885                    else
2886                        fd->nrvo_can = 0;
2887                }
2888                else if (fd->nrvo_var != v)
2889                    fd->nrvo_can = 0;
2890            }
2891            else //if (!exp->isLvalue())    // keep NRVO-ability
2892                fd->nrvo_can = 0;
2893        }
2894        else
2895        {
2896            // handle NRVO
2897            fd->nrvo_can = 0;
2898
2899            // infer return type
2900            if (fd->inferRetType)
2901            {
2902                if (tf->next && tf->next->ty != Tvoid)
2903                {
2904                    if (tf->next->ty != Terror)
2905                    {
2906                        rs->error("mismatched function return type inference of void and %s",
2907                                  tf->next->toChars());
2908                    }
2909                    errors = true;
2910                    tf->next = Type::terror;
2911                }
2912                else
2913                    tf->next = Type::tvoid;
2914
2915                tret = tf->next;
2916                tbret = tret->toBasetype();
2917            }
2918
2919            if (inferRef)               // deduce 'auto ref'
2920                tf->isref = false;
2921
2922            if (tbret->ty != Tvoid)     // if non-void return
2923            {
2924                if (tbret->ty != Terror)
2925                    rs->error("return expression expected");
2926                errors = true;
2927            }
2928            else if (fd->isMain())
2929            {
2930                // main() returns 0, even if it returns void
2931                rs->exp = new IntegerExp(0);
2932            }
2933        }
2934
2935        // If any branches have called a ctor, but this branch hasn't, it's an error
2936        if (sc->callSuper & CSXany_ctor &&
2937            !(sc->callSuper & (CSXthis_ctor | CSXsuper_ctor)))
2938        {
2939            rs->error("return without calling constructor");
2940            errors = true;
2941        }
2942        sc->callSuper |= CSXreturn;
2943        if (sc->fieldinit)
2944        {
2945            AggregateDeclaration *ad = fd->isMember2();
2946            assert(ad);
2947            size_t dim = sc->fieldinit_dim;
2948            for (size_t i = 0; i < dim; i++)
2949            {
2950                VarDeclaration *v = ad->fields[i];
2951                bool mustInit = (v->storage_class & STCnodefaultctor ||
2952                                 v->type->needsNested());
2953                if (mustInit && !(sc->fieldinit[i] & CSXthis_ctor))
2954                {
2955                    rs->error("an earlier return statement skips field %s initialization", v->toChars());
2956                    errors = true;
2957                }
2958                sc->fieldinit[i] |= CSXreturn;
2959            }
2960        }
2961
2962        if (errors)
2963            return setError();
2964
2965        if (sc->fes)
2966        {
2967            if (!rs->exp)
2968            {
2969                // Send out "case receiver" statement to the foreach.
2970                //  return exp;
2971                Statement *s = new ReturnStatement(Loc(), rs->exp);
2972                sc->fes->cases->push(s);
2973
2974                // Immediately rewrite "this" return statement as:
2975                //  return cases->dim+1;
2976                rs->exp = new IntegerExp(sc->fes->cases->dim + 1);
2977                if (e0)
2978                {
2979                    result = new CompoundStatement(rs->loc, new ExpStatement(rs->loc, e0), rs);
2980                    return;
2981                }
2982                result = rs;
2983                return;
2984            }
2985            else
2986            {
2987                fd->buildResultVar(NULL, rs->exp->type);
2988                bool r = fd->vresult->checkNestedReference(sc, Loc());
2989                assert(!r);  // vresult should be always accessible
2990
2991                // Send out "case receiver" statement to the foreach.
2992                //  return vresult;
2993                Statement *s = new ReturnStatement(Loc(), new VarExp(Loc(), fd->vresult));
2994                sc->fes->cases->push(s);
2995
2996                // Save receiver index for the later rewriting from:
2997                //  return exp;
2998                // to:
2999                //  vresult = exp; retrun caseDim;
3000                rs->caseDim = sc->fes->cases->dim + 1;
3001            }
3002        }
3003        if (rs->exp)
3004        {
3005            if (!fd->returns)
3006                fd->returns = new ReturnStatements();
3007            fd->returns->push(rs);
3008        }
3009        if (e0)
3010        {
3011            result = new CompoundStatement(rs->loc, new ExpStatement(rs->loc, e0), rs);
3012            return;
3013        }
3014        result = rs;
3015    }
3016
3017    void visit(BreakStatement *bs)
3018    {
3019        //printf("BreakStatement::semantic()\n");
3020        // If:
3021        //  break Identifier;
3022        if (bs->ident)
3023        {
3024            bs->ident = fixupLabelName(sc, bs->ident);
3025
3026            FuncDeclaration *thisfunc = sc->func;
3027
3028            for (Scope *scx = sc; scx; scx = scx->enclosing)
3029            {
3030                if (scx->func != thisfunc)  // if in enclosing function
3031                {
3032                    if (sc->fes)            // if this is the body of a foreach
3033                    {
3034                        /* Post this statement to the fes, and replace
3035                         * it with a return value that caller will put into
3036                         * a switch. Caller will figure out where the break
3037                         * label actually is.
3038                         * Case numbers start with 2, not 0, as 0 is continue
3039                         * and 1 is break.
3040                         */
3041                        sc->fes->cases->push(bs);
3042                        result = new ReturnStatement(Loc(), new IntegerExp(sc->fes->cases->dim + 1));
3043                        return;
3044                    }
3045                    break;                  // can't break to it
3046                }
3047
3048                LabelStatement *ls = scx->slabel;
3049                if (ls && ls->ident == bs->ident)
3050                {
3051                    Statement *s = ls->statement;
3052
3053                    if (!s || !s->hasBreak())
3054                        bs->error("label '%s' has no break", bs->ident->toChars());
3055                    else if (ls->tf != sc->tf)
3056                        bs->error("cannot break out of finally block");
3057                    else
3058                    {
3059                        ls->breaks = true;
3060                        result = bs;
3061                        return;
3062                    }
3063                    return setError();
3064                }
3065            }
3066            bs->error("enclosing label '%s' for break not found", bs->ident->toChars());
3067            return setError();
3068        }
3069        else if (!sc->sbreak)
3070        {
3071            if (sc->os && sc->os->tok != TOKon_scope_failure)
3072            {
3073                bs->error("break is not inside %s bodies", Token::toChars(sc->os->tok));
3074            }
3075            else if (sc->fes)
3076            {
3077                // Replace break; with return 1;
3078                result = new ReturnStatement(Loc(), new IntegerExp(1));
3079                return;
3080            }
3081            else
3082                bs->error("break is not inside a loop or switch");
3083            return setError();
3084        }
3085        else if (sc->sbreak->isForwardingStatement())
3086        {
3087            bs->error("must use labeled `break` within `static foreach`");
3088        }
3089        result = bs;
3090    }
3091
3092    void visit(ContinueStatement *cs)
3093    {
3094        //printf("ContinueStatement::semantic() %p\n", cs);
3095        if (cs->ident)
3096        {
3097            cs->ident = fixupLabelName(sc, cs->ident);
3098
3099            Scope *scx;
3100            FuncDeclaration *thisfunc = sc->func;
3101
3102            for (scx = sc; scx; scx = scx->enclosing)
3103            {
3104                LabelStatement *ls;
3105
3106                if (scx->func != thisfunc)  // if in enclosing function
3107                {
3108                    if (sc->fes)            // if this is the body of a foreach
3109                    {
3110                        for (; scx; scx = scx->enclosing)
3111                        {
3112                            ls = scx->slabel;
3113                            if (ls && ls->ident == cs->ident && ls->statement == sc->fes)
3114                            {
3115                                // Replace continue ident; with return 0;
3116                                result = new ReturnStatement(Loc(), new IntegerExp(0));
3117                                return;
3118                            }
3119                        }
3120
3121                        /* Post this statement to the fes, and replace
3122                         * it with a return value that caller will put into
3123                         * a switch. Caller will figure out where the break
3124                         * label actually is.
3125                         * Case numbers start with 2, not 0, as 0 is continue
3126                         * and 1 is break.
3127                         */
3128                        sc->fes->cases->push(cs);
3129                        result = new ReturnStatement(Loc(), new IntegerExp(sc->fes->cases->dim + 1));
3130                        return;
3131                    }
3132                    break;                  // can't continue to it
3133                }
3134
3135                ls = scx->slabel;
3136                if (ls && ls->ident == cs->ident)
3137                {
3138                    Statement *s = ls->statement;
3139
3140                    if (!s || !s->hasContinue())
3141                        cs->error("label '%s' has no continue", cs->ident->toChars());
3142                    else if (ls->tf != sc->tf)
3143                        cs->error("cannot continue out of finally block");
3144                    else
3145                    {
3146                        result = cs;
3147                        return;
3148                    }
3149                    return setError();
3150                }
3151            }
3152            cs->error("enclosing label '%s' for continue not found", cs->ident->toChars());
3153            return setError();
3154        }
3155        else if (!sc->scontinue)
3156        {
3157            if (sc->os && sc->os->tok != TOKon_scope_failure)
3158            {
3159                cs->error("continue is not inside %s bodies", Token::toChars(sc->os->tok));
3160            }
3161            else if (sc->fes)
3162            {
3163                // Replace continue; with return 0;
3164                result = new ReturnStatement(Loc(), new IntegerExp(0));
3165                return;
3166            }
3167            else
3168                cs->error("continue is not inside a loop");
3169            return setError();
3170        }
3171        else if (sc->scontinue->isForwardingStatement())
3172        {
3173            cs->error("must use labeled `continue` within `static foreach`");
3174        }
3175        result = cs;
3176    }
3177
3178    void visit(SynchronizedStatement *ss)
3179    {
3180        if (ss->exp)
3181        {
3182            ss->exp = semantic(ss->exp, sc);
3183            ss->exp = resolveProperties(sc, ss->exp);
3184            ss->exp = ss->exp->optimize(WANTvalue);
3185            ss->exp = checkGC(sc, ss->exp);
3186            if (ss->exp->op == TOKerror)
3187                goto Lbody;
3188            ClassDeclaration *cd = ss->exp->type->isClassHandle();
3189            if (!cd)
3190            {
3191                ss->error("can only synchronize on class objects, not '%s'", ss->exp->type->toChars());
3192                return setError();
3193            }
3194            else if (cd->isInterfaceDeclaration())
3195            {
3196                /* Cast the interface to an object, as the object has the monitor,
3197                 * not the interface.
3198                 */
3199                if (!ClassDeclaration::object)
3200                {
3201                    ss->error("missing or corrupt object.d");
3202                    fatal();
3203                }
3204
3205                Type *t = ClassDeclaration::object->type;
3206                t = t->semantic(Loc(), sc)->toBasetype();
3207                assert(t->ty == Tclass);
3208
3209                ss->exp = new CastExp(ss->loc, ss->exp, t);
3210                ss->exp = semantic(ss->exp, sc);
3211            }
3212
3213            /* Rewrite as:
3214             *  auto tmp = exp;
3215             *  _d_monitorenter(tmp);
3216             *  try { body } finally { _d_monitorexit(tmp); }
3217             */
3218            VarDeclaration *tmp = copyToTemp(0, "__sync", ss->exp);
3219            tmp->semantic(sc);
3220
3221            Statements *cs = new Statements();
3222            cs->push(new ExpStatement(ss->loc, tmp));
3223
3224            Parameters* args = new Parameters;
3225            args->push(new Parameter(0, ClassDeclaration::object->type, NULL, NULL));
3226
3227            FuncDeclaration *fdenter = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorenter);
3228            Expression *e = new CallExp(ss->loc, new VarExp(ss->loc, fdenter, false), new VarExp(ss->loc, tmp));
3229            e->type = Type::tvoid;                  // do not run semantic on e
3230            cs->push(new ExpStatement(ss->loc, e));
3231
3232            FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorexit);
3233            e = new CallExp(ss->loc, new VarExp(ss->loc, fdexit, false), new VarExp(ss->loc, tmp));
3234            e->type = Type::tvoid;                  // do not run semantic on e
3235            Statement *s = new ExpStatement(ss->loc, e);
3236            s = new TryFinallyStatement(ss->loc, ss->_body, s);
3237            cs->push(s);
3238
3239            s = new CompoundStatement(ss->loc, cs);
3240            result = semantic(s, sc);
3241            return;
3242        }
3243        else
3244        {
3245            /* Generate our own critical section, then rewrite as:
3246             *  __gshared byte[CriticalSection.sizeof] critsec;
3247             *  _d_criticalenter(critsec.ptr);
3248             *  try { body } finally { _d_criticalexit(critsec.ptr); }
3249             */
3250            Identifier *id = Identifier::generateId("__critsec");
3251            Type *t = Type::tint8->sarrayOf(Target::ptrsize + Target::critsecsize());
3252            VarDeclaration *tmp = new VarDeclaration(ss->loc, t, id, NULL);
3253            tmp->storage_class |= STCtemp | STCgshared | STCstatic;
3254
3255            Statements *cs = new Statements();
3256            cs->push(new ExpStatement(ss->loc, tmp));
3257
3258            /* This is just a dummy variable for "goto skips declaration" error.
3259             * Backend optimizer could remove this unused variable.
3260             */
3261            VarDeclaration *v = new VarDeclaration(ss->loc, Type::tvoidptr, Identifier::generateId("__sync"), NULL);
3262            v->semantic(sc);
3263            cs->push(new ExpStatement(ss->loc, v));
3264
3265            Parameters* args = new Parameters;
3266            args->push(new Parameter(0, t->pointerTo(), NULL, NULL));
3267
3268            FuncDeclaration *fdenter = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalenter, STCnothrow);
3269            Expression *e = new DotIdExp(ss->loc, new VarExp(ss->loc, tmp), Id::ptr);
3270            e = semantic(e, sc);
3271            e = new CallExp(ss->loc, new VarExp(ss->loc, fdenter, false), e);
3272            e->type = Type::tvoid;                  // do not run semantic on e
3273            cs->push(new ExpStatement(ss->loc, e));
3274
3275            FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalexit, STCnothrow);
3276            e = new DotIdExp(ss->loc, new VarExp(ss->loc, tmp), Id::ptr);
3277            e = semantic(e, sc);
3278            e = new CallExp(ss->loc, new VarExp(ss->loc, fdexit, false), e);
3279            e->type = Type::tvoid;                  // do not run semantic on e
3280            Statement *s = new ExpStatement(ss->loc, e);
3281            s = new TryFinallyStatement(ss->loc, ss->_body, s);
3282            cs->push(s);
3283
3284            s = new CompoundStatement(ss->loc, cs);
3285            result = semantic(s, sc);
3286            return;
3287        }
3288    Lbody:
3289        if (ss->_body)
3290            ss->_body = semantic(ss->_body, sc);
3291        if (ss->_body && ss->_body->isErrorStatement())
3292        {
3293            result = ss->_body;
3294            return;
3295        }
3296        result = ss;
3297    }
3298
3299    void visit(WithStatement *ws)
3300    {
3301        ScopeDsymbol *sym;
3302        Initializer *init;
3303
3304        //printf("WithStatement::semantic()\n");
3305        ws->exp = semantic(ws->exp, sc);
3306        ws->exp = resolveProperties(sc, ws->exp);
3307        ws->exp = ws->exp->optimize(WANTvalue);
3308        ws->exp = checkGC(sc, ws->exp);
3309        if (ws->exp->op == TOKerror)
3310            return setError();
3311        if (ws->exp->op == TOKscope)
3312        {
3313            sym = new WithScopeSymbol(ws);
3314            sym->parent = sc->scopesym;
3315            sym->endlinnum = ws->endloc.linnum;
3316        }
3317        else if (ws->exp->op == TOKtype)
3318        {
3319            Dsymbol *s = ((TypeExp *)ws->exp)->type->toDsymbol(sc);
3320            if (!s || !s->isScopeDsymbol())
3321            {
3322                ws->error("with type %s has no members", ws->exp->toChars());
3323                return setError();
3324            }
3325            sym = new WithScopeSymbol(ws);
3326            sym->parent = sc->scopesym;
3327            sym->endlinnum = ws->endloc.linnum;
3328        }
3329        else
3330        {
3331            Type *t = ws->exp->type->toBasetype();
3332
3333            Expression *olde = ws->exp;
3334            if (t->ty == Tpointer)
3335            {
3336                ws->exp = new PtrExp(ws->loc, ws->exp);
3337                ws->exp = semantic(ws->exp, sc);
3338                t = ws->exp->type->toBasetype();
3339            }
3340
3341            assert(t);
3342            t = t->toBasetype();
3343            if (t->isClassHandle())
3344            {
3345                init = new ExpInitializer(ws->loc, ws->exp);
3346                ws->wthis = new VarDeclaration(ws->loc, ws->exp->type, Id::withSym, init);
3347                ws->wthis->semantic(sc);
3348
3349                sym = new WithScopeSymbol(ws);
3350                sym->parent = sc->scopesym;
3351                sym->endlinnum = ws->endloc.linnum;
3352            }
3353            else if (t->ty == Tstruct)
3354            {
3355                if (!ws->exp->isLvalue())
3356                {
3357                    /* Re-write to
3358                     * {
3359                     *   auto __withtmp = exp
3360                     *   with(__withtmp)
3361                     *   {
3362                     *     ...
3363                     *   }
3364                     * }
3365                     */
3366                    VarDeclaration *tmp = copyToTemp(0, "__withtmp", ws->exp);
3367                    tmp->semantic(sc);
3368                    ExpStatement *es = new ExpStatement(ws->loc, tmp);
3369                    ws->exp = new VarExp(ws->loc, tmp);
3370                    Statement *ss = new ScopeStatement(ws->loc, new CompoundStatement(ws->loc, es, ws), ws->endloc);
3371                    result = semantic(ss, sc);
3372                    return;
3373                }
3374                Expression *e = ws->exp->addressOf();
3375                init = new ExpInitializer(ws->loc, e);
3376                ws->wthis = new VarDeclaration(ws->loc, e->type, Id::withSym, init);
3377                ws->wthis->semantic(sc);
3378                sym = new WithScopeSymbol(ws);
3379                // Need to set the scope to make use of resolveAliasThis
3380                sym->setScope(sc);
3381                sym->parent = sc->scopesym;
3382                sym->endlinnum = ws->endloc.linnum;
3383            }
3384            else
3385            {
3386                ws->error("with expressions must be aggregate types or pointers to them, not '%s'", olde->type->toChars());
3387                return setError();
3388            }
3389        }
3390
3391        if (ws->_body)
3392        {
3393            sym->_scope = sc;
3394            sc = sc->push(sym);
3395            sc->insert(sym);
3396            ws->_body = semantic(ws->_body, sc);
3397            sc->pop();
3398            if (ws->_body && ws->_body->isErrorStatement())
3399            {
3400                result = ws->_body;
3401                return;
3402            }
3403        }
3404
3405        result = ws;
3406    }
3407
3408    void visit(TryCatchStatement *tcs)
3409    {
3410        if (!global.params.useExceptions)
3411        {
3412            tcs->error("Cannot use try-catch statements with -betterC");
3413            return setError();
3414        }
3415
3416        if (!ClassDeclaration::throwable)
3417        {
3418            tcs->error("Cannot use try-catch statements because `object.Throwable` was not declared");
3419            return setError();
3420        }
3421
3422        unsigned flags = 0;
3423        const unsigned FLAGcpp = 1;
3424        const unsigned FLAGd = 2;
3425
3426        tcs->_body = semanticScope(tcs->_body, sc, NULL, NULL);
3427        assert(tcs->_body);
3428
3429        /* Even if body is empty, still do semantic analysis on catches
3430        */
3431        bool catchErrors = false;
3432        for (size_t i = 0; i < tcs->catches->dim; i++)
3433        {
3434            Catch *c = (*tcs->catches)[i];
3435            semantic(c, sc);
3436            if (c->errors)
3437            {
3438                catchErrors = true;
3439                continue;
3440            }
3441            ClassDeclaration *cd = c->type->toBasetype()->isClassHandle();
3442            flags |= cd->isCPPclass() ? FLAGcpp : FLAGd;
3443
3444            // Determine if current catch 'hides' any previous catches
3445            for (size_t j = 0; j < i; j++)
3446            {
3447                Catch *cj = (*tcs->catches)[j];
3448                const char *si = c->loc.toChars();
3449                const char *sj = cj->loc.toChars();
3450
3451                if (c->type->toBasetype()->implicitConvTo(cj->type->toBasetype()))
3452                {
3453                    tcs->error("catch at %s hides catch at %s", sj, si);
3454                    catchErrors = true;
3455                }
3456            }
3457        }
3458
3459        if (sc->func)
3460        {
3461            if (flags == (FLAGcpp | FLAGd))
3462            {
3463                tcs->error("cannot mix catching D and C++ exceptions in the same try-catch");
3464                catchErrors = true;
3465            }
3466        }
3467
3468        if (catchErrors)
3469            return setError();
3470
3471        if (tcs->_body->isErrorStatement())
3472        {
3473            result = tcs->_body;
3474            return;
3475        }
3476
3477        /* If the try body never throws, we can eliminate any catches
3478         * of recoverable exceptions.
3479         */
3480
3481        if (!(blockExit(tcs->_body, sc->func, false) & BEthrow) && ClassDeclaration::exception)
3482        {
3483            for (size_t i = 0; i < tcs->catches->dim; i++)
3484            {
3485                Catch *c = (*tcs->catches)[i];
3486
3487                /* If catch exception type is derived from Exception
3488                */
3489                if (c->type->toBasetype()->implicitConvTo(ClassDeclaration::exception->type) &&
3490                    (!c->handler || !c->handler->comeFrom()))
3491                {
3492                    // Remove c from the array of catches
3493                    tcs->catches->remove(i);
3494                    --i;
3495                }
3496            }
3497        }
3498
3499        if (tcs->catches->dim == 0)
3500        {
3501            result = tcs->_body->hasCode() ? tcs->_body : NULL;
3502            return;
3503        }
3504
3505        result = tcs;
3506    }
3507
3508    void visit(TryFinallyStatement *tfs)
3509    {
3510        //printf("TryFinallyStatement::semantic()\n");
3511        tfs->_body = semantic(tfs->_body, sc);
3512        sc = sc->push();
3513        sc->tf = tfs;
3514        sc->sbreak = NULL;
3515        sc->scontinue = NULL;       // no break or continue out of finally block
3516        tfs->finalbody = semanticNoScope(tfs->finalbody, sc);
3517        sc->pop();
3518
3519        if (!tfs->_body)
3520        {
3521            result = tfs->finalbody;
3522            return;
3523        }
3524
3525        if (!tfs->finalbody)
3526        {
3527            result = tfs->_body;
3528            return;
3529        }
3530
3531        int blockexit = blockExit(tfs->_body, sc->func, false);
3532
3533        // if not worrying about exceptions
3534        if (!(global.params.useExceptions && ClassDeclaration::throwable))
3535            blockexit &= ~BEthrow;            // don't worry about paths that otherwise may throw
3536
3537        // Don't care about paths that halt, either
3538        if ((blockexit & ~BEhalt) == BEfallthru)
3539        {
3540            result = new CompoundStatement(tfs->loc, tfs->_body, tfs->finalbody);
3541            return;
3542        }
3543        result = tfs;
3544    }
3545
3546    void visit(OnScopeStatement *oss)
3547    {
3548        if (oss->tok != TOKon_scope_exit)
3549        {
3550            // scope(success) and scope(failure) are rewritten to try-catch(-finally) statement,
3551            // so the generated catch block cannot be placed in finally block.
3552            // See also Catch::semantic.
3553            if (sc->os && sc->os->tok != TOKon_scope_failure)
3554            {
3555                // If enclosing is scope(success) or scope(exit), this will be placed in finally block.
3556                oss->error("cannot put %s statement inside %s", Token::toChars(oss->tok), Token::toChars(sc->os->tok));
3557                return setError();
3558            }
3559            if (sc->tf)
3560            {
3561                oss->error("cannot put %s statement inside finally block", Token::toChars(oss->tok));
3562                return setError();
3563            }
3564        }
3565
3566        sc = sc->push();
3567        sc->tf = NULL;
3568        sc->os = oss;
3569        if (oss->tok != TOKon_scope_failure)
3570        {
3571            // Jump out from scope(failure) block is allowed.
3572            sc->sbreak = NULL;
3573            sc->scontinue = NULL;
3574        }
3575        oss->statement = semanticNoScope(oss->statement, sc);
3576        sc->pop();
3577
3578        if (!oss->statement || oss->statement->isErrorStatement())
3579        {
3580            result = oss->statement;
3581            return;
3582        }
3583        result = oss;
3584    }
3585
3586    void visit(ThrowStatement *ts)
3587    {
3588        //printf("ThrowStatement::semantic()\n");
3589
3590        if (!global.params.useExceptions)
3591        {
3592            ts->error("Cannot use `throw` statements with -betterC");
3593            return setError();
3594        }
3595
3596        if (!ClassDeclaration::throwable)
3597        {
3598            ts->error("Cannot use `throw` statements because `object.Throwable` was not declared");
3599            return setError();
3600        }
3601
3602        FuncDeclaration *fd = sc->parent->isFuncDeclaration();
3603        fd->hasReturnExp |= 2;
3604
3605        ts->exp = semantic(ts->exp, sc);
3606        ts->exp = resolveProperties(sc, ts->exp);
3607        ts->exp = checkGC(sc, ts->exp);
3608        if (ts->exp->op == TOKerror)
3609            return setError();
3610
3611        checkThrowEscape(sc, ts->exp, false);
3612
3613        ClassDeclaration *cd = ts->exp->type->toBasetype()->isClassHandle();
3614        if (!cd || ((cd != ClassDeclaration::throwable) && !ClassDeclaration::throwable->isBaseOf(cd, NULL)))
3615        {
3616            ts->error("can only throw class objects derived from Throwable, not type %s", ts->exp->type->toChars());
3617            return setError();
3618        }
3619
3620        result = ts;
3621    }
3622
3623    void visit(DebugStatement *ds)
3624    {
3625        if (ds->statement)
3626        {
3627            sc = sc->push();
3628            sc->flags |= SCOPEdebug;
3629            ds->statement = semantic(ds->statement, sc);
3630            sc->pop();
3631        }
3632        result = ds->statement;
3633    }
3634
3635    void visit(GotoStatement *gs)
3636    {
3637        //printf("GotoStatement::semantic()\n");
3638        FuncDeclaration *fd = sc->func;
3639
3640        gs->ident = fixupLabelName(sc, gs->ident);
3641        gs->label = fd->searchLabel(gs->ident);
3642        gs->tf = sc->tf;
3643        gs->os = sc->os;
3644        gs->lastVar = sc->lastVar;
3645
3646        if (!gs->label->statement && sc->fes)
3647        {
3648            /* Either the goto label is forward referenced or it
3649             * is in the function that the enclosing foreach is in.
3650             * Can't know yet, so wrap the goto in a scope statement
3651             * so we can patch it later, and add it to a 'look at this later'
3652             * list.
3653             */
3654            ScopeStatement *ss = new ScopeStatement(gs->loc, gs, gs->loc);
3655            sc->fes->gotos->push(ss);       // 'look at this later' list
3656            result = ss;
3657            return;
3658        }
3659
3660        // Add to fwdref list to check later
3661        if (!gs->label->statement)
3662        {
3663            if (!fd->gotos)
3664                fd->gotos = new GotoStatements();
3665            fd->gotos->push(gs);
3666        }
3667        else if (gs->checkLabel())
3668            return setError();
3669
3670        result = gs;
3671    }
3672
3673    void visit(LabelStatement *ls)
3674    {
3675        //printf("LabelStatement::semantic()\n");
3676        FuncDeclaration *fd = sc->parent->isFuncDeclaration();
3677
3678        ls->ident = fixupLabelName(sc, ls->ident);
3679        ls->tf = sc->tf;
3680        ls->os = sc->os;
3681        ls->lastVar = sc->lastVar;
3682
3683        LabelDsymbol *ls2 = fd->searchLabel(ls->ident);
3684        if (ls2->statement)
3685        {
3686            ls->error("label '%s' already defined", ls2->toChars());
3687            return setError();
3688        }
3689        else
3690            ls2->statement = ls;
3691
3692        sc = sc->push();
3693        sc->scopesym = sc->enclosing->scopesym;
3694        sc->callSuper |= CSXlabel;
3695        if (sc->fieldinit)
3696        {
3697            size_t dim = sc->fieldinit_dim;
3698            for (size_t i = 0; i < dim; i++)
3699                sc->fieldinit[i] |= CSXlabel;
3700        }
3701        sc->slabel = ls;
3702        if (ls->statement)
3703            ls->statement = semantic(ls->statement, sc);
3704        sc->pop();
3705
3706        result = ls;
3707    }
3708
3709    void visit(AsmStatement *s)
3710    {
3711        result = asmSemantic(s, sc);
3712    }
3713
3714    void visit(CompoundAsmStatement *cas)
3715    {
3716        // Apply postfix attributes of the asm block to each statement.
3717        sc = sc->push();
3718        sc->stc |= cas->stc;
3719
3720        for (size_t i = 0; i < cas->statements->dim; i++)
3721        {
3722            Statement *s = (*cas->statements)[i];
3723            (*cas->statements)[i] = s ? semantic(s, sc) : NULL;
3724        }
3725
3726        assert(sc->func);
3727        // use setImpure/setGC when the deprecation cycle is over
3728        PURE purity;
3729        if (!(cas->stc & STCpure) && (purity = sc->func->isPureBypassingInference()) != PUREimpure && purity != PUREfwdref)
3730            cas->deprecation("asm statement is assumed to be impure - mark it with 'pure' if it is not");
3731        if (!(cas->stc & STCnogc) && sc->func->isNogcBypassingInference())
3732            cas->deprecation("asm statement is assumed to use the GC - mark it with '@nogc' if it does not");
3733        if (!(cas->stc & (STCtrusted|STCsafe)) && sc->func->setUnsafe())
3734            cas->error("asm statement is assumed to be @system - mark it with '@trusted' if it is not");
3735
3736        sc->pop();
3737        result = cas;
3738    }
3739
3740    void visit(ImportStatement *imps)
3741    {
3742        for (size_t i = 0; i < imps->imports->dim; i++)
3743        {
3744            Import *s = (*imps->imports)[i]->isImport();
3745            assert(!s->aliasdecls.dim);
3746            for (size_t j = 0; j < s->names.dim; j++)
3747            {
3748                Identifier *name = s->names[j];
3749                Identifier *alias = s->aliases[j];
3750
3751                if (!alias)
3752                    alias = name;
3753
3754                TypeIdentifier *tname = new TypeIdentifier(s->loc, name);
3755                AliasDeclaration *ad = new AliasDeclaration(s->loc, alias, tname);
3756                ad->_import = s;
3757                s->aliasdecls.push(ad);
3758            }
3759
3760            s->semantic(sc);
3761            // https://issues.dlang.org/show_bug.cgi?id=19942
3762            // If the module that's being imported doesn't exist, don't add it to the symbol table
3763            // for the current scope.
3764            if (s->mod != NULL)
3765            {
3766                Module::addDeferredSemantic2(s);     // Bugzilla 14666
3767                sc->insert(s);
3768
3769                for (size_t j = 0; j < s->aliasdecls.dim; j++)
3770                {
3771                    sc->insert(s->aliasdecls[j]);
3772                }
3773            }
3774        }
3775        result = imps;
3776    }
3777};
3778
3779Statement *semantic(Statement *s, Scope *sc)
3780{
3781    StatementSemanticVisitor v = StatementSemanticVisitor(sc);
3782    s->accept(&v);
3783    return v.result;
3784}
3785
3786void semantic(Catch *c, Scope *sc)
3787{
3788    //printf("Catch::semantic(%s)\n", ident->toChars());
3789
3790    if (sc->os && sc->os->tok != TOKon_scope_failure)
3791    {
3792        // If enclosing is scope(success) or scope(exit), this will be placed in finally block.
3793        error(c->loc, "cannot put catch statement inside %s", Token::toChars(sc->os->tok));
3794        c->errors = true;
3795    }
3796    if (sc->tf)
3797    {
3798        /* This is because the _d_local_unwind() gets the stack munged
3799         * up on this. The workaround is to place any try-catches into
3800         * a separate function, and call that.
3801         * To fix, have the compiler automatically convert the finally
3802         * body into a nested function.
3803         */
3804        error(c->loc, "cannot put catch statement inside finally block");
3805        c->errors = true;
3806    }
3807
3808    ScopeDsymbol *sym = new ScopeDsymbol();
3809    sym->parent = sc->scopesym;
3810    sc = sc->push(sym);
3811
3812    if (!c->type)
3813    {
3814        deprecation(c->loc, "catch statement without an exception specification is deprecated; use catch(Throwable) for old behavior");
3815
3816        // reference .object.Throwable
3817        c->type = getThrowable();
3818    }
3819    c->type = c->type->semantic(c->loc, sc);
3820    if (c->type == Type::terror)
3821        c->errors = true;
3822    else
3823    {
3824        ClassDeclaration *cd = c->type->toBasetype()->isClassHandle();
3825        if (!cd)
3826        {
3827            error(c->loc, "can only catch class objects, not '%s'", c->type->toChars());
3828            c->errors = true;
3829        }
3830        else if (cd->isCPPclass())
3831        {
3832            if (!Target::cppExceptions)
3833            {
3834                error(c->loc, "catching C++ class objects not supported for this target");
3835                c->errors = true;
3836            }
3837            if (sc->func && !sc->intypeof && !c->internalCatch && sc->func->setUnsafe())
3838            {
3839                error(c->loc, "cannot catch C++ class objects in @safe code");
3840                c->errors = true;
3841            }
3842        }
3843        else if (cd != ClassDeclaration::throwable && !ClassDeclaration::throwable->isBaseOf(cd, NULL))
3844        {
3845            error(c->loc, "can only catch class objects derived from Throwable, not '%s'", c->type->toChars());
3846            c->errors = true;
3847        }
3848        else if (sc->func && !sc->intypeof && !c->internalCatch &&
3849                 cd != ClassDeclaration::exception && !ClassDeclaration::exception->isBaseOf(cd, NULL) &&
3850                 sc->func->setUnsafe())
3851        {
3852            error(c->loc, "can only catch class objects derived from Exception in @safe code, not '%s'", c->type->toChars());
3853            c->errors = true;
3854        }
3855
3856        if (c->ident)
3857        {
3858            c->var = new VarDeclaration(c->loc, c->type, c->ident, NULL);
3859            c->var->semantic(sc);
3860            sc->insert(c->var);
3861        }
3862        c->handler = semantic(c->handler, sc);
3863        if (c->handler && c->handler->isErrorStatement())
3864            c->errors = true;
3865    }
3866    sc->pop();
3867}
3868
3869Statement *semanticNoScope(Statement *s, Scope *sc)
3870{
3871    //printf("Statement::semanticNoScope() %s\n", toChars());
3872    if (!s->isCompoundStatement() && !s->isScopeStatement())
3873    {
3874        s = new CompoundStatement(s->loc, s); // so scopeCode() gets called
3875    }
3876    s = semantic(s, sc);
3877    return s;
3878}
3879
3880// Same as semanticNoScope(), but do create a new scope
3881Statement *semanticScope(Statement *s, Scope *sc, Statement *sbreak, Statement *scontinue)
3882{
3883    ScopeDsymbol *sym = new ScopeDsymbol();
3884    sym->parent = sc->scopesym;
3885    Scope *scd = sc->push(sym);
3886    if (sbreak)
3887        scd->sbreak = sbreak;
3888    if (scontinue)
3889        scd->scontinue = scontinue;
3890    s = semanticNoScope(s, scd);
3891    scd->pop();
3892    return s;
3893}
3894
3895/*******************
3896 * See StatementSemanticVisitor.makeTupleForeach.  This is a simple
3897 * wrapper that returns the generated statements/declarations.
3898 */
3899Statement *makeTupleForeachStatic(Scope *sc, ForeachStatement *fs, bool needExpansion)
3900{
3901    StatementSemanticVisitor v = StatementSemanticVisitor(sc);
3902    v.makeTupleForeachStatic(fs, needExpansion);
3903    return v.result;
3904}
3905
3906Dsymbols *makeTupleForeachStaticDecl(Scope *sc, ForeachStatement *fs, Dsymbols *dbody, bool needExpansion)
3907{
3908    StatementSemanticVisitor v = StatementSemanticVisitor(sc);
3909    return v.makeTupleForeachStaticDecl(fs, dbody, needExpansion);
3910}
3911