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 
32 StorageClass mergeFuncAttrs(StorageClass s1, FuncDeclaration *f);
33 bool checkReturnEscapeRef(Scope *sc, Expression *e, bool gag);
34 bool checkThrowEscape(Scope *sc, Expression *e, bool gag);
35 LabelStatement *checkLabeledLoop(Scope *sc, Statement *statement);
36 Identifier *fixupLabelName(Scope *sc, Identifier *ident);
37 FuncDeclaration *isFuncAddress(Expression *e, bool *hasOverloads = NULL);
38 VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e);
39 Expression *checkAssignmentAsCondition(Expression *e);
40 TypeIdentifier *getThrowable();
41 
42 Expression *semantic(Expression *e, Scope *sc);
43 Statement *semantic(Statement *s, Scope *sc);
44 void semantic(Catch *c, Scope *sc);
45 Statement *semanticNoScope(Statement *s, Scope *sc);
46 Statement *semanticScope(Statement *s, Scope *sc, Statement *sbreak, Statement *scontinue);
47 int blockExit(Statement *s, FuncDeclaration *func, bool mustNotThrow);
48 
49 class StatementSemanticVisitor : public Visitor
50 {
51 public:
52     Statement *result;
53     Scope *sc;
54 
StatementSemanticVisitor(Scope * sc)55     StatementSemanticVisitor(Scope *sc)
56     {
57         this->result = NULL;
58         this->sc = sc;
59     }
60 
61 private:
setError()62     void setError()
63     {
64         result = new ErrorStatement();
65     }
66 
67 public:
visit(Statement * s)68     void visit(Statement *s)
69     {
70         result = s;
71     }
72 
visit(ErrorStatement * s)73     void visit(ErrorStatement *s)
74     {
75         result = s;
76     }
77 
visit(PeelStatement * s)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 
visit(ExpStatement * s)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 
visit(CompileStatement * cs)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 
visit(CompoundStatement * cs)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 
visit(UnrolledLoopStatement * uls)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 
visit(ScopeStatement * ss)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 
visit(ForwardingStatement * ss)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 
visit(WhileStatement * ws)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 
visit(DoStatement * ds)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 
visit(ForStatement * fs)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      */
declareVariable(ForeachStatement * fs,Type * paramtype,TupleExp * te,bool needExpansion,bool isStatic,Statements * statements,Dsymbols * declarations,StorageClass storageClass,Type * type,Identifier * ident,Expression * e,Type * t)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                 type = e->type;
572                 if (paramtype)
573                     type = paramtype;
574                 Initializer *ie = new ExpInitializer(Loc(), e);
575                 VarDeclaration *v = new VarDeclaration(loc, type, ident, ie);
576                 if (storageClass & STCref)
577                     v->storage_class |= STCref | STCforeach;
578                 if (isStatic || storageClass & STCmanifest || e->isConst() ||
579                     e->op == TOKstring ||
580                     e->op == TOKstructliteral ||
581                     e->op == TOKarrayliteral)
582                 {
583                     if (v->storage_class & STCref)
584                     {
585                         if (!isStatic || !needExpansion)
586                         {
587                             fs->error("constant value %s cannot be ref", ie->toChars());
588                         }
589                         else
590                         {
591                             fs->error("constant value %s cannot be ref", ident->toChars());
592                         }
593                         return false;
594                     }
595                     else
596                         v->storage_class |= STCmanifest;
597                 }
598                 var = v;
599             }
600         }
601         else
602         {
603             var = new AliasDeclaration(loc, ident, t);
604             if (paramtype)
605             {
606                 fs->error("cannot specify element type for symbol %s", fs->toChars());
607                 return false;
608             }
609         }
610         if (isStatic)
611             var->storage_class |= STClocal;
612         if (statements)
613             statements->push(new ExpStatement(loc, var));
614         else if (declarations)
615             declarations->push(var);
616         else
617             assert(0);
618         return true;
619     }
620 
makeTupleForeachBody(ForeachStatement * fs,size_t k,Type * paramtype,TupleExp * te,TypeTuple * tuple,bool needExpansion,bool isStatic,bool isDecl,Statements * statements,Dsymbols * declarations,Dsymbols * dbody)621     bool makeTupleForeachBody(ForeachStatement *fs, size_t k,
622         Type *paramtype, TupleExp *te, TypeTuple *tuple,
623         bool needExpansion, bool isStatic, bool isDecl,
624         Statements *statements, Dsymbols *declarations, Dsymbols *dbody)
625     {
626         Loc loc = fs->loc;
627         Expression *e = NULL;
628         Type *t = NULL;
629         if (te)
630             e = (*te->exps)[k];
631         else
632             t = Parameter::getNth(tuple->arguments, k)->type;
633         Parameter *p = (*fs->parameters)[0];
634         Statements *stmts = (isDecl) ? NULL : new Statements();
635         Dsymbols *decls = (isDecl) ? new Dsymbols() : NULL;
636 
637         size_t dim = fs->parameters->dim;
638         if (!needExpansion && dim == 2)
639         {
640             // Declare key
641             if (p->storageClass & (STCout | STCref | STClazy))
642             {
643                 fs->error("no storage class for key %s", p->ident->toChars());
644                 return false;
645             }
646             if (isStatic)
647             {
648                 if (!p->type)
649                 {
650                     p->type = Type::tsize_t;
651                 }
652             }
653             p->type = p->type->semantic(loc, sc);
654             TY keyty = p->type->ty;
655             if (keyty != Tint32 && keyty != Tuns32)
656             {
657                 if (global.params.isLP64)
658                 {
659                     if (keyty != Tint64 && keyty != Tuns64)
660                     {
661                         fs->error("foreach: key type must be int or uint, long or ulong, not %s", p->type->toChars());
662                         return false;
663                     }
664                 }
665                 else
666                 {
667                     fs->error("foreach: key type must be int or uint, not %s", p->type->toChars());
668                     return false;
669                 }
670             }
671             Initializer *ie = new ExpInitializer(Loc(), new IntegerExp(k));
672             VarDeclaration *var = new VarDeclaration(loc, p->type, p->ident, ie);
673             var->storage_class |= STCmanifest;
674             if (isStatic)
675                 var->storage_class |= STClocal;
676             if (!isDecl)
677                 stmts->push(new ExpStatement(loc, var));
678             else
679                 decls->push(var);
680             p = (*fs->parameters)[1];  // value
681         }
682 
683         if (!isStatic || !needExpansion)
684         {
685             // Declare value
686             if (!declareVariable(fs, paramtype, te, needExpansion, isStatic, stmts, decls,
687                                  p->storageClass, p->type, p->ident, e, t))
688             {
689                 return false;
690             }
691         }
692         else
693         {
694             // expand tuples into multiple `static foreach` variables.
695             assert(e && !t);
696             Identifier *ident = Identifier::generateId("__value");
697             declareVariable(fs, paramtype, te, needExpansion, isStatic, stmts, decls,
698                             0, e->type, ident, e, NULL);
699             Identifier *field = Identifier::idPool("tuple");
700             Expression *access = new DotIdExp(loc, e, field);
701             access = semantic(access, sc);
702             if (!tuple)
703                 return false;
704             //printf("%s\n", tuple->toChars());
705             for (size_t l = 0; l < dim; l++)
706             {
707                 Parameter *cp = (*fs->parameters)[l];
708                 Expression *init_ = new IndexExp(loc, access, new IntegerExp(loc, l, Type::tsize_t));
709                 init_ = semantic(init_, sc);
710                 assert(init_->type);
711                 declareVariable(fs, paramtype, te, needExpansion, isStatic, stmts, decls,
712                                 p->storageClass, init_->type, cp->ident, init_, NULL);
713             }
714         }
715         Statement *fwdstmt = NULL;
716         Dsymbol *fwddecl = NULL;
717         if (!isDecl)
718         {
719             if (fs->_body)
720                 stmts->push(fs->_body->syntaxCopy());
721             fwdstmt = new CompoundStatement(loc, stmts);
722         }
723         else
724         {
725             decls->append(Dsymbol::arraySyntaxCopy(dbody));
726         }
727         if (!isStatic)
728         {
729             fwdstmt = new ScopeStatement(loc, fwdstmt, fs->endloc);
730         }
731         else if (!isDecl)
732         {
733             fwdstmt = new ForwardingStatement(loc, fwdstmt);
734         }
735         else
736         {
737             fwddecl = new ForwardingAttribDeclaration(decls);
738         }
739 
740         if (statements)
741             statements->push(fwdstmt);
742         else if (declarations)
743             declarations->push(fwddecl);
744         else
745             assert(0);
746         return true;
747     }
748 
749     /*******************
750      * Type check and unroll `foreach` over an expression tuple as well
751      * as `static foreach` statements and `static foreach`
752      * declarations. For `static foreach` statements and `static
753      * foreach` declarations, the visitor interface is used (and the
754      * result is written into the `result` field.) For `static
755      * foreach` declarations, the resulting Dsymbols* are returned
756      * directly.
757      *
758      * The unrolled body is wrapped into a
759      *  - UnrolledLoopStatement, for `foreach` over an expression tuple.
760      *  - ForwardingStatement, for `static foreach` statements.
761      *  - ForwardingAttribDeclaration, for `static foreach` declarations.
762      *
763      * `static foreach` variables are declared as `STClocal`, such
764      * that they are inserted into the local symbol tables of the
765      * forwarding constructs instead of forwarded. For `static
766      * foreach` with multiple foreach loop variables whose aggregate
767      * has been lowered into a sequence of tuples, this function
768      * expands the tuples into multiple `STClocal` `static foreach`
769      * variables.
770      */
makeTupleForeach(ForeachStatement * fs,bool needExpansion,bool isStatic,bool isDecl,Statements * statements,Dsymbols * declarations,Dsymbols * dbody)771     bool makeTupleForeach(ForeachStatement *fs, bool needExpansion, bool isStatic, bool isDecl,
772                           Statements *statements, Dsymbols *declarations, Dsymbols *dbody)
773     {
774         Loc loc = fs->loc;
775         size_t dim = fs->parameters->dim;
776         if (!needExpansion && (dim < 1 || dim > 2))
777         {
778             fs->error("only one (value) or two (key,value) arguments for tuple foreach");
779             return false;
780         }
781 
782         Type *paramtype = (*fs->parameters)[dim-1]->type;
783         if (paramtype)
784         {
785             paramtype = paramtype->semantic(loc, sc);
786             if (paramtype->ty == Terror)
787                 return false;
788         }
789 
790         Type *tab = fs->aggr->type->toBasetype();
791         TypeTuple *tuple = (TypeTuple *)tab;
792         //printf("aggr: op = %d, %s\n", fs->aggr->op, fs->aggr->toChars());
793         size_t n;
794         TupleExp *te = NULL;
795         if (fs->aggr->op == TOKtuple)       // expression tuple
796         {
797             te = (TupleExp *)fs->aggr;
798             n = te->exps->dim;
799         }
800         else if (fs->aggr->op == TOKtype)   // type tuple
801         {
802             n = Parameter::dim(tuple->arguments);
803         }
804         else
805             assert(0);
806         for (size_t j = 0; j < n; j++)
807         {
808             size_t k = (fs->op == TOKforeach) ? j : n - 1 - j;
809             if (!makeTupleForeachBody(fs, k, paramtype, te, tuple,
810                                       needExpansion, isStatic, isDecl,
811                                       statements, declarations, dbody))
812                 return false;
813         }
814         return true;
815     }
816 
makeTupleForeachStaticDecl(ForeachStatement * fs,Dsymbols * dbody,bool needExpansion)817     Dsymbols *makeTupleForeachStaticDecl(ForeachStatement *fs, Dsymbols *dbody, bool needExpansion)
818     {
819         assert(sc);
820         Dsymbols *declarations = new Dsymbols();
821         if (!makeTupleForeach(fs, needExpansion, true, true, NULL, declarations, dbody))
822             return NULL;
823 
824         return declarations;
825     }
826 
makeTupleForeachStatic(ForeachStatement * fs,bool needExpansion)827     void makeTupleForeachStatic(ForeachStatement *fs, bool needExpansion)
828     {
829         Loc loc = fs->loc;
830         assert(sc);
831         Statements *statements = new Statements();
832         if (!makeTupleForeach(fs, needExpansion, true, false, statements, NULL, NULL))
833             return setError();
834 
835         result = new CompoundStatement(loc, statements);
836     }
837 
visit(ForeachStatement * fs)838     void visit(ForeachStatement *fs)
839     {
840         //printf("ForeachStatement::semantic() %p\n", fs);
841         ScopeDsymbol *sym;
842         Statement *s = fs;
843         Loc loc = fs->loc;
844         size_t dim = fs->parameters->dim;
845         TypeAArray *taa = NULL;
846         Dsymbol *sapply = NULL;
847 
848         Type *tn = NULL;
849         Type *tnv = NULL;
850 
851         fs->func = sc->func;
852         if (fs->func->fes)
853             fs->func = fs->func->fes->func;
854 
855         VarDeclaration *vinit = NULL;
856         fs->aggr = semantic(fs->aggr, sc);
857         fs->aggr = resolveProperties(sc, fs->aggr);
858         fs->aggr = fs->aggr->optimize(WANTvalue);
859         if (fs->aggr->op == TOKerror)
860             return setError();
861 
862         Expression *oaggr = fs->aggr;
863         if (fs->aggr->type && fs->aggr->type->toBasetype()->ty == Tstruct &&
864             ((TypeStruct *)(fs->aggr->type->toBasetype()))->sym->dtor &&
865             fs->aggr->op != TOKtype && !fs->aggr->isLvalue())
866         {
867             // Bugzilla 14653: Extend the life of rvalue aggregate till the end of foreach.
868             vinit = copyToTemp(STCrvalue, "__aggr", fs->aggr);
869             vinit->semantic(sc);
870             fs->aggr = new VarExp(fs->aggr->loc, vinit);
871         }
872 
873         if (!inferAggregate(fs, sc, sapply))
874         {
875             const char *msg = "";
876             if (fs->aggr->type && isAggregate(fs->aggr->type))
877             {
878                 msg = ", define opApply(), range primitives, or use .tupleof";
879             }
880             fs->error("invalid foreach aggregate %s%s", oaggr->toChars(), msg);
881             return setError();
882         }
883 
884         Dsymbol* sapplyOld = sapply;  // 'sapply' will be NULL if and after 'inferApplyArgTypes' errors
885 
886         /* Check for inference errors
887         */
888         if (!inferApplyArgTypes(fs, sc, sapply))
889         {
890             /**
891               Try and extract the parameter count of the opApply callback function, e.g.:
892               int opApply(int delegate(int, float)) => 2 args
893               */
894             bool foundMismatch = false;
895             size_t foreachParamCount = 0;
896             if (sapplyOld)
897             {
898                 if (FuncDeclaration *fd = sapplyOld->isFuncDeclaration())
899                 {
900                     int fvarargs;  // ignored (opApply shouldn't take variadics)
901                     Parameters *fparameters = fd->getParameters(&fvarargs);
902 
903                     if (Parameter::dim(fparameters) == 1)
904                     {
905                         // first param should be the callback function
906                         Parameter *fparam = Parameter::getNth(fparameters, 0);
907                         if ((fparam->type->ty == Tpointer || fparam->type->ty == Tdelegate) &&
908                             fparam->type->nextOf()->ty == Tfunction)
909                         {
910                             TypeFunction *tf = (TypeFunction *)fparam->type->nextOf();
911                             foreachParamCount = Parameter::dim(tf->parameters);
912                             foundMismatch = true;
913                         }
914                     }
915                 }
916             }
917 
918             //printf("dim = %d, parameters->dim = %d\n", dim, fs->parameters->dim);
919             if (foundMismatch && dim != foreachParamCount)
920             {
921                 const char *plural = foreachParamCount > 1 ? "s" : "";
922                 fs->error("cannot infer argument types, expected %d argument%s, not %d",
923                           foreachParamCount, plural, dim);
924             }
925             else
926                 fs->error("cannot uniquely infer foreach argument types");
927 
928             return setError();
929         }
930 
931         Type *tab = fs->aggr->type->toBasetype();
932 
933         if (tab->ty == Ttuple)      // don't generate new scope for tuple loops
934         {
935             Statements *statements = new Statements();
936             if (!makeTupleForeach(fs, false, false, false, statements, NULL, NULL))
937                 return setError();
938 
939             result = new UnrolledLoopStatement(loc, statements);
940             if (LabelStatement *ls = checkLabeledLoop(sc, fs))
941                 ls->gotoTarget = result;
942             if (fs->aggr->op == TOKtuple)
943             {
944                 TupleExp *te = (TupleExp *)fs->aggr;
945                 if (te->e0)
946                     result = new CompoundStatement(loc, new ExpStatement(te->e0->loc, te->e0), result);
947             }
948             if (vinit)
949                 result = new CompoundStatement(loc, new ExpStatement(loc, vinit), result);
950             result = semantic(result, sc);
951             return;
952         }
953 
954         sym = new ScopeDsymbol();
955         sym->parent = sc->scopesym;
956         sym->endlinnum = fs->endloc.linnum;
957         Scope *sc2 = sc->push(sym);
958 
959         sc2->noctor++;
960 
961         for (size_t i = 0; i < dim; i++)
962         {
963             Parameter *p = (*fs->parameters)[i];
964             if (p->storageClass & STCmanifest)
965             {
966                 fs->error("cannot declare enum loop variables for non-unrolled foreach");
967             }
968             if (p->storageClass & STCalias)
969             {
970                 fs->error("cannot declare alias loop variables for non-unrolled foreach");
971             }
972         }
973 
974         switch (tab->ty)
975         {
976             case Tarray:
977             case Tsarray:
978                 {
979                     if (fs->checkForArgTypes())
980                     {
981                         result = fs;
982                         return;
983                     }
984 
985                     if (dim < 1 || dim > 2)
986                     {
987                         fs->error("only one or two arguments for array foreach");
988                         goto Lerror2;
989                     }
990 
991                     // Finish semantic on all foreach parameter types.
992                     for (size_t i = 0; i < dim; i++)
993                     {
994                         Parameter *p = (*fs->parameters)[i];
995                         p->type = p->type->semantic(loc, sc2);
996                         p->type = p->type->addStorageClass(p->storageClass);
997                     }
998 
999                     tn = tab->nextOf()->toBasetype();
1000 
1001                     if (dim == 2)
1002                     {
1003                         Type *tindex = (*fs->parameters)[0]->type;
1004                         if (!tindex->isintegral())
1005                         {
1006                             fs->error("foreach: key cannot be of non-integral type `%s`",
1007                                       tindex->toChars());
1008                             goto Lerror2;
1009                         }
1010                         /* What cases to deprecate implicit conversions for:
1011                          *  1. foreach aggregate is a dynamic array
1012                          *  2. foreach body is lowered to _aApply (see special case below).
1013                          */
1014                         Type *tv = (*fs->parameters)[1]->type->toBasetype();
1015                         if ((tab->ty == Tarray ||
1016                              (tn->ty != tv->ty &&
1017                               (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar) &&
1018                               (tv->ty == Tchar || tv->ty == Twchar || tv->ty == Tdchar))) &&
1019                             !Type::tsize_t->implicitConvTo(tindex))
1020                         {
1021                             fs->deprecation("foreach: loop index implicitly converted from `size_t` to `%s`",
1022                                             tindex->toChars());
1023                         }
1024                     }
1025 
1026                     /* Look for special case of parsing char types out of char type
1027                      * array.
1028                      */
1029                     if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
1030                     {
1031                         int i = (dim == 1) ? 0 : 1;     // index of value
1032                         Parameter *p = (*fs->parameters)[i];
1033                         tnv = p->type->toBasetype();
1034                         if (tnv->ty != tn->ty &&
1035                             (tnv->ty == Tchar || tnv->ty == Twchar || tnv->ty == Tdchar))
1036                         {
1037                             if (p->storageClass & STCref)
1038                             {
1039                                 fs->error("foreach: value of UTF conversion cannot be ref");
1040                                 goto Lerror2;
1041                             }
1042                             if (dim == 2)
1043                             {
1044                                 p = (*fs->parameters)[0];
1045                                 if (p->storageClass & STCref)
1046                                 {
1047                                     fs->error("foreach: key cannot be ref");
1048                                     goto Lerror2;
1049                                 }
1050                             }
1051                             goto Lapply;
1052                         }
1053                     }
1054 
1055                     for (size_t i = 0; i < dim; i++)
1056                     {
1057                         // Declare parameterss
1058                         Parameter *p = (*fs->parameters)[i];
1059                         VarDeclaration *var;
1060 
1061                         if (dim == 2 && i == 0)
1062                         {
1063                             var = new VarDeclaration(loc, p->type->mutableOf(), Identifier::generateId("__key"), NULL);
1064                             var->storage_class |= STCtemp | STCforeach;
1065                             if (var->storage_class & (STCref | STCout))
1066                                 var->storage_class |= STCnodtor;
1067 
1068                             fs->key = var;
1069                             if (p->storageClass & STCref)
1070                             {
1071                                 if (var->type->constConv(p->type) <= MATCHnomatch)
1072                                 {
1073                                     fs->error("key type mismatch, %s to ref %s",
1074                                               var->type->toChars(), p->type->toChars());
1075                                     goto Lerror2;
1076                                 }
1077                             }
1078                             if (tab->ty == Tsarray)
1079                             {
1080                                 TypeSArray *ta =  (TypeSArray *)tab;
1081                                 IntRange dimrange = getIntRange(ta->dim);
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 
visit(ForeachRangeStatement * fs)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 
visit(IfStatement * ifs)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 
visit(ConditionalStatement * cs)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 
visit(PragmaStatement * ps)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 
visit(StaticAssertStatement * s)2181     void visit(StaticAssertStatement *s)
2182     {
2183         s->sa->semantic2(sc);
2184     }
2185 
visit(SwitchStatement * ss)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 
visit(CaseStatement * cs)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 
visit(CaseRangeStatement * crs)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 
visit(DefaultStatement * ds)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 
visit(GotoDefaultStatement * gds)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 
visit(GotoCaseStatement * gcs)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 
visit(ReturnStatement * rs)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 
visit(BreakStatement * bs)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 
visit(ContinueStatement * cs)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 
visit(SynchronizedStatement * ss)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 
visit(WithStatement * ws)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 
visit(TryCatchStatement * tcs)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 
visit(TryFinallyStatement * tfs)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 
visit(OnScopeStatement * oss)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 
visit(ThrowStatement * ts)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 
visit(DebugStatement * ds)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 
visit(GotoStatement * gs)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 
visit(LabelStatement * ls)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 
visit(AsmStatement * s)3709     void visit(AsmStatement *s)
3710     {
3711         result = asmSemantic(s, sc);
3712     }
3713 
visit(CompoundAsmStatement * cas)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 
visit(ImportStatement * imps)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 
semantic(Statement * s,Scope * sc)3779 Statement *semantic(Statement *s, Scope *sc)
3780 {
3781     StatementSemanticVisitor v = StatementSemanticVisitor(sc);
3782     s->accept(&v);
3783     return v.result;
3784 }
3785 
semantic(Catch * c,Scope * sc)3786 void 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 
semanticNoScope(Statement * s,Scope * sc)3869 Statement *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
semanticScope(Statement * s,Scope * sc,Statement * sbreak,Statement * scontinue)3881 Statement *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  */
makeTupleForeachStatic(Scope * sc,ForeachStatement * fs,bool needExpansion)3899 Statement *makeTupleForeachStatic(Scope *sc, ForeachStatement *fs, bool needExpansion)
3900 {
3901     StatementSemanticVisitor v = StatementSemanticVisitor(sc);
3902     v.makeTupleForeachStatic(fs, needExpansion);
3903     return v.result;
3904 }
3905 
makeTupleForeachStaticDecl(Scope * sc,ForeachStatement * fs,Dsymbols * dbody,bool needExpansion)3906 Dsymbols *makeTupleForeachStaticDecl(Scope *sc, ForeachStatement *fs, Dsymbols *dbody, bool needExpansion)
3907 {
3908     StatementSemanticVisitor v = StatementSemanticVisitor(sc);
3909     return v.makeTupleForeachStaticDecl(fs, dbody, needExpansion);
3910 }
3911