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