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