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