Merge dmd upstream 6243fa6d2
[official-gcc.git] / gcc / d / dmd / statementsem.c
blob9be934fb4ef21b696bce70d1f34ae844a43a09d4
2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2018 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 */
10 #include "root/dsystem.h"
11 #include "root/rmem.h"
12 #include "root/checkedint.h"
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"
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();
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);
48 class StatementSemanticVisitor : public Visitor
50 public:
51 Statement *result;
52 Scope *sc;
54 StatementSemanticVisitor(Scope *sc)
56 this->result = NULL;
57 this->sc = sc;
60 private:
61 void setError()
63 result = new ErrorStatement();
66 public:
67 void visit(Statement *s)
69 result = s;
72 void visit(ErrorStatement *s)
74 result = s;
77 void visit(PeelStatement *s)
79 /* "peel" off this wrapper, and don't run semantic()
80 * on the result.
82 result = s->s;
85 void visit(ExpStatement *s)
87 if (s->exp)
89 //printf("ExpStatement::semantic() %s\n", s->exp->toChars());
91 // Allow CommaExp in ExpStatement because return isn't used
92 if (s->exp->op == TOKcomma)
93 ((CommaExp *)s->exp)->allowCommaExp = true;
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))
100 if (f->checkForwardRef(s->exp->loc))
101 s->exp = new ErrorExp();
103 if (discardValue(s->exp))
104 s->exp = new ErrorExp();
106 s->exp = s->exp->optimize(WANTvalue);
107 s->exp = checkGC(sc, s->exp);
108 if (s->exp->op == TOKerror)
109 return setError();
111 result = s;
114 void visit(CompileStatement *cs)
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);
124 void visit(CompoundStatement *cs)
126 //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", cs, sc);
127 for (size_t i = 0; i < cs->statements->dim; )
129 Statement *s = (*cs->statements)[i];
130 if (s)
132 Statements *flt = s->flatten(sc);
133 if (flt)
135 cs->statements->remove(i);
136 cs->statements->insert(i, flt);
137 continue;
139 s = semantic(s, sc);
140 (*cs->statements)[i] = s;
141 if (s)
143 Statement *sentry;
144 Statement *sexception;
145 Statement *sfinally;
147 (*cs->statements)[i] = s->scopeCode(sc, &sentry, &sexception, &sfinally);
148 if (sentry)
150 sentry = semantic(sentry, sc);
151 cs->statements->insert(i, sentry);
152 i++;
154 if (sexception)
155 sexception = semantic(sexception, sc);
156 if (sexception)
158 if (i + 1 == cs->statements->dim && !sfinally)
161 else
163 /* Rewrite:
164 * s; s1; s2;
165 * As:
166 * s;
167 * try { s1; s2; }
168 * catch (Throwable __o)
169 * { sexception; throw __o; }
171 Statements *a = new Statements();
172 for (size_t j = i + 1; j < cs->statements->dim; j++)
174 a->push((*cs->statements)[j]);
176 Statement *body = new CompoundStatement(Loc(), a);
177 body = new ScopeStatement(Loc(), body, Loc());
179 Identifier *id = Identifier::generateId("__o");
181 Statement *handler = new PeelStatement(sexception);
182 if (blockExit(sexception, sc->func, false) & BEfallthru)
184 ThrowStatement *ts = new ThrowStatement(Loc(), new IdentifierExp(Loc(), id));
185 ts->internalThrow = true;
186 handler = new CompoundStatement(Loc(), handler, ts);
189 Catches *catches = new Catches();
190 Catch *ctch = new Catch(Loc(), getThrowable(), id, handler);
191 ctch->internalCatch = true;
192 catches->push(ctch);
194 s = new TryCatchStatement(Loc(), body, catches);
195 if (sfinally)
196 s = new TryFinallyStatement(Loc(), s, sfinally);
197 s = semantic(s, sc);
199 cs->statements->setDim(i + 1);
200 cs->statements->push(s);
201 break;
204 else if (sfinally)
206 if (0 && i + 1 == cs->statements->dim)
208 cs->statements->push(sfinally);
210 else
212 /* Rewrite:
213 * s; s1; s2;
214 * As:
215 * s; try { s1; s2; } finally { sfinally; }
217 Statements *a = new Statements();
218 for (size_t j = i + 1; j < cs->statements->dim; j++)
220 a->push((*cs->statements)[j]);
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;
231 else
233 /* Remove NULL statements from the list.
235 cs->statements->remove(i);
236 continue;
239 i++;
241 for (size_t i = 0; i < cs->statements->dim; ++i)
243 Lagain:
244 Statement *s = (*cs->statements)[i];
245 if (!s)
246 continue;
248 Statement *se = s->isErrorStatement();
249 if (se)
251 result = se;
252 return;
255 /* Bugzilla 11653: 'semantic' may return another CompoundStatement
256 * (eg. CaseRangeStatement), so flatten it here.
258 Statements *flt = s->flatten(sc);
259 if (flt)
261 cs->statements->remove(i);
262 cs->statements->insert(i, flt);
263 if (cs->statements->dim <= i)
264 break;
265 goto Lagain;
268 if (cs->statements->dim == 1)
270 result = (*cs->statements)[0];
271 return;
273 result = cs;
276 void visit(UnrolledLoopStatement *uls)
278 //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", uls, sc);
279 Scope *scd = sc->push();
280 scd->sbreak = uls;
281 scd->scontinue = uls;
283 Statement *serror = NULL;
284 for (size_t i = 0; i < uls->statements->dim; i++)
286 Statement *s = (*uls->statements)[i];
287 if (s)
289 //printf("[%d]: %s\n", i, s->toChars());
290 s = semantic(s, scd);
291 (*uls->statements)[i] = s;
293 if (s && !serror)
294 serror = s->isErrorStatement();
298 scd->pop();
299 result = serror ? serror : uls;
302 void visit(ScopeStatement *ss)
304 ScopeDsymbol *sym;
305 //printf("ScopeStatement::semantic(sc = %p)\n", sc);
306 if (ss->statement)
308 sym = new ScopeDsymbol();
309 sym->parent = sc->scopesym;
310 sym->endlinnum = ss->endloc.linnum;
311 sc = sc->push(sym);
313 Statements *a = ss->statement->flatten(sc);
314 if (a)
316 ss->statement = new CompoundStatement(ss->loc, a);
319 ss->statement = semantic(ss->statement, sc);
320 if (ss->statement)
322 if (ss->statement->isErrorStatement())
324 sc->pop();
325 result = ss->statement;
326 return;
329 Statement *sentry;
330 Statement *sexception;
331 Statement *sfinally;
333 ss->statement = ss->statement->scopeCode(sc, &sentry, &sexception, &sfinally);
334 assert(!sentry);
335 assert(!sexception);
336 if (sfinally)
338 //printf("adding sfinally\n");
339 sfinally = semantic(sfinally, sc);
340 ss->statement = new CompoundStatement(ss->loc, ss->statement, sfinally);
344 sc->pop();
346 result = ss;
349 void visit(WhileStatement *ws)
351 /* Rewrite as a for(;condition;) loop
353 Statement *s = new ForStatement(ws->loc, NULL, ws->condition, NULL, ws->_body, ws->endloc);
354 s = semantic(s, sc);
355 result = s;
358 void visit(DoStatement *ds)
360 sc->noctor++;
361 if (ds->_body)
362 ds->_body = semanticScope(ds->_body, sc, ds, ds);
363 sc->noctor--;
365 if (ds->condition->op == TOKdotid)
366 ((DotIdExp *)ds->condition)->noderef = true;
368 // check in syntax level
369 ds->condition = checkAssignmentAsCondition(ds->condition);
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);
376 ds->condition = ds->condition->toBoolean(sc);
378 if (ds->condition->op == TOKerror)
379 return setError();
381 if (ds->_body && ds->_body->isErrorStatement())
383 result = ds->_body;
384 return;
387 result = ds;
390 void visit(ForStatement *fs)
392 //printf("ForStatement::semantic %s\n", toChars());
394 if (fs->_init)
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(); }
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())
418 if (LabelStatement *ls = checkLabeledLoop(sc, fs))
419 ls->gotoTarget = fs;
420 fs->relatedLabeled = s;
422 result = s;
423 return;
425 assert(fs->_init == NULL);
427 ScopeDsymbol *sym = new ScopeDsymbol();
428 sym->parent = sc->scopesym;
429 sym->endlinnum = fs->endloc.linnum;
430 sc = sc->push(sym);
432 sc->noctor++;
433 if (fs->condition)
435 if (fs->condition->op == TOKdotid)
436 ((DotIdExp *)fs->condition)->noderef = true;
438 // check in syntax level
439 fs->condition = checkAssignmentAsCondition(fs->condition);
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);
447 if (fs->increment)
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);
457 sc->sbreak = fs;
458 sc->scontinue = fs;
459 if (fs->_body)
460 fs->_body = semanticNoScope(fs->_body, sc);
461 sc->noctor--;
463 sc->pop();
465 if ((fs->condition && fs->condition->op == TOKerror) ||
466 (fs->increment && fs->increment->op == TOKerror) ||
467 (fs->_body && fs->_body->isErrorStatement()))
468 return setError();
470 result = fs;
473 void visit(ForeachStatement *fs)
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;
483 Type *tn = NULL;
484 Type *tnv = NULL;
486 fs->func = sc->func;
487 if (fs->func->fes)
488 fs->func = fs->func->fes->func;
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();
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())
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);
508 if (!inferAggregate(fs, sc, sapply))
510 const char *msg = "";
511 if (fs->aggr->type && isAggregate(fs->aggr->type))
513 msg = ", define opApply(), range primitives, or use .tupleof";
515 fs->error("invalid foreach aggregate %s%s", oaggr->toChars(), msg);
516 return setError();
519 Dsymbol* sapplyOld = sapply; // 'sapply' will be NULL if and after 'inferApplyArgTypes' errors
521 /* Check for inference errors
523 if (!inferApplyArgTypes(fs, sc, sapply))
526 Try and extract the parameter count of the opApply callback function, e.g.:
527 int opApply(int delegate(int, float)) => 2 args
529 bool foundMismatch = false;
530 size_t foreachParamCount = 0;
531 if (sapplyOld)
533 if (FuncDeclaration *fd = sapplyOld->isFuncDeclaration())
535 int fvarargs; // ignored (opApply shouldn't take variadics)
536 Parameters *fparameters = fd->getParameters(&fvarargs);
538 if (Parameter::dim(fparameters) == 1)
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)
545 TypeFunction *tf = (TypeFunction *)fparam->type->nextOf();
546 foreachParamCount = Parameter::dim(tf->parameters);
547 foundMismatch = true;
553 //printf("dim = %d, parameters->dim = %d\n", dim, fs->parameters->dim);
554 if (foundMismatch && dim != foreachParamCount)
556 const char *plural = foreachParamCount > 1 ? "s" : "";
557 fs->error("cannot infer argument types, expected %d argument%s, not %d",
558 foreachParamCount, plural, dim);
560 else
561 fs->error("cannot uniquely infer foreach argument types");
563 return setError();
566 Type *tab = fs->aggr->type->toBasetype();
568 if (tab->ty == Ttuple) // don't generate new scope for tuple loops
570 if (dim < 1 || dim > 2)
572 fs->error("only one (value) or two (key,value) arguments for tuple foreach");
573 return setError();
576 Type *paramtype = (*fs->parameters)[dim-1]->type;
577 if (paramtype)
579 paramtype = paramtype->semantic(loc, sc);
580 if (paramtype->ty == Terror)
581 return setError();
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
591 te = (TupleExp *)fs->aggr;
592 n = te->exps->dim;
594 else if (fs->aggr->op == TOKtype) // type tuple
596 n = Parameter::dim(tuple->arguments);
598 else
599 assert(0);
600 for (size_t j = 0; j < n; j++)
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();
612 if (dim == 2)
614 // Declare key
615 if (p->storageClass & (STCout | STCref | STClazy))
617 fs->error("no storage class for key %s", p->ident->toChars());
618 return setError();
620 p->type = p->type->semantic(loc, sc);
621 TY keyty = p->type->ty;
622 if (keyty != Tint32 && keyty != Tuns32)
624 if (global.params.isLP64)
626 if (keyty != Tint64 && keyty != Tuns64)
628 fs->error("foreach: key type must be int or uint, long or ulong, not %s", p->type->toChars());
629 return setError();
632 else
634 fs->error("foreach: key type must be int or uint, not %s", p->type->toChars());
635 return setError();
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
644 // Declare value
645 if (p->storageClass & (STCout | STClazy) ||
646 (p->storageClass & STCref && !te))
648 fs->error("no storage class for value %s", p->ident->toChars());
649 return setError();
651 Dsymbol *var;
652 if (te)
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)
664 FuncExp *fe = (FuncExp *)e;
665 ds = fe->td ? (Dsymbol *)fe->td : fe->fd;
668 if (ds)
670 var = new AliasDeclaration(loc, p->ident, ds);
671 if (p->storageClass & STCref)
673 fs->error("symbol %s cannot be ref", s->toChars());
674 return setError();
676 if (paramtype)
678 fs->error("cannot specify element type for symbol %s", ds->toChars());
679 return setError();
682 else if (e->op == TOKtype)
684 var = new AliasDeclaration(loc, p->ident, e->type);
685 if (paramtype)
687 fs->error("cannot specify element type for type %s", e->type->toChars());
688 return setError();
691 else
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)
703 if (v->storage_class & STCref)
705 fs->error("constant value %s cannot be ref", ie->toChars());
706 return setError();
708 else
709 v->storage_class |= STCmanifest;
711 var = v;
714 else
716 var = new AliasDeclaration(loc, p->ident, t);
717 if (paramtype)
719 fs->error("cannot specify element type for symbol %s", s->toChars());
720 return setError();
723 st->push(new ExpStatement(loc, var));
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);
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;
744 sym = new ScopeDsymbol();
745 sym->parent = sc->scopesym;
746 sym->endlinnum = fs->endloc.linnum;
747 Scope *sc2 = sc->push(sym);
749 sc2->noctor++;
751 switch (tab->ty)
753 case Tarray:
754 case Tsarray:
756 if (fs->checkForArgTypes())
758 result = fs;
759 return;
762 if (dim < 1 || dim > 2)
764 fs->error("only one or two arguments for array foreach");
765 goto Lerror2;
768 /* Look for special case of parsing char types out of char type
769 * array.
771 tn = tab->nextOf()->toBasetype();
772 if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
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))
782 if (p->storageClass & STCref)
784 fs->error("foreach: value of UTF conversion cannot be ref");
785 goto Lerror2;
787 if (dim == 2)
789 p = (*fs->parameters)[0];
790 if (p->storageClass & STCref)
792 fs->error("foreach: key cannot be ref");
793 goto Lerror2;
796 goto Lapply;
800 for (size_t i = 0; i < dim; i++)
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;
808 if (dim == 2 && i == 0)
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;
815 fs->key = var;
816 if (p->storageClass & STCref)
818 if (var->type->constConv(p->type) <= MATCHnomatch)
820 fs->error("key type mismatch, %s to ref %s",
821 var->type->toChars(), p->type->toChars());
822 goto Lerror2;
825 if (tab->ty == Tsarray)
827 TypeSArray *ta = (TypeSArray *)tab;
828 IntRange dimrange = getIntRange(ta->dim);
829 if (!IntRange::fromType(var->type).contains(dimrange))
831 fs->error("index type '%s' cannot cover index range 0..%llu", p->type->toChars(), ta->dim->toInteger());
832 goto Lerror2;
834 fs->key->range = new IntRange(SignExtendedNumber(0), dimrange.imax);
837 else
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;
845 fs->value = var;
846 if (var->storage_class & STCref)
848 if (fs->aggr->checkModifiable(sc2, 1) == 2)
849 var->storage_class |= STCctorinit;
851 Type *t = tab->nextOf();
852 if (t->constConv(p->type) <= MATCHnomatch)
854 fs->error("argument type mismatch, %s to ref %s",
855 t->toChars(), p->type->toChars());
856 goto Lerror2;
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 }
867 * foreach_reverse (key, value; a) body =>
868 * for (T[] tmp = a[], size_t key = tmp.length; key--; )
869 * { T value = tmp[k]; body }
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))
877 ArrayLiteralExp *ale = (ArrayLiteralExp *)fs->aggr;
878 size_t edim = ale->elements ? ale->elements->dim : 0;
879 Type *telem = (*fs->parameters)[dim - 1]->type;
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;
887 // for (T[edim] tmp = a, ...)
888 tmp = new VarDeclaration(loc, fs->aggr->type, id, ie);
890 else
891 tmp = new VarDeclaration(loc, tab->nextOf()->arrayOf(), id, ie);
892 tmp->storage_class |= STCtemp;
893 tmp->endlinnum = fs->endloc.linnum;
895 Expression *tmp_length = new DotIdExp(loc, new VarExp(loc, tmp), Id::length);
897 if (!fs->key)
899 Identifier *idkey = Identifier::generateId("__key");
900 fs->key = new VarDeclaration(loc, Type::tsize_t, idkey, NULL);
901 fs->key->storage_class |= STCtemp;
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));
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);
915 Expression *cond;
916 if (fs->op == TOKforeach_reverse)
918 // key--
919 cond = new PostExp(TOKminusminus, loc, new VarExp(loc, fs->key));
921 else
923 // key < tmp.length
924 cond = new CmpExp(TOKlt, loc, new VarExp(loc, fs->key), tmp_length);
927 Expression *increment = NULL;
928 if (fs->op == TOKforeach)
930 // key += 1
931 increment = new AddAssignExp(loc, new VarExp(loc, fs->key), new IntegerExp(loc, 1, fs->key->type));
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);
938 if (dim == 2)
940 Parameter *p = (*fs->parameters)[0];
941 if ((p->storageClass & STCref) && p->type->equals(fs->key->type))
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);
947 else
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())
955 /* Limit the range of the key to the specified range
957 v->range = new IntRange(fs->key->range->imin, fs->key->range->imax - SignExtendedNumber(1));
961 fs->_body = new CompoundStatement(loc, ds, fs->_body);
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;
970 case Taarray:
971 if (fs->op == TOKforeach_reverse)
972 fs->warning("cannot use foreach_reverse with an associative array");
973 if (fs->checkForArgTypes())
975 result = fs;
976 return;
979 taa = (TypeAArray *)tab;
980 if (dim < 1 || dim > 2)
982 fs->error("only one or two arguments for associative array foreach");
983 goto Lerror2;
985 goto Lapply;
987 case Tclass:
988 case Tstruct:
989 /* Prefer using opApply, if it exists
991 if (sapply)
992 goto Lapply;
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 * ...
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)
1011 idfront = Id::Ffront;
1012 idpopFront = Id::FpopFront;
1014 else
1016 idfront = Id::Fback;
1017 idpopFront = Id::FpopBack;
1019 Dsymbol *sfront = ad->search(Loc(), idfront);
1020 if (!sfront)
1021 goto Lapply;
1023 /* Generate a temporary __r and initialize it with the aggregate.
1025 VarDeclaration *r;
1026 Statement *init;
1027 if (vinit && fs->aggr->op == TOKvar && ((VarExp *)fs->aggr)->var == vinit)
1029 r = vinit;
1030 init = new ExpStatement(loc, vinit);
1032 else
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);
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);
1045 // __r.idpopFront()
1046 e = new VarExp(loc, r);
1047 Expression *increment = new CallExp(loc, new DotIdExp(loc, e, idpopFront));
1049 /* Declaration statement for e:
1050 * auto e = __r.idfront;
1052 e = new VarExp(loc, r);
1053 Expression *einit = new DotIdExp(loc, e, idfront);
1054 Statement *makeargs, *forbody;
1055 if (dim == 1)
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);
1062 makeargs = new ExpStatement(loc, ve);
1064 else
1066 VarDeclaration *vd = copyToTemp(STCref, "__front", einit);
1067 makeargs = new ExpStatement(loc, vd);
1069 Type *tfront = NULL;
1070 if (FuncDeclaration *fd = sfront->isFuncDeclaration())
1072 if (!fd->functionSemantic())
1073 goto Lrangeerr;
1074 tfront = fd->type;
1076 else if (TemplateDeclaration *td = sfront->isTemplateDeclaration())
1078 Expressions a;
1079 if (FuncDeclaration *f = resolveFuncCall(loc, sc, td, NULL, tab, &a, 1))
1080 tfront = f->type;
1082 else if (Declaration *d = sfront->isDeclaration())
1084 tfront = d->type;
1086 if (!tfront || tfront->ty == Terror)
1087 goto Lrangeerr;
1089 if (tfront->toBasetype()->ty == Tfunction)
1090 tfront = tfront->toBasetype()->nextOf();
1091 if (tfront->ty == Tvoid)
1093 fs->error("%s.front is void and has no value", oaggr->toChars());
1094 goto Lerror2;
1097 // Resolve inout qualifier of front type
1098 tfront = tfront->substWildTo(tab->mod);
1100 Expression *ve = new VarExp(loc, vd);
1101 ve->type = tfront;
1103 Expressions *exps = new Expressions();
1104 exps->push(ve);
1105 int pos = 0;
1106 while (exps->dim < dim)
1108 pos = expandAliasThisTuples(exps, pos);
1109 if (pos == -1)
1110 break;
1112 if (exps->dim != dim)
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;
1120 for (size_t i = 0; i < dim; i++)
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;
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));
1137 forbody = new CompoundStatement(loc,
1138 makeargs, fs->_body);
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;
1146 Lrangeerr:
1147 fs->error("cannot infer argument types");
1148 goto Lerror2;
1150 case Tdelegate:
1151 if (fs->op == TOKforeach_reverse)
1152 fs->deprecation("cannot use foreach_reverse with a delegate");
1153 Lapply:
1155 if (fs->checkForArgTypes())
1157 fs->_body = semanticNoScope(fs->_body, sc2);
1158 result = fs;
1159 return;
1162 TypeFunction *tfld = NULL;
1163 if (sapply)
1165 FuncDeclaration *fdapply = sapply->isFuncDeclaration();
1166 if (fdapply)
1168 assert(fdapply->type && fdapply->type->ty == Tfunction);
1169 tfld = (TypeFunction *)fdapply->type->semantic(loc, sc2);
1170 goto Lget;
1172 else if (tab->ty == Tdelegate)
1174 tfld = (TypeFunction *)tab->nextOf();
1175 Lget:
1176 //printf("tfld = %s\n", tfld->toChars());
1177 if (tfld->parameters->dim == 1)
1179 Parameter *p = Parameter::getNth(tfld->parameters, 0);
1180 if (p->type && p->type->ty == Tdelegate)
1182 Type *t = p->type->semantic(loc, sc2);
1183 assert(t->ty == Tdelegate);
1184 tfld = (TypeFunction *)t->nextOf();
1190 /* Turn body into the function literal:
1191 * int delegate(ref T param) { body }
1193 Parameters *params = new Parameters();
1194 for (size_t i = 0; i < dim; i++)
1196 Parameter *p = (*fs->parameters)[i];
1197 StorageClass stc = STCref;
1198 Identifier *id;
1200 p->type = p->type->semantic(loc, sc2);
1201 p->type = p->type->addStorageClass(p->storageClass);
1202 if (tfld)
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)
1210 if (!stc)
1212 fs->error("foreach: cannot make %s ref", p->ident->toChars());
1213 goto Lerror2;
1215 goto LcopyArg;
1218 else if (p->storageClass & STCref)
1220 // default delegate parameters are marked as ref, then
1221 // argument copy is not need.
1222 id = p->ident;
1224 else
1226 // Make a copy of the ref argument so it isn't
1227 // a reference.
1228 LcopyArg:
1229 id = Identifier::generateId("__applyArg", (int)i);
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);
1237 params->push(new Parameter(stc, p->type, id, NULL));
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;
1250 // Resolve any forward referenced goto's
1251 for (size_t i = 0; i < fs->gotos->dim; i++)
1253 GotoStatement *gs = (GotoStatement *)(*fs->gotos)[i]->statement;
1254 if (!gs->label->statement)
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;
1263 Expression *e = NULL;
1264 Expression *ec;
1265 if (vinit)
1267 e = new DeclarationExp(loc, vinit);
1268 e = semantic(e, sc2);
1269 if (e->op == TOKerror)
1270 goto Lerror2;
1273 if (taa)
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)
1281 Type *ti = (isRef ? taa->index->addMod(MODconst) : taa->index);
1282 if (isRef ? !ti->constConv(ta) : !ti->implicitConvTo(ta))
1284 fs->error("foreach: index must be type %s, not %s", ti->toChars(), ta->toChars());
1285 goto Lerror2;
1287 p = (*fs->parameters)[1];
1288 isRef = (p->storageClass & STCref) != 0;
1289 ta = p->type;
1291 Type *taav = taa->nextOf();
1292 if (isRef ? !taav->constConv(ta) : !taav->implicitConvTo(ta))
1294 fs->error("foreach: value must be type %s, not %s", taav->toChars(), ta->toChars());
1295 goto Lerror2;
1298 /* Call:
1299 * extern(C) int _aaApply(void*, in size_t, int delegate(void*))
1300 * _aaApply(aggr, keysize, flde)
1302 * extern(C) int _aaApply2(void*, in size_t, int delegate(void*, void*))
1303 * _aaApply2(aggr, keysize, flde)
1305 static const char *name[2] = { "_aaApply", "_aaApply2" };
1306 static FuncDeclaration *fdapply[2] = { NULL, NULL };
1307 static TypeDelegate *fldeTy[2] = { NULL, NULL };
1309 unsigned char i = (dim == 2 ? 1 : 0);
1310 if (!fdapply[i])
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]);
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))
1334 flde = new CastExp(loc, flde, flde->type);
1335 flde->type = fldeTy[i];
1337 exps->push(new IntegerExp(Loc(), keysize, Type::tsize_t));
1338 exps->push(flde);
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
1344 else if (tab->ty == Tarray || tab->ty == Tsarray)
1346 /* Call:
1347 * _aApply(aggr, flde)
1349 static const char fntab[9][3] =
1350 { "cc","cw","cd",
1351 "wc","cc","wd",
1352 "dc","dw","dd"
1354 const int BUFFER_LEN = 7+1+2+ sizeof(dim)*3 + 1;
1355 char fdname[BUFFER_LEN];
1356 int flag;
1358 switch (tn->ty)
1360 case Tchar: flag = 0; break;
1361 case Twchar: flag = 3; break;
1362 case Tdchar: flag = 6; break;
1363 default: assert(0);
1365 switch (tnv->ty)
1367 case Tchar: flag += 0; break;
1368 case Twchar: flag += 1; break;
1369 case Tdchar: flag += 2; break;
1370 default: assert(0);
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);
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);
1388 if (tab->ty == Tsarray)
1389 fs->aggr = fs->aggr->castTo(sc2, tn->arrayOf());
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;
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
1401 else if (tab->ty == Tdelegate)
1403 /* Call:
1404 * aggr(flde)
1406 if (fs->aggr->op == TOKdelegate &&
1407 ((DelegateExp *)fs->aggr)->func->isNested())
1409 // See Bugzilla 3560
1410 fs->aggr = ((DelegateExp *)fs->aggr)->e1;
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)
1418 fs->error("opApply() function for %s must return an int", tab->toChars());
1419 goto Lerror2;
1422 else
1424 if (global.params.vsafe)
1425 fld->tookAddressOf = 1; // allocate a closure unless the opApply() uses 'scope'
1427 assert(tab->ty == Tstruct || tab->ty == Tclass);
1428 assert(sapply);
1429 /* Call:
1430 * aggr.apply(flde)
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)
1439 fs->error("opApply() function for %s must return an int", tab->toChars());
1440 goto Lerror2;
1443 e = Expression::combine(e, ec);
1445 if (!fs->cases->dim)
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);
1451 else
1453 // Construct a switch statement around the return value
1454 // of the apply function.
1455 Statements *a = new Statements();
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);
1462 // cases 2...
1463 for (size_t i = 0; i < fs->cases->dim; i++)
1465 s = (*fs->cases)[i];
1466 s = new CaseStatement(Loc(), new IntegerExp(i + 2), s);
1467 a->push(s);
1470 s = new CompoundStatement(loc, a);
1471 s = new SwitchStatement(loc, e, s, false);
1473 s = semantic(s, sc2);
1474 break;
1476 case Terror:
1477 Lerror2:
1478 s = new ErrorStatement();
1479 break;
1481 default:
1482 fs->error("foreach: %s is not an aggregate type", fs->aggr->type->toChars());
1483 goto Lerror2;
1485 sc2->noctor--;
1486 sc2->pop();
1487 result = s;
1490 void visit(ForeachRangeStatement *fs)
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)
1499 fs->error("invalid range lower bound %s", fs->lwr->toChars());
1500 Lerror:
1501 return setError();
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)
1509 fs->error("invalid range upper bound %s", fs->upr->toChars());
1510 goto Lerror;
1513 if (fs->prm->type)
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);
1519 if (fs->upr->implicitConvTo(fs->prm->type) || (fs->prm->storageClass & STCref))
1521 fs->upr = fs->upr->implicitCastTo(sc, fs->prm->type);
1523 else
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))
1531 fs->upr = fs->upr->implicitCastTo(sc, fs->prm->type);
1535 else
1537 /* Must infer types from lwr and upr
1539 Type *tlwr = fs->lwr->type->toBasetype();
1540 if (tlwr->ty == Tstruct || tlwr->ty == Tclass)
1542 /* Just picking the first really isn't good enough.
1544 fs->prm->type = fs->lwr->type;
1546 else if (fs->lwr->type == fs->upr->type)
1548 /* Same logic as CondExp ?lwr:upr
1550 fs->prm->type = fs->lwr->type;
1552 else
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;
1561 fs->prm->type = fs->prm->type->addStorageClass(fs->prm->storageClass);
1563 if (fs->prm->type->ty == Terror ||
1564 fs->lwr->op == TOKerror ||
1565 fs->upr->op == TOKerror)
1567 return setError();
1570 /* Convert to a for loop:
1571 * foreach (key; lwr .. upr) =>
1572 * for (auto key = lwr, auto tmp = upr; key < tmp; ++key)
1574 * foreach_reverse (key; lwr .. upr) =>
1575 * for (auto tmp = lwr, auto key = upr; key-- > tmp;)
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)
1584 fs->key->range = new IntRange(lower, upper);
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;
1592 Statements *cs = new Statements();
1593 // Keep order of evaluation as lwr, then upr
1594 if (fs->op == TOKforeach)
1596 cs->push(new ExpStatement(loc, fs->key));
1597 cs->push(new ExpStatement(loc, tmp));
1599 else
1601 cs->push(new ExpStatement(loc, tmp));
1602 cs->push(new ExpStatement(loc, fs->key));
1604 Statement *forinit = new CompoundDeclarationStatement(loc, cs);
1606 Expression *cond;
1607 if (fs->op == TOKforeach_reverse)
1609 cond = new PostExp(TOKminusminus, loc, new VarExp(loc, fs->key));
1610 if (fs->prm->type->isscalar())
1612 // key-- > tmp
1613 cond = new CmpExp(TOKgt, loc, cond, new VarExp(loc, tmp));
1615 else
1617 // key-- != tmp
1618 cond = new EqualExp(TOKnotequal, loc, cond, new VarExp(loc, tmp));
1621 else
1623 if (fs->prm->type->isscalar())
1625 // key < tmp
1626 cond = new CmpExp(TOKlt, loc, new VarExp(loc, fs->key), new VarExp(loc, tmp));
1628 else
1630 // key != tmp
1631 cond = new EqualExp(TOKnotequal, loc, new VarExp(loc, fs->key), new VarExp(loc, tmp));
1635 Expression *increment = NULL;
1636 if (fs->op == TOKforeach)
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));
1643 if ((fs->prm->storageClass & STCref) && fs->prm->type->equals(fs->key->type))
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);
1649 else
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())
1657 /* Limit the range of the key to the specified range
1659 v->range = new IntRange(fs->key->range->imin, fs->key->range->imax - SignExtendedNumber(1));
1662 if (fs->prm->storageClass & STCref)
1664 if (fs->key->type->constConv(fs->prm->type) <= MATCHnomatch)
1666 fs->error("prmument type mismatch, %s to ref %s",
1667 fs->key->type->toChars(), fs->prm->type->toChars());
1668 goto Lerror;
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);
1678 void visit(IfStatement *ifs)
1680 // Evaluate at runtime
1681 unsigned cs0 = sc->callSuper;
1682 unsigned cs1;
1683 unsigned *fi0 = sc->saveFieldInit();
1684 unsigned *fi1 = NULL;
1686 // check in syntax level
1687 ifs->condition = checkAssignmentAsCondition(ifs->condition);
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)
1695 /* Declare prm, which we will set to be the
1696 * result of condition.
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);
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);
1709 if (ifs->match->edtor)
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;
1717 else
1719 if (ifs->condition->op == TOKdotid)
1720 ((DotIdExp *)ifs->condition)->noderef = true;
1722 ifs->condition = semantic(ifs->condition, sc);
1723 ifs->condition = resolveProperties(sc, ifs->condition);
1724 ifs->condition = ifs->condition->addDtorHook(sc);
1726 ifs->condition = checkGC(sc, ifs->condition);
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);
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();
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);
1749 if (ifs->condition->op == TOKerror ||
1750 (ifs->ifbody && ifs->ifbody->isErrorStatement()) ||
1751 (ifs->elsebody && ifs->elsebody->isErrorStatement()))
1753 return setError();
1755 result = ifs;
1758 void visit(ConditionalStatement *cs)
1760 //printf("ConditionalStatement::semantic()\n");
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))
1767 DebugCondition *dc = cs->condition->isDebugCondition();
1768 if (dc)
1770 sc = sc->push();
1771 sc->flags |= SCOPEdebug;
1772 cs->ifbody = semantic(cs->ifbody, sc);
1773 sc->pop();
1775 else
1776 cs->ifbody = semantic(cs->ifbody, sc);
1777 result = cs->ifbody;
1779 else
1781 if (cs->elsebody)
1782 cs->elsebody = semantic(cs->elsebody, sc);
1783 result = cs->elsebody;
1787 void visit(PragmaStatement *ps)
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)
1794 if (ps->args)
1796 for (size_t i = 0; i < ps->args->dim; i++)
1798 Expression *e = (*ps->args)[i];
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)
1808 errorSupplemental(ps->loc, "while evaluating pragma(msg, %s)", (*ps->args)[i]->toChars());
1809 goto Lerror;
1811 StringExp *se = e->toStringExp();
1812 if (se)
1814 se = se->toUTF8(sc);
1815 fprintf(stderr, "%.*s", (int)se->len, (char *)se->string);
1817 else
1818 fprintf(stderr, "%s", e->toChars());
1820 fprintf(stderr, "\n");
1823 else if (ps->ident == Id::lib)
1825 /* Should this be allowed?
1827 ps->error("pragma(lib) not allowed as statement");
1828 goto Lerror;
1830 else if (ps->ident == Id::startaddress)
1832 if (!ps->args || ps->args->dim != 1)
1833 ps->error("function name expected for start address");
1834 else
1836 Expression *e = (*ps->args)[0];
1838 sc = sc->startCTFE();
1839 e = semantic(e, sc);
1840 e = resolveProperties(sc, e);
1841 sc = sc->endCTFE();
1843 e = e->ctfeInterpret();
1844 (*ps->args)[0] = e;
1845 Dsymbol *sa = getDsymbol(e);
1846 if (!sa || !sa->isFuncDeclaration())
1848 ps->error("function name expected for start address, not '%s'", e->toChars());
1849 goto Lerror;
1851 if (ps->_body)
1853 ps->_body = semantic(ps->_body, sc);
1854 if (ps->_body->isErrorStatement())
1856 result = ps->_body;
1857 return;
1860 result = ps;
1861 return;
1864 else if (ps->ident == Id::Pinline)
1866 PINLINE inlining = PINLINEdefault;
1867 if (!ps->args || ps->args->dim == 0)
1868 inlining = PINLINEdefault;
1869 else if (!ps->args || ps->args->dim != 1)
1871 ps->error("boolean expression expected for pragma(inline)");
1872 goto Lerror;
1874 else
1876 Expression *e = (*ps->args)[0];
1878 if (e->op != TOKint64 || !e->type->equals(Type::tbool))
1880 ps->error("pragma(inline, true or false) expected, not %s", e->toChars());
1881 goto Lerror;
1884 if (e->isBool(true))
1885 inlining = PINLINEalways;
1886 else if (e->isBool(false))
1887 inlining = PINLINEnever;
1889 FuncDeclaration *fd = sc->func;
1890 if (!fd)
1892 ps->error("pragma(inline) is not inside a function");
1893 goto Lerror;
1895 fd->inlining = inlining;
1898 else
1900 ps->error("unrecognized pragma(%s)", ps->ident->toChars());
1901 goto Lerror;
1904 if (ps->_body)
1906 ps->_body = semantic(ps->_body, sc);
1908 result = ps->_body;
1909 return;
1911 Lerror:
1912 return setError();
1915 void visit(StaticAssertStatement *s)
1917 s->sa->semantic2(sc);
1920 void visit(SwitchStatement *ss)
1922 //printf("SwitchStatement::semantic(%p)\n", ss);
1923 ss->tf = sc->tf;
1924 if (ss->cases)
1926 result = ss; // already run
1927 return;
1929 bool conditionError = false;
1930 ss->condition = semantic(ss->condition, sc);
1931 ss->condition = resolveProperties(sc, ss->condition);
1933 Type *att = NULL;
1934 TypeEnum *te = NULL;
1935 while (ss->condition->op != TOKerror)
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())
1942 // If it's not an array, cast it to one
1943 if (ss->condition->type->ty != Tarray)
1945 ss->condition = ss->condition->implicitCastTo(sc, ss->condition->type->nextOf()->arrayOf());
1947 ss->condition->type = ss->condition->type->constOf();
1948 break;
1950 ss->condition = integralPromotions(ss->condition, sc);
1951 if (ss->condition->op != TOKerror && ss->condition->type->isintegral())
1952 break;
1954 AggregateDeclaration *ad = isAggregate(ss->condition->type);
1955 if (ad && ad->aliasthis && ss->condition->type != att)
1957 if (!att && ss->condition->type->checkAliasThisRec())
1958 att = ss->condition->type;
1959 if (Expression *e = resolveAliasThis(sc, ss->condition, true))
1961 ss->condition = e;
1962 continue;
1966 if (ss->condition->op != TOKerror)
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;
1974 ss->condition = ss->condition->optimize(WANTvalue);
1975 ss->condition = checkGC(sc, ss->condition);
1976 if (ss->condition->op == TOKerror)
1977 conditionError = true;
1979 bool needswitcherror = false;
1981 ss->lastVar = sc->lastVar;
1983 sc = sc->push();
1984 sc->sbreak = ss;
1985 sc->sw = ss;
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--;
1992 if (conditionError || ss->_body->isErrorStatement())
1993 goto Lerror;
1995 // Resolve any goto case's with exp
1996 for (size_t i = 0; i < ss->gotoCases.dim; i++)
1998 GotoCaseStatement *gcs = ss->gotoCases[i];
2000 if (!gcs->exp)
2002 gcs->error("no case statement following goto case;");
2003 goto Lerror;
2006 for (Scope *scx = sc; scx; scx = scx->enclosing)
2008 if (!scx->sw)
2009 continue;
2010 for (size_t j = 0; j < scx->sw->cases->dim; j++)
2012 CaseStatement *cs = (*scx->sw->cases)[j];
2014 if (cs->exp->equals(gcs->exp))
2016 gcs->cs = cs;
2017 goto Lfoundcase;
2021 gcs->error("case %s not found", gcs->exp->toChars());
2022 goto Lerror;
2024 Lfoundcase:
2028 if (ss->isFinal)
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)
2039 size_t dim = ed->members->dim;
2040 for (size_t i = 0; i < dim; i++)
2042 EnumMember *em = (*ed->members)[i]->isEnumMember();
2043 if (em)
2045 for (size_t j = 0; j < ss->cases->dim; j++)
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;
2053 ss->error("enum member %s not represented in final switch", em->toChars());
2054 goto Lerror;
2060 else
2061 needswitcherror = true;
2064 if (!sc->sw->sdefault && (!ss->isFinal || needswitcherror || global.params.useAssert))
2066 ss->hasNoDefault = 1;
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;'");
2071 // Generate runtime error if the default is hit
2072 Statements *a = new Statements();
2073 CompoundStatement *cs;
2074 Statement *s;
2076 if (global.params.useSwitchError)
2077 s = new SwitchErrorStatement(ss->loc);
2078 else
2079 s = new ExpStatement(ss->loc, new HaltExp(ss->loc));
2081 a->reserve(2);
2082 sc->sw->sdefault = new DefaultStatement(ss->loc, s);
2083 a->push(ss->_body);
2084 if (blockExit(ss->_body, sc->func, false) & BEfallthru)
2085 a->push(new BreakStatement(Loc(), NULL));
2086 a->push(sc->sw->sdefault);
2087 cs = new CompoundStatement(ss->loc, a);
2088 ss->_body = cs;
2091 if (ss->checkLabel())
2092 goto Lerror;
2094 sc->pop();
2095 result = ss;
2096 return;
2098 Lerror:
2099 sc->pop();
2100 result = new ErrorStatement();
2103 void visit(CaseStatement *cs)
2105 SwitchStatement *sw = sc->sw;
2106 bool errors = false;
2108 //printf("CaseStatement::semantic() %s\n", cs->toChars());
2109 sc = sc->startCTFE();
2110 cs->exp = semantic(cs->exp, sc);
2111 cs->exp = resolveProperties(sc, cs->exp);
2112 sc = sc->endCTFE();
2113 if (sw)
2115 cs->exp = cs->exp->implicitCastTo(sc, sw->condition->type);
2116 cs->exp = cs->exp->optimize(WANTvalue | WANTexpand);
2118 Expression *e = cs->exp;
2119 // Remove all the casts the user and/or implicitCastTo may introduce
2120 // otherwise we'd sometimes fail the check below.
2121 while (e->op == TOKcast)
2122 e = ((CastExp *)e)->e1;
2124 /* This is where variables are allowed as case expressions.
2126 if (e->op == TOKvar)
2128 VarExp *ve = (VarExp *)e;
2129 VarDeclaration *v = ve->var->isVarDeclaration();
2130 Type *t = cs->exp->type->toBasetype();
2131 if (v && (t->isintegral() || t->ty == Tclass))
2133 /* Flag that we need to do special code generation
2134 * for this, i.e. generate a sequence of if-then-else
2136 sw->hasVars = 1;
2138 /* TODO check if v can be uninitialized at that point.
2140 if (!v->isConst() && !v->isImmutable())
2142 cs->deprecation("case variables have to be const or immutable");
2145 if (sw->isFinal)
2147 cs->error("case variables not allowed in final switch statements");
2148 errors = true;
2151 /* Also check if the VarExp is declared in a scope outside of this one.
2152 * 'scx' is set to the scope of the switch statement.
2154 for (Scope *scx = sc; scx; scx = scx->enclosing)
2156 if (scx->enclosing && scx->enclosing->sw == sw)
2157 continue;
2158 assert(scx->sw == sw);
2160 if (!scx->search(cs->exp->loc, v->ident, NULL))
2162 cs->error("case variable `%s` declared at %s cannot be declared in switch body",
2163 v->toChars(), v->loc.toChars());
2164 errors = true;
2166 break;
2168 goto L1;
2171 else
2172 cs->exp = cs->exp->ctfeInterpret();
2174 if (StringExp *se = cs->exp->toStringExp())
2175 cs->exp = se;
2176 else if (cs->exp->op != TOKint64 && cs->exp->op != TOKerror)
2178 cs->error("case must be a string or an integral constant, not %s", cs->exp->toChars());
2179 errors = true;
2183 for (size_t i = 0; i < sw->cases->dim; i++)
2185 CaseStatement *cs2 = (*sw->cases)[i];
2187 //printf("comparing '%s' with '%s'\n", cs->exp->toChars(), cs2->exp->toChars());
2188 if (cs2->exp->equals(cs->exp))
2190 cs->error("duplicate case %s in switch statement", cs->exp->toChars());
2191 errors = true;
2192 break;
2196 sw->cases->push(cs);
2198 // Resolve any goto case's with no exp to this case statement
2199 for (size_t i = 0; i < sw->gotoCases.dim; )
2201 GotoCaseStatement *gcs = sw->gotoCases[i];
2203 if (!gcs->exp)
2205 gcs->cs = cs;
2206 sw->gotoCases.remove(i); // remove from array
2207 continue;
2209 i++;
2212 if (sc->sw->tf != sc->tf)
2214 cs->error("switch and case are in different finally blocks");
2215 errors = true;
2218 else
2220 cs->error("case not in switch statement");
2221 errors = true;
2223 cs->statement = semantic(cs->statement, sc);
2224 if (cs->statement->isErrorStatement())
2226 result = cs->statement;
2227 return;
2229 if (errors || cs->exp->op == TOKerror)
2230 return setError();
2232 cs->lastVar = sc->lastVar;
2233 result = cs;
2236 void visit(CaseRangeStatement *crs)
2238 SwitchStatement *sw = sc->sw;
2239 if (sw == NULL)
2241 crs->error("case range not in switch statement");
2242 return setError();
2245 //printf("CaseRangeStatement::semantic() %s\n", toChars());
2246 bool errors = false;
2247 if (sw->isFinal)
2249 crs->error("case ranges not allowed in final switch");
2250 errors = true;
2253 sc = sc->startCTFE();
2254 crs->first = semantic(crs->first, sc);
2255 crs->first = resolveProperties(sc, crs->first);
2256 sc = sc->endCTFE();
2257 crs->first = crs->first->implicitCastTo(sc, sw->condition->type);
2258 crs->first = crs->first->ctfeInterpret();
2260 sc = sc->startCTFE();
2261 crs->last = semantic(crs->last, sc);
2262 crs->last = resolveProperties(sc, crs->last);
2263 sc = sc->endCTFE();
2264 crs->last = crs->last->implicitCastTo(sc, sw->condition->type);
2265 crs->last = crs->last->ctfeInterpret();
2267 if (crs->first->op == TOKerror || crs->last->op == TOKerror || errors)
2269 if (crs->statement)
2270 semantic(crs->statement, sc);
2271 return setError();
2274 uinteger_t fval = crs->first->toInteger();
2275 uinteger_t lval = crs->last->toInteger();
2278 if ( (crs->first->type->isunsigned() && fval > lval) ||
2279 (!crs->first->type->isunsigned() && (sinteger_t)fval > (sinteger_t)lval))
2281 crs->error("first case %s is greater than last case %s",
2282 crs->first->toChars(), crs->last->toChars());
2283 errors = true;
2284 lval = fval;
2287 if (lval - fval > 256)
2289 crs->error("had %llu cases which is more than 256 cases in case range", lval - fval);
2290 errors = true;
2291 lval = fval + 256;
2294 if (errors)
2295 return setError();
2297 /* This works by replacing the CaseRange with an array of Case's.
2299 * case a: .. case b: s;
2300 * =>
2301 * case a:
2302 * [...]
2303 * case b:
2304 * s;
2307 Statements *statements = new Statements();
2308 for (uinteger_t i = fval; i != lval + 1; i++)
2310 Statement *s = crs->statement;
2311 if (i != lval) // if not last case
2312 s = new ExpStatement(crs->loc, (Expression *)NULL);
2313 Expression *e = new IntegerExp(crs->loc, i, crs->first->type);
2314 Statement *cs = new CaseStatement(crs->loc, e, s);
2315 statements->push(cs);
2317 Statement *s = new CompoundStatement(crs->loc, statements);
2318 s = semantic(s, sc);
2319 result = s;
2322 void visit(DefaultStatement *ds)
2324 //printf("DefaultStatement::semantic()\n");
2325 bool errors = false;
2326 if (sc->sw)
2328 if (sc->sw->sdefault)
2330 ds->error("switch statement already has a default");
2331 errors = true;
2333 sc->sw->sdefault = ds;
2335 if (sc->sw->tf != sc->tf)
2337 ds->error("switch and default are in different finally blocks");
2338 errors = true;
2340 if (sc->sw->isFinal)
2342 ds->error("default statement not allowed in final switch statement");
2343 errors = true;
2346 else
2348 ds->error("default not in switch statement");
2349 errors = true;
2351 ds->statement = semantic(ds->statement, sc);
2352 if (errors || ds->statement->isErrorStatement())
2353 return setError();
2355 ds->lastVar = sc->lastVar;
2356 result = ds;
2359 void visit(GotoDefaultStatement *gds)
2361 gds->sw = sc->sw;
2362 if (!gds->sw)
2364 gds->error("goto default not in switch statement");
2365 return setError();
2367 if (gds->sw->isFinal)
2369 gds->error("goto default not allowed in final switch statement");
2370 return setError();
2372 result = gds;
2375 void visit(GotoCaseStatement *gcs)
2377 if (!sc->sw)
2379 gcs->error("goto case not in switch statement");
2380 return setError();
2383 if (gcs->exp)
2385 gcs->exp = semantic(gcs->exp, sc);
2386 gcs->exp = gcs->exp->implicitCastTo(sc, sc->sw->condition->type);
2387 gcs->exp = gcs->exp->optimize(WANTvalue);
2388 if (gcs->exp->op == TOKerror)
2389 return setError();
2392 sc->sw->gotoCases.push(gcs);
2393 result = gcs;
2396 void visit(ReturnStatement *rs)
2398 //printf("ReturnStatement::semantic() %s\n", toChars());
2400 FuncDeclaration *fd = sc->parent->isFuncDeclaration();
2402 if (fd->fes)
2403 fd = fd->fes->func; // fd is now function enclosing foreach
2405 TypeFunction *tf = (TypeFunction *)fd->type;
2406 assert(tf->ty == Tfunction);
2408 if (rs->exp && rs->exp->op == TOKvar && ((VarExp *)rs->exp)->var == fd->vresult)
2410 // return vresult;
2411 if (sc->fes)
2413 assert(rs->caseDim == 0);
2414 sc->fes->cases->push(rs);
2415 result = new ReturnStatement(Loc(), new IntegerExp(sc->fes->cases->dim + 1));
2416 return;
2418 if (fd->returnLabel)
2420 GotoStatement *gs = new GotoStatement(rs->loc, Id::returnLabel);
2421 gs->label = fd->returnLabel;
2422 result = gs;
2423 return;
2426 if (!fd->returns)
2427 fd->returns = new ReturnStatements();
2428 fd->returns->push(rs);
2429 result = rs;
2430 return;
2433 Type *tret = tf->next;
2434 Type *tbret = tret ? tret->toBasetype() : NULL;
2436 bool inferRef = (tf->isref && (fd->storage_class & STCauto));
2437 Expression *e0 = NULL;
2439 bool errors = false;
2440 if (sc->flags & SCOPEcontract)
2442 rs->error("return statements cannot be in contracts");
2443 errors = true;
2445 if (sc->os && sc->os->tok != TOKon_scope_failure)
2447 rs->error("return statements cannot be in %s bodies", Token::toChars(sc->os->tok));
2448 errors = true;
2450 if (sc->tf)
2452 rs->error("return statements cannot be in finally bodies");
2453 errors = true;
2456 if (fd->isCtorDeclaration())
2458 if (rs->exp)
2460 rs->error("cannot return expression from constructor");
2461 errors = true;
2464 // Constructors implicitly do:
2465 // return this;
2466 rs->exp = new ThisExp(Loc());
2467 rs->exp->type = tret;
2469 else if (rs->exp)
2471 fd->hasReturnExp |= (fd->hasReturnExp & 1 ? 16 : 1);
2473 FuncLiteralDeclaration *fld = fd->isFuncLiteralDeclaration();
2474 if (tret)
2475 rs->exp = inferType(rs->exp, tret);
2476 else if (fld && fld->treq)
2477 rs->exp = inferType(rs->exp, fld->treq->nextOf()->nextOf());
2478 rs->exp = semantic(rs->exp, sc);
2480 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
2481 if (rs->exp->op == TOKtype)
2482 rs->exp = resolveAliasThis(sc, rs->exp);
2484 rs->exp = resolveProperties(sc, rs->exp);
2485 if (rs->exp->checkType())
2486 rs->exp = new ErrorExp();
2487 if (FuncDeclaration *f = isFuncAddress(rs->exp))
2489 if (fd->inferRetType && f->checkForwardRef(rs->exp->loc))
2490 rs->exp = new ErrorExp();
2492 if (checkNonAssignmentArrayOp(rs->exp))
2493 rs->exp = new ErrorExp();
2495 // Extract side-effect part
2496 rs->exp = Expression::extractLast(rs->exp, &e0);
2497 if (rs->exp->op == TOKcall)
2498 rs->exp = valueNoDtor(rs->exp);
2500 if (e0)
2501 e0 = e0->optimize(WANTvalue);
2503 /* Void-return function can have void typed expression
2504 * on return statement.
2506 if ((tbret && tbret->ty == Tvoid) || rs->exp->type->ty == Tvoid)
2508 if (rs->exp->type->ty != Tvoid)
2510 rs->error("cannot return non-void from void function");
2511 errors = true;
2513 rs->exp = new CastExp(rs->loc, rs->exp, Type::tvoid);
2514 rs->exp = semantic(rs->exp, sc);
2517 /* Replace:
2518 * return exp;
2519 * with:
2520 * exp; return;
2522 e0 = Expression::combine(e0, rs->exp);
2523 rs->exp = NULL;
2525 if (e0)
2526 e0 = checkGC(sc, e0);
2529 if (rs->exp)
2531 if (fd->inferRetType) // infer return type
2533 if (!tret)
2535 tf->next = rs->exp->type;
2537 else if (tret->ty != Terror && !rs->exp->type->equals(tret))
2539 int m1 = rs->exp->type->implicitConvTo(tret);
2540 int m2 = tret->implicitConvTo(rs->exp->type);
2541 //printf("exp->type = %s m2<-->m1 tret %s\n", rs->exp->type->toChars(), tret->toChars());
2542 //printf("m1 = %d, m2 = %d\n", m1, m2);
2544 if (m1 && m2)
2546 else if (!m1 && m2)
2547 tf->next = rs->exp->type;
2548 else if (m1 && !m2)
2550 else if (rs->exp->op != TOKerror)
2552 rs->error("mismatched function return type inference of %s and %s",
2553 rs->exp->type->toChars(), tret->toChars());
2554 errors = true;
2555 tf->next = Type::terror;
2559 tret = tf->next;
2560 tbret = tret->toBasetype();
2563 if (inferRef) // deduce 'auto ref'
2565 /* Determine "refness" of function return:
2566 * if it's an lvalue, return by ref, else return by value
2568 if (rs->exp->isLvalue())
2570 /* May return by ref
2572 if (checkReturnEscapeRef(sc, rs->exp, true))
2573 tf->isref = false; // return by value
2575 else
2576 tf->isref = false; // return by value
2578 /* The "refness" is determined by all of return statements.
2579 * This means:
2580 * return 3; return x; // ok, x can be a value
2581 * return x; return 3; // ok, x can be a value
2585 // handle NRVO
2586 if (fd->nrvo_can && rs->exp->op == TOKvar)
2588 VarExp *ve = (VarExp *)rs->exp;
2589 VarDeclaration *v = ve->var->isVarDeclaration();
2591 if (tf->isref)
2593 // Function returns a reference
2594 if (!inferRef)
2595 fd->nrvo_can = 0;
2597 else if (!v || v->isOut() || v->isRef())
2598 fd->nrvo_can = 0;
2599 else if (fd->nrvo_var == NULL)
2601 if (!v->isDataseg() && !v->isParameter() && v->toParent2() == fd)
2603 //printf("Setting nrvo to %s\n", v->toChars());
2604 fd->nrvo_var = v;
2606 else
2607 fd->nrvo_can = 0;
2609 else if (fd->nrvo_var != v)
2610 fd->nrvo_can = 0;
2612 else //if (!exp->isLvalue()) // keep NRVO-ability
2613 fd->nrvo_can = 0;
2615 else
2617 // handle NRVO
2618 fd->nrvo_can = 0;
2620 // infer return type
2621 if (fd->inferRetType)
2623 if (tf->next && tf->next->ty != Tvoid)
2625 if (tf->next->ty != Terror)
2627 rs->error("mismatched function return type inference of void and %s",
2628 tf->next->toChars());
2630 errors = true;
2631 tf->next = Type::terror;
2633 else
2634 tf->next = Type::tvoid;
2636 tret = tf->next;
2637 tbret = tret->toBasetype();
2640 if (inferRef) // deduce 'auto ref'
2641 tf->isref = false;
2643 if (tbret->ty != Tvoid) // if non-void return
2645 if (tbret->ty != Terror)
2646 rs->error("return expression expected");
2647 errors = true;
2649 else if (fd->isMain())
2651 // main() returns 0, even if it returns void
2652 rs->exp = new IntegerExp(0);
2656 // If any branches have called a ctor, but this branch hasn't, it's an error
2657 if (sc->callSuper & CSXany_ctor &&
2658 !(sc->callSuper & (CSXthis_ctor | CSXsuper_ctor)))
2660 rs->error("return without calling constructor");
2661 errors = true;
2663 sc->callSuper |= CSXreturn;
2664 if (sc->fieldinit)
2666 AggregateDeclaration *ad = fd->isMember2();
2667 assert(ad);
2668 size_t dim = sc->fieldinit_dim;
2669 for (size_t i = 0; i < dim; i++)
2671 VarDeclaration *v = ad->fields[i];
2672 bool mustInit = (v->storage_class & STCnodefaultctor ||
2673 v->type->needsNested());
2674 if (mustInit && !(sc->fieldinit[i] & CSXthis_ctor))
2676 rs->error("an earlier return statement skips field %s initialization", v->toChars());
2677 errors = true;
2679 sc->fieldinit[i] |= CSXreturn;
2683 if (errors)
2684 return setError();
2686 if (sc->fes)
2688 if (!rs->exp)
2690 // Send out "case receiver" statement to the foreach.
2691 // return exp;
2692 Statement *s = new ReturnStatement(Loc(), rs->exp);
2693 sc->fes->cases->push(s);
2695 // Immediately rewrite "this" return statement as:
2696 // return cases->dim+1;
2697 rs->exp = new IntegerExp(sc->fes->cases->dim + 1);
2698 if (e0)
2700 result = new CompoundStatement(rs->loc, new ExpStatement(rs->loc, e0), rs);
2701 return;
2703 result = rs;
2704 return;
2706 else
2708 fd->buildResultVar(NULL, rs->exp->type);
2709 bool r = fd->vresult->checkNestedReference(sc, Loc());
2710 assert(!r); // vresult should be always accessible
2712 // Send out "case receiver" statement to the foreach.
2713 // return vresult;
2714 Statement *s = new ReturnStatement(Loc(), new VarExp(Loc(), fd->vresult));
2715 sc->fes->cases->push(s);
2717 // Save receiver index for the later rewriting from:
2718 // return exp;
2719 // to:
2720 // vresult = exp; retrun caseDim;
2721 rs->caseDim = sc->fes->cases->dim + 1;
2724 if (rs->exp)
2726 if (!fd->returns)
2727 fd->returns = new ReturnStatements();
2728 fd->returns->push(rs);
2730 if (e0)
2732 result = new CompoundStatement(rs->loc, new ExpStatement(rs->loc, e0), rs);
2733 return;
2735 result = rs;
2738 void visit(BreakStatement *bs)
2740 //printf("BreakStatement::semantic()\n");
2741 // If:
2742 // break Identifier;
2743 if (bs->ident)
2745 bs->ident = fixupLabelName(sc, bs->ident);
2747 FuncDeclaration *thisfunc = sc->func;
2749 for (Scope *scx = sc; scx; scx = scx->enclosing)
2751 if (scx->func != thisfunc) // if in enclosing function
2753 if (sc->fes) // if this is the body of a foreach
2755 /* Post this statement to the fes, and replace
2756 * it with a return value that caller will put into
2757 * a switch. Caller will figure out where the break
2758 * label actually is.
2759 * Case numbers start with 2, not 0, as 0 is continue
2760 * and 1 is break.
2762 sc->fes->cases->push(bs);
2763 result = new ReturnStatement(Loc(), new IntegerExp(sc->fes->cases->dim + 1));
2764 return;
2766 break; // can't break to it
2769 LabelStatement *ls = scx->slabel;
2770 if (ls && ls->ident == bs->ident)
2772 Statement *s = ls->statement;
2774 if (!s || !s->hasBreak())
2775 bs->error("label '%s' has no break", bs->ident->toChars());
2776 else if (ls->tf != sc->tf)
2777 bs->error("cannot break out of finally block");
2778 else
2780 ls->breaks = true;
2781 result = bs;
2782 return;
2784 return setError();
2787 bs->error("enclosing label '%s' for break not found", bs->ident->toChars());
2788 return setError();
2790 else if (!sc->sbreak)
2792 if (sc->os && sc->os->tok != TOKon_scope_failure)
2794 bs->error("break is not inside %s bodies", Token::toChars(sc->os->tok));
2796 else if (sc->fes)
2798 // Replace break; with return 1;
2799 result = new ReturnStatement(Loc(), new IntegerExp(1));
2800 return;
2802 else
2803 bs->error("break is not inside a loop or switch");
2804 return setError();
2806 result = bs;
2809 void visit(ContinueStatement *cs)
2811 //printf("ContinueStatement::semantic() %p\n", cs);
2812 if (cs->ident)
2814 cs->ident = fixupLabelName(sc, cs->ident);
2816 Scope *scx;
2817 FuncDeclaration *thisfunc = sc->func;
2819 for (scx = sc; scx; scx = scx->enclosing)
2821 LabelStatement *ls;
2823 if (scx->func != thisfunc) // if in enclosing function
2825 if (sc->fes) // if this is the body of a foreach
2827 for (; scx; scx = scx->enclosing)
2829 ls = scx->slabel;
2830 if (ls && ls->ident == cs->ident && ls->statement == sc->fes)
2832 // Replace continue ident; with return 0;
2833 result = new ReturnStatement(Loc(), new IntegerExp(0));
2834 return;
2838 /* Post this statement to the fes, and replace
2839 * it with a return value that caller will put into
2840 * a switch. Caller will figure out where the break
2841 * label actually is.
2842 * Case numbers start with 2, not 0, as 0 is continue
2843 * and 1 is break.
2845 sc->fes->cases->push(cs);
2846 result = new ReturnStatement(Loc(), new IntegerExp(sc->fes->cases->dim + 1));
2847 return;
2849 break; // can't continue to it
2852 ls = scx->slabel;
2853 if (ls && ls->ident == cs->ident)
2855 Statement *s = ls->statement;
2857 if (!s || !s->hasContinue())
2858 cs->error("label '%s' has no continue", cs->ident->toChars());
2859 else if (ls->tf != sc->tf)
2860 cs->error("cannot continue out of finally block");
2861 else
2863 result = cs;
2864 return;
2866 return setError();
2869 cs->error("enclosing label '%s' for continue not found", cs->ident->toChars());
2870 return setError();
2872 else if (!sc->scontinue)
2874 if (sc->os && sc->os->tok != TOKon_scope_failure)
2876 cs->error("continue is not inside %s bodies", Token::toChars(sc->os->tok));
2878 else if (sc->fes)
2880 // Replace continue; with return 0;
2881 result = new ReturnStatement(Loc(), new IntegerExp(0));
2882 return;
2884 else
2885 cs->error("continue is not inside a loop");
2886 return setError();
2888 result = cs;
2891 void visit(SynchronizedStatement *ss)
2893 if (ss->exp)
2895 ss->exp = semantic(ss->exp, sc);
2896 ss->exp = resolveProperties(sc, ss->exp);
2897 ss->exp = ss->exp->optimize(WANTvalue);
2898 ss->exp = checkGC(sc, ss->exp);
2899 if (ss->exp->op == TOKerror)
2900 goto Lbody;
2901 ClassDeclaration *cd = ss->exp->type->isClassHandle();
2902 if (!cd)
2904 ss->error("can only synchronize on class objects, not '%s'", ss->exp->type->toChars());
2905 return setError();
2907 else if (cd->isInterfaceDeclaration())
2909 /* Cast the interface to an object, as the object has the monitor,
2910 * not the interface.
2912 if (!ClassDeclaration::object)
2914 ss->error("missing or corrupt object.d");
2915 fatal();
2918 Type *t = ClassDeclaration::object->type;
2919 t = t->semantic(Loc(), sc)->toBasetype();
2920 assert(t->ty == Tclass);
2922 ss->exp = new CastExp(ss->loc, ss->exp, t);
2923 ss->exp = semantic(ss->exp, sc);
2926 /* Rewrite as:
2927 * auto tmp = exp;
2928 * _d_monitorenter(tmp);
2929 * try { body } finally { _d_monitorexit(tmp); }
2931 VarDeclaration *tmp = copyToTemp(0, "__sync", ss->exp);
2933 Statements *cs = new Statements();
2934 cs->push(new ExpStatement(ss->loc, tmp));
2936 Parameters* args = new Parameters;
2937 args->push(new Parameter(0, ClassDeclaration::object->type, NULL, NULL));
2939 FuncDeclaration *fdenter = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorenter);
2940 Expression *e = new CallExp(ss->loc, new VarExp(ss->loc, fdenter, false), new VarExp(ss->loc, tmp));
2941 e->type = Type::tvoid; // do not run semantic on e
2942 cs->push(new ExpStatement(ss->loc, e));
2944 FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorexit);
2945 e = new CallExp(ss->loc, new VarExp(ss->loc, fdexit, false), new VarExp(ss->loc, tmp));
2946 e->type = Type::tvoid; // do not run semantic on e
2947 Statement *s = new ExpStatement(ss->loc, e);
2948 s = new TryFinallyStatement(ss->loc, ss->_body, s);
2949 cs->push(s);
2951 s = new CompoundStatement(ss->loc, cs);
2952 result = semantic(s, sc);
2953 return;
2955 else
2957 /* Generate our own critical section, then rewrite as:
2958 * __gshared byte[CriticalSection.sizeof] critsec;
2959 * _d_criticalenter(critsec.ptr);
2960 * try { body } finally { _d_criticalexit(critsec.ptr); }
2962 Identifier *id = Identifier::generateId("__critsec");
2963 Type *t = Type::tint8->sarrayOf(Target::ptrsize + Target::critsecsize());
2964 VarDeclaration *tmp = new VarDeclaration(ss->loc, t, id, NULL);
2965 tmp->storage_class |= STCtemp | STCgshared | STCstatic;
2967 Statements *cs = new Statements();
2968 cs->push(new ExpStatement(ss->loc, tmp));
2970 /* This is just a dummy variable for "goto skips declaration" error.
2971 * Backend optimizer could remove this unused variable.
2973 VarDeclaration *v = new VarDeclaration(ss->loc, Type::tvoidptr, Identifier::generateId("__sync"), NULL);
2974 v->semantic(sc);
2975 cs->push(new ExpStatement(ss->loc, v));
2977 Parameters* args = new Parameters;
2978 args->push(new Parameter(0, t->pointerTo(), NULL, NULL));
2980 FuncDeclaration *fdenter = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalenter, STCnothrow);
2981 Expression *e = new DotIdExp(ss->loc, new VarExp(ss->loc, tmp), Id::ptr);
2982 e = semantic(e, sc);
2983 e = new CallExp(ss->loc, new VarExp(ss->loc, fdenter, false), e);
2984 e->type = Type::tvoid; // do not run semantic on e
2985 cs->push(new ExpStatement(ss->loc, e));
2987 FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalexit, STCnothrow);
2988 e = new DotIdExp(ss->loc, new VarExp(ss->loc, tmp), Id::ptr);
2989 e = semantic(e, sc);
2990 e = new CallExp(ss->loc, new VarExp(ss->loc, fdexit, false), e);
2991 e->type = Type::tvoid; // do not run semantic on e
2992 Statement *s = new ExpStatement(ss->loc, e);
2993 s = new TryFinallyStatement(ss->loc, ss->_body, s);
2994 cs->push(s);
2996 s = new CompoundStatement(ss->loc, cs);
2997 result = semantic(s, sc);
2998 return;
3000 Lbody:
3001 if (ss->_body)
3002 ss->_body = semantic(ss->_body, sc);
3003 if (ss->_body && ss->_body->isErrorStatement())
3005 result = ss->_body;
3006 return;
3008 result = ss;
3011 void visit(WithStatement *ws)
3013 ScopeDsymbol *sym;
3014 Initializer *init;
3016 //printf("WithStatement::semantic()\n");
3017 ws->exp = semantic(ws->exp, sc);
3018 ws->exp = resolveProperties(sc, ws->exp);
3019 ws->exp = ws->exp->optimize(WANTvalue);
3020 ws->exp = checkGC(sc, ws->exp);
3021 if (ws->exp->op == TOKerror)
3022 return setError();
3023 if (ws->exp->op == TOKscope)
3025 sym = new WithScopeSymbol(ws);
3026 sym->parent = sc->scopesym;
3027 sym->endlinnum = ws->endloc.linnum;
3029 else if (ws->exp->op == TOKtype)
3031 Dsymbol *s = ((TypeExp *)ws->exp)->type->toDsymbol(sc);
3032 if (!s || !s->isScopeDsymbol())
3034 ws->error("with type %s has no members", ws->exp->toChars());
3035 return setError();
3037 sym = new WithScopeSymbol(ws);
3038 sym->parent = sc->scopesym;
3039 sym->endlinnum = ws->endloc.linnum;
3041 else
3043 Type *t = ws->exp->type->toBasetype();
3045 Expression *olde = ws->exp;
3046 if (t->ty == Tpointer)
3048 ws->exp = new PtrExp(ws->loc, ws->exp);
3049 ws->exp = semantic(ws->exp, sc);
3050 t = ws->exp->type->toBasetype();
3053 assert(t);
3054 t = t->toBasetype();
3055 if (t->isClassHandle())
3057 init = new ExpInitializer(ws->loc, ws->exp);
3058 ws->wthis = new VarDeclaration(ws->loc, ws->exp->type, Id::withSym, init);
3059 ws->wthis->semantic(sc);
3061 sym = new WithScopeSymbol(ws);
3062 sym->parent = sc->scopesym;
3063 sym->endlinnum = ws->endloc.linnum;
3065 else if (t->ty == Tstruct)
3067 if (!ws->exp->isLvalue())
3069 /* Re-write to
3071 * auto __withtmp = exp
3072 * with(__withtmp)
3074 * ...
3078 VarDeclaration *tmp = copyToTemp(0, "__withtmp", ws->exp);
3079 ExpStatement *es = new ExpStatement(ws->loc, tmp);
3080 ws->exp = new VarExp(ws->loc, tmp);
3081 Statement *ss = new ScopeStatement(ws->loc, new CompoundStatement(ws->loc, es, ws), ws->endloc);
3082 result = semantic(ss, sc);
3083 return;
3085 Expression *e = ws->exp->addressOf();
3086 init = new ExpInitializer(ws->loc, e);
3087 ws->wthis = new VarDeclaration(ws->loc, e->type, Id::withSym, init);
3088 ws->wthis->semantic(sc);
3089 sym = new WithScopeSymbol(ws);
3090 // Need to set the scope to make use of resolveAliasThis
3091 sym->setScope(sc);
3092 sym->parent = sc->scopesym;
3093 sym->endlinnum = ws->endloc.linnum;
3095 else
3097 ws->error("with expressions must be aggregate types or pointers to them, not '%s'", olde->type->toChars());
3098 return setError();
3102 if (ws->_body)
3104 sym->_scope = sc;
3105 sc = sc->push(sym);
3106 sc->insert(sym);
3107 ws->_body = semantic(ws->_body, sc);
3108 sc->pop();
3109 if (ws->_body && ws->_body->isErrorStatement())
3111 result = ws->_body;
3112 return;
3116 result = ws;
3119 void visit(TryCatchStatement *tcs)
3121 unsigned flags = 0;
3122 const unsigned FLAGcpp = 1;
3123 const unsigned FLAGd = 2;
3125 tcs->_body = semanticScope(tcs->_body, sc, NULL, NULL);
3126 assert(tcs->_body);
3128 /* Even if body is empty, still do semantic analysis on catches
3130 bool catchErrors = false;
3131 for (size_t i = 0; i < tcs->catches->dim; i++)
3133 Catch *c = (*tcs->catches)[i];
3134 semantic(c, sc);
3135 if (c->errors)
3137 catchErrors = true;
3138 continue;
3140 ClassDeclaration *cd = c->type->toBasetype()->isClassHandle();
3141 flags |= cd->isCPPclass() ? FLAGcpp : FLAGd;
3143 // Determine if current catch 'hides' any previous catches
3144 for (size_t j = 0; j < i; j++)
3146 Catch *cj = (*tcs->catches)[j];
3147 const char *si = c->loc.toChars();
3148 const char *sj = cj->loc.toChars();
3150 if (c->type->toBasetype()->implicitConvTo(cj->type->toBasetype()))
3152 tcs->error("catch at %s hides catch at %s", sj, si);
3153 catchErrors = true;
3158 if (sc->func)
3160 if (flags == (FLAGcpp | FLAGd))
3162 tcs->error("cannot mix catching D and C++ exceptions in the same try-catch");
3163 catchErrors = true;
3167 if (catchErrors)
3168 return setError();
3170 if (tcs->_body->isErrorStatement())
3172 result = tcs->_body;
3173 return;
3176 /* If the try body never throws, we can eliminate any catches
3177 * of recoverable exceptions.
3180 if (!(blockExit(tcs->_body, sc->func, false) & BEthrow) && ClassDeclaration::exception)
3182 for (size_t i = 0; i < tcs->catches->dim; i++)
3184 Catch *c = (*tcs->catches)[i];
3186 /* If catch exception type is derived from Exception
3188 if (c->type->toBasetype()->implicitConvTo(ClassDeclaration::exception->type) &&
3189 (!c->handler || !c->handler->comeFrom()))
3191 // Remove c from the array of catches
3192 tcs->catches->remove(i);
3193 --i;
3198 if (tcs->catches->dim == 0)
3200 result = tcs->_body->hasCode() ? tcs->_body : NULL;
3201 return;
3204 result = tcs;
3207 void visit(TryFinallyStatement *tfs)
3209 //printf("TryFinallyStatement::semantic()\n");
3210 tfs->_body = semantic(tfs->_body, sc);
3211 sc = sc->push();
3212 sc->tf = tfs;
3213 sc->sbreak = NULL;
3214 sc->scontinue = NULL; // no break or continue out of finally block
3215 tfs->finalbody = semanticNoScope(tfs->finalbody, sc);
3216 sc->pop();
3218 if (!tfs->_body)
3220 result = tfs->finalbody;
3221 return;
3224 if (!tfs->finalbody)
3226 result = tfs->_body;
3227 return;
3230 if (blockExit(tfs->_body, sc->func, false) == BEfallthru)
3232 result = new CompoundStatement(tfs->loc, tfs->_body, tfs->finalbody);
3233 return;
3235 result = tfs;
3238 void visit(OnScopeStatement *oss)
3240 #ifndef IN_GCC
3241 if (oss->tok != TOKon_scope_exit)
3243 // scope(success) and scope(failure) are rewritten to try-catch(-finally) statement,
3244 // so the generated catch block cannot be placed in finally block.
3245 // See also Catch::semantic.
3246 if (sc->os && sc->os->tok != TOKon_scope_failure)
3248 // If enclosing is scope(success) or scope(exit), this will be placed in finally block.
3249 oss->error("cannot put %s statement inside %s", Token::toChars(oss->tok), Token::toChars(sc->os->tok));
3250 return setError();
3252 if (sc->tf)
3254 oss->error("cannot put %s statement inside finally block", Token::toChars(oss->tok));
3255 return setError();
3258 #endif
3260 sc = sc->push();
3261 sc->tf = NULL;
3262 sc->os = oss;
3263 if (oss->tok != TOKon_scope_failure)
3265 // Jump out from scope(failure) block is allowed.
3266 sc->sbreak = NULL;
3267 sc->scontinue = NULL;
3269 oss->statement = semanticNoScope(oss->statement, sc);
3270 sc->pop();
3272 if (!oss->statement || oss->statement->isErrorStatement())
3274 result = oss->statement;
3275 return;
3277 result = oss;
3280 void visit(ThrowStatement *ts)
3282 //printf("ThrowStatement::semantic()\n");
3284 FuncDeclaration *fd = sc->parent->isFuncDeclaration();
3285 fd->hasReturnExp |= 2;
3287 ts->exp = semantic(ts->exp, sc);
3288 ts->exp = resolveProperties(sc, ts->exp);
3289 ts->exp = checkGC(sc, ts->exp);
3290 if (ts->exp->op == TOKerror)
3291 return setError();
3293 checkThrowEscape(sc, ts->exp, false);
3295 ClassDeclaration *cd = ts->exp->type->toBasetype()->isClassHandle();
3296 if (!cd || ((cd != ClassDeclaration::throwable) && !ClassDeclaration::throwable->isBaseOf(cd, NULL)))
3298 ts->error("can only throw class objects derived from Throwable, not type %s", ts->exp->type->toChars());
3299 return setError();
3302 result = ts;
3305 void visit(DebugStatement *ds)
3307 if (ds->statement)
3309 sc = sc->push();
3310 sc->flags |= SCOPEdebug;
3311 ds->statement = semantic(ds->statement, sc);
3312 sc->pop();
3314 result = ds->statement;
3317 void visit(GotoStatement *gs)
3319 //printf("GotoStatement::semantic()\n");
3320 FuncDeclaration *fd = sc->func;
3322 gs->ident = fixupLabelName(sc, gs->ident);
3323 gs->label = fd->searchLabel(gs->ident);
3324 gs->tf = sc->tf;
3325 gs->os = sc->os;
3326 gs->lastVar = sc->lastVar;
3328 if (!gs->label->statement && sc->fes)
3330 /* Either the goto label is forward referenced or it
3331 * is in the function that the enclosing foreach is in.
3332 * Can't know yet, so wrap the goto in a scope statement
3333 * so we can patch it later, and add it to a 'look at this later'
3334 * list.
3336 ScopeStatement *ss = new ScopeStatement(gs->loc, gs, gs->loc);
3337 sc->fes->gotos->push(ss); // 'look at this later' list
3338 result = ss;
3339 return;
3342 // Add to fwdref list to check later
3343 if (!gs->label->statement)
3345 if (!fd->gotos)
3346 fd->gotos = new GotoStatements();
3347 fd->gotos->push(gs);
3349 else if (gs->checkLabel())
3350 return setError();
3352 result = gs;
3355 void visit(LabelStatement *ls)
3357 //printf("LabelStatement::semantic()\n");
3358 FuncDeclaration *fd = sc->parent->isFuncDeclaration();
3360 ls->ident = fixupLabelName(sc, ls->ident);
3361 ls->tf = sc->tf;
3362 ls->os = sc->os;
3363 ls->lastVar = sc->lastVar;
3365 LabelDsymbol *ls2 = fd->searchLabel(ls->ident);
3366 if (ls2->statement)
3368 ls->error("label '%s' already defined", ls2->toChars());
3369 return setError();
3371 else
3372 ls2->statement = ls;
3374 sc = sc->push();
3375 sc->scopesym = sc->enclosing->scopesym;
3376 sc->callSuper |= CSXlabel;
3377 if (sc->fieldinit)
3379 size_t dim = sc->fieldinit_dim;
3380 for (size_t i = 0; i < dim; i++)
3381 sc->fieldinit[i] |= CSXlabel;
3383 sc->slabel = ls;
3384 if (ls->statement)
3385 ls->statement = semantic(ls->statement, sc);
3386 sc->pop();
3388 result = ls;
3391 void visit(AsmStatement *s)
3393 result = asmSemantic(s, sc);
3396 void visit(CompoundAsmStatement *cas)
3398 // Apply postfix attributes of the asm block to each statement.
3399 sc = sc->push();
3400 sc->stc |= cas->stc;
3402 for (size_t i = 0; i < cas->statements->dim; i++)
3404 Statement *s = (*cas->statements)[i];
3405 (*cas->statements)[i] = s ? semantic(s, sc) : NULL;
3408 assert(sc->func);
3409 // use setImpure/setGC when the deprecation cycle is over
3410 PURE purity;
3411 if (!(cas->stc & STCpure) && (purity = sc->func->isPureBypassingInference()) != PUREimpure && purity != PUREfwdref)
3412 cas->deprecation("asm statement is assumed to be impure - mark it with 'pure' if it is not");
3413 if (!(cas->stc & STCnogc) && sc->func->isNogcBypassingInference())
3414 cas->deprecation("asm statement is assumed to use the GC - mark it with '@nogc' if it does not");
3415 if (!(cas->stc & (STCtrusted|STCsafe)) && sc->func->setUnsafe())
3416 cas->error("asm statement is assumed to be @system - mark it with '@trusted' if it is not");
3418 sc->pop();
3419 result = cas;
3422 void visit(ImportStatement *imps)
3424 for (size_t i = 0; i < imps->imports->dim; i++)
3426 Import *s = (*imps->imports)[i]->isImport();
3427 assert(!s->aliasdecls.dim);
3428 for (size_t j = 0; j < s->names.dim; j++)
3430 Identifier *name = s->names[j];
3431 Identifier *alias = s->aliases[j];
3433 if (!alias)
3434 alias = name;
3436 TypeIdentifier *tname = new TypeIdentifier(s->loc, name);
3437 AliasDeclaration *ad = new AliasDeclaration(s->loc, alias, tname);
3438 ad->_import = s;
3439 s->aliasdecls.push(ad);
3442 s->semantic(sc);
3443 Module::addDeferredSemantic2(s); // Bugzilla 14666
3444 sc->insert(s);
3446 for (size_t j = 0; j < s->aliasdecls.dim; j++)
3448 sc->insert(s->aliasdecls[j]);
3451 result = imps;
3455 Statement *semantic(Statement *s, Scope *sc)
3457 StatementSemanticVisitor v = StatementSemanticVisitor(sc);
3458 s->accept(&v);
3459 return v.result;
3462 void semantic(Catch *c, Scope *sc)
3464 //printf("Catch::semantic(%s)\n", ident->toChars());
3466 #ifndef IN_GCC
3467 if (sc->os && sc->os->tok != TOKon_scope_failure)
3469 // If enclosing is scope(success) or scope(exit), this will be placed in finally block.
3470 error(c->loc, "cannot put catch statement inside %s", Token::toChars(sc->os->tok));
3471 c->errors = true;
3473 if (sc->tf)
3475 /* This is because the _d_local_unwind() gets the stack munged
3476 * up on this. The workaround is to place any try-catches into
3477 * a separate function, and call that.
3478 * To fix, have the compiler automatically convert the finally
3479 * body into a nested function.
3481 error(c->loc, "cannot put catch statement inside finally block");
3482 c->errors = true;
3484 #endif
3486 ScopeDsymbol *sym = new ScopeDsymbol();
3487 sym->parent = sc->scopesym;
3488 sc = sc->push(sym);
3490 if (!c->type)
3492 deprecation(c->loc, "catch statement without an exception specification is deprecated; use catch(Throwable) for old behavior");
3494 // reference .object.Throwable
3495 c->type = getThrowable();
3497 c->type = c->type->semantic(c->loc, sc);
3498 if (c->type == Type::terror)
3499 c->errors = true;
3500 else
3502 ClassDeclaration *cd = c->type->toBasetype()->isClassHandle();
3503 if (!cd)
3505 error(c->loc, "can only catch class objects, not '%s'", c->type->toChars());
3506 c->errors = true;
3508 else if (cd->isCPPclass())
3510 if (!Target::cppExceptions)
3512 error(c->loc, "catching C++ class objects not supported for this target");
3513 c->errors = true;
3515 if (sc->func && !sc->intypeof && !c->internalCatch && sc->func->setUnsafe())
3517 error(c->loc, "cannot catch C++ class objects in @safe code");
3518 c->errors = true;
3521 else if (cd != ClassDeclaration::throwable && !ClassDeclaration::throwable->isBaseOf(cd, NULL))
3523 error(c->loc, "can only catch class objects derived from Throwable, not '%s'", c->type->toChars());
3524 c->errors = true;
3526 else if (sc->func && !sc->intypeof && !c->internalCatch &&
3527 cd != ClassDeclaration::exception && !ClassDeclaration::exception->isBaseOf(cd, NULL) &&
3528 sc->func->setUnsafe())
3530 error(c->loc, "can only catch class objects derived from Exception in @safe code, not '%s'", c->type->toChars());
3531 c->errors = true;
3534 if (c->ident)
3536 c->var = new VarDeclaration(c->loc, c->type, c->ident, NULL);
3537 c->var->semantic(sc);
3538 sc->insert(c->var);
3540 c->handler = semantic(c->handler, sc);
3541 if (c->handler && c->handler->isErrorStatement())
3542 c->errors = true;
3544 sc->pop();
3547 Statement *semanticNoScope(Statement *s, Scope *sc)
3549 //printf("Statement::semanticNoScope() %s\n", toChars());
3550 if (!s->isCompoundStatement() && !s->isScopeStatement())
3552 s = new CompoundStatement(s->loc, s); // so scopeCode() gets called
3554 s = semantic(s, sc);
3555 return s;
3558 // Same as semanticNoScope(), but do create a new scope
3559 Statement *semanticScope(Statement *s, Scope *sc, Statement *sbreak, Statement *scontinue)
3561 ScopeDsymbol *sym = new ScopeDsymbol();
3562 sym->parent = sc->scopesym;
3563 Scope *scd = sc->push(sym);
3564 if (sbreak)
3565 scd->sbreak = sbreak;
3566 if (scontinue)
3567 scd->scontinue = scontinue;
3568 s = semanticNoScope(s, scd);
3569 scd->pop();
3570 return s;