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