1
2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
4 * written by Walter Bright
5 * http://www.digitalmars.com
6 * Distributed under the Boost Software License, Version 1.0.
7 * http://www.boost.org/LICENSE_1_0.txt
8 * https://github.com/D-Programming-Language/dmd/blob/master/src/statement.c
9 */
10
11 #include "root/dsystem.h"
12
13 #include "statement.h"
14 #include "errors.h"
15 #include "expression.h"
16 #include "cond.h"
17 #include "init.h"
18 #include "staticassert.h"
19 #include "scope.h"
20 #include "declaration.h"
21 #include "aggregate.h"
22 #include "id.h"
23 #include "hdrgen.h"
24 #include "parse.h"
25 #include "template.h"
26 #include "attrib.h"
27 #include "import.h"
28
29 bool walkPostorder(Statement *s, StoppableVisitor *v);
30 StorageClass mergeFuncAttrs(StorageClass s1, FuncDeclaration *f);
31 bool checkEscapeRef(Scope *sc, Expression *e, bool gag);
32 VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e);
33 Expression *semantic(Expression *e, Scope *sc);
34 StringExp *semanticString(Scope *sc, Expression *exp, const char *s);
35 Statement *makeTupleForeachStatic(Scope *sc, ForeachStatement *fs, bool needExpansion);
36
fixupLabelName(Scope * sc,Identifier * ident)37 Identifier *fixupLabelName(Scope *sc, Identifier *ident)
38 {
39 unsigned flags = (sc->flags & SCOPEcontract);
40 const char *id = ident->toChars();
41 if (flags && flags != SCOPEinvariant &&
42 !(id[0] == '_' && id[1] == '_'))
43 {
44 /* CTFE requires FuncDeclaration::labtab for the interpretation.
45 * So fixing the label name inside in/out contracts is necessary
46 * for the uniqueness in labtab.
47 */
48 const char *prefix = flags == SCOPErequire ? "__in_" : "__out_";
49 OutBuffer buf;
50 buf.printf("%s%s", prefix, ident->toChars());
51
52 const char *name = buf.extractString();
53 ident = Identifier::idPool(name);
54 }
55 return ident;
56 }
57
checkLabeledLoop(Scope * sc,Statement * statement)58 LabelStatement *checkLabeledLoop(Scope *sc, Statement *statement)
59 {
60 if (sc->slabel && sc->slabel->statement == statement)
61 {
62 return sc->slabel;
63 }
64 return NULL;
65 }
66
67 /***********************************************************
68 * Check an assignment is used as a condition.
69 * Intended to be use before the `semantic` call on `e`.
70 * Params:
71 * e = condition expression which is not yet run semantic analysis.
72 * Returns:
73 * `e` or ErrorExp.
74 */
checkAssignmentAsCondition(Expression * e)75 Expression *checkAssignmentAsCondition(Expression *e)
76 {
77 Expression *ec = e;
78 while (ec->op == TOKcomma)
79 ec = ((CommaExp *)ec)->e2;
80 if (ec->op == TOKassign)
81 {
82 ec->error("assignment cannot be used as a condition, perhaps == was meant?");
83 return new ErrorExp();
84 }
85 return e;
86 }
87
88 /// Return a type identifier reference to 'object.Throwable'
getThrowable()89 TypeIdentifier *getThrowable()
90 {
91 TypeIdentifier *tid = new TypeIdentifier(Loc(), Id::empty);
92 tid->addIdent(Id::object);
93 tid->addIdent(Id::Throwable);
94 return tid;
95 }
96
97 /******************************** Statement ***************************/
98
Statement(Loc loc)99 Statement::Statement(Loc loc)
100 : loc(loc)
101 {
102 // If this is an in{} contract scope statement (skip for determining
103 // inlineStatus of a function body for header content)
104 }
105
syntaxCopy()106 Statement *Statement::syntaxCopy()
107 {
108 assert(0);
109 return NULL;
110 }
111
print()112 void Statement::print()
113 {
114 fprintf(stderr, "%s\n", toChars());
115 fflush(stderr);
116 }
117
toChars()118 const char *Statement::toChars()
119 {
120 HdrGenState hgs;
121
122 OutBuffer buf;
123 ::toCBuffer(this, &buf, &hgs);
124 return buf.extractString();
125 }
126
127
error(const char * format,...)128 void Statement::error(const char *format, ...)
129 {
130 va_list ap;
131 va_start(ap, format);
132 ::verror(loc, format, ap);
133 va_end( ap );
134 }
135
warning(const char * format,...)136 void Statement::warning(const char *format, ...)
137 {
138 va_list ap;
139 va_start(ap, format);
140 ::vwarning(loc, format, ap);
141 va_end( ap );
142 }
143
deprecation(const char * format,...)144 void Statement::deprecation(const char *format, ...)
145 {
146 va_list ap;
147 va_start(ap, format);
148 ::vdeprecation(loc, format, ap);
149 va_end( ap );
150 }
151
hasBreak()152 bool Statement::hasBreak()
153 {
154 //printf("Statement::hasBreak()\n");
155 return false;
156 }
157
hasContinue()158 bool Statement::hasContinue()
159 {
160 return false;
161 }
162
163 /* ============================================== */
164 // true if statement uses exception handling
165
usesEH()166 bool Statement::usesEH()
167 {
168 class UsesEH : public StoppableVisitor
169 {
170 public:
171 void visit(Statement *) {}
172 void visit(TryCatchStatement *) { stop = true; }
173 void visit(TryFinallyStatement *) { stop = true; }
174 void visit(OnScopeStatement *) { stop = true; }
175 void visit(SynchronizedStatement *) { stop = true; }
176 };
177
178 UsesEH ueh;
179 return walkPostorder(this, &ueh);
180 }
181
182 /* ============================================== */
183 // true if statement 'comes from' somewhere else, like a goto
184
comeFrom()185 bool Statement::comeFrom()
186 {
187 class ComeFrom : public StoppableVisitor
188 {
189 public:
190 void visit(Statement *) {}
191 void visit(CaseStatement *) { stop = true; }
192 void visit(DefaultStatement *) { stop = true; }
193 void visit(LabelStatement *) { stop = true; }
194 void visit(AsmStatement *) { stop = true; }
195 };
196
197 ComeFrom cf;
198 return walkPostorder(this, &cf);
199 }
200
201 /* ============================================== */
202 // Return true if statement has executable code.
203
hasCode()204 bool Statement::hasCode()
205 {
206 class HasCode : public StoppableVisitor
207 {
208 public:
209 void visit(Statement *)
210 {
211 stop = true;
212 }
213
214 void visit(ExpStatement *s)
215 {
216 if (s->exp != NULL)
217 {
218 stop = s->exp->hasCode();
219 }
220 }
221
222 void visit(CompoundStatement *) {}
223 void visit(ScopeStatement *) {}
224 void visit(ImportStatement *) {}
225 };
226
227 HasCode hc;
228 return walkPostorder(this, &hc);
229 }
230
last()231 Statement *Statement::last()
232 {
233 return this;
234 }
235
236 /****************************************
237 * If this statement has code that needs to run in a finally clause
238 * at the end of the current scope, return that code in the form of
239 * a Statement.
240 * Output:
241 * *sentry code executed upon entry to the scope
242 * *sexception code executed upon exit from the scope via exception
243 * *sfinally code executed in finally block
244 */
245
scopeCode(Scope *,Statement ** sentry,Statement ** sexception,Statement ** sfinally)246 Statement *Statement::scopeCode(Scope *, Statement **sentry, Statement **sexception, Statement **sfinally)
247 {
248 //printf("Statement::scopeCode()\n");
249 //print();
250 *sentry = NULL;
251 *sexception = NULL;
252 *sfinally = NULL;
253 return this;
254 }
255
256 /*********************************
257 * Flatten out the scope by presenting the statement
258 * as an array of statements.
259 * Returns NULL if no flattening necessary.
260 */
261
flatten(Scope *)262 Statements *Statement::flatten(Scope *)
263 {
264 return NULL;
265 }
266
267
268 /******************************** ErrorStatement ***************************/
269
ErrorStatement()270 ErrorStatement::ErrorStatement()
271 : Statement(Loc())
272 {
273 assert(global.gaggedErrors || global.errors);
274 }
275
syntaxCopy()276 Statement *ErrorStatement::syntaxCopy()
277 {
278 return this;
279 }
280
281 /******************************** PeelStatement ***************************/
282
PeelStatement(Statement * s)283 PeelStatement::PeelStatement(Statement *s)
284 : Statement(s->loc)
285 {
286 this->s = s;
287 }
288
289 /******************************** ExpStatement ***************************/
290
ExpStatement(Loc loc,Expression * exp)291 ExpStatement::ExpStatement(Loc loc, Expression *exp)
292 : Statement(loc)
293 {
294 this->exp = exp;
295 }
296
ExpStatement(Loc loc,Dsymbol * declaration)297 ExpStatement::ExpStatement(Loc loc, Dsymbol *declaration)
298 : Statement(loc)
299 {
300 this->exp = new DeclarationExp(loc, declaration);
301 }
302
create(Loc loc,Expression * exp)303 ExpStatement *ExpStatement::create(Loc loc, Expression *exp)
304 {
305 return new ExpStatement(loc, exp);
306 }
307
syntaxCopy()308 Statement *ExpStatement::syntaxCopy()
309 {
310 return new ExpStatement(loc, exp ? exp->syntaxCopy() : NULL);
311 }
312
scopeCode(Scope *,Statement ** sentry,Statement ** sexception,Statement ** sfinally)313 Statement *ExpStatement::scopeCode(Scope *, Statement **sentry, Statement **sexception, Statement **sfinally)
314 {
315 //printf("ExpStatement::scopeCode()\n");
316 //print();
317
318 *sentry = NULL;
319 *sexception = NULL;
320 *sfinally = NULL;
321
322 if (exp)
323 {
324 if (exp->op == TOKdeclaration)
325 {
326 DeclarationExp *de = (DeclarationExp *)(exp);
327 VarDeclaration *v = de->declaration->isVarDeclaration();
328 if (v && !v->isDataseg())
329 {
330 if (v->needsScopeDtor())
331 {
332 //printf("dtor is: "); v->edtor->print();
333 *sfinally = new DtorExpStatement(loc, v->edtor, v);
334 v->storage_class |= STCnodtor; // don't add in dtor again
335 }
336 }
337 }
338 }
339 return this;
340 }
341
342 /****************************************
343 * Convert TemplateMixin members (== Dsymbols) to Statements.
344 */
toStatement(Dsymbol * s)345 Statement *toStatement(Dsymbol *s)
346 {
347 class ToStmt : public Visitor
348 {
349 public:
350 Statement *result;
351
352 ToStmt()
353 {
354 this->result = NULL;
355 }
356
357 Statement *visitMembers(Loc loc, Dsymbols *a)
358 {
359 if (!a)
360 return NULL;
361
362 Statements *statements = new Statements();
363 for (size_t i = 0; i < a->dim; i++)
364 {
365 statements->push(toStatement((*a)[i]));
366 }
367 return new CompoundStatement(loc, statements);
368 }
369
370 void visit(Dsymbol *s)
371 {
372 ::error(Loc(), "Internal Compiler Error: cannot mixin %s %s\n", s->kind(), s->toChars());
373 result = new ErrorStatement();
374 }
375
376 void visit(TemplateMixin *tm)
377 {
378 Statements *a = new Statements();
379 for (size_t i = 0; i < tm->members->dim; i++)
380 {
381 Statement *s = toStatement((*tm->members)[i]);
382 if (s)
383 a->push(s);
384 }
385 result = new CompoundStatement(tm->loc, a);
386 }
387
388 /* An actual declaration symbol will be converted to DeclarationExp
389 * with ExpStatement.
390 */
391 Statement *declStmt(Dsymbol *s)
392 {
393 DeclarationExp *de = new DeclarationExp(s->loc, s);
394 de->type = Type::tvoid; // avoid repeated semantic
395 return new ExpStatement(s->loc, de);
396 }
397 void visit(VarDeclaration *d) { result = declStmt(d); }
398 void visit(AggregateDeclaration *d) { result = declStmt(d); }
399 void visit(FuncDeclaration *d) { result = declStmt(d); }
400 void visit(EnumDeclaration *d) { result = declStmt(d); }
401 void visit(AliasDeclaration *d) { result = declStmt(d); }
402 void visit(TemplateDeclaration *d) { result = declStmt(d); }
403
404 /* All attributes have been already picked by the semantic analysis of
405 * 'bottom' declarations (function, struct, class, etc).
406 * So we don't have to copy them.
407 */
408 void visit(StorageClassDeclaration *d) { result = visitMembers(d->loc, d->decl); }
409 void visit(DeprecatedDeclaration *d) { result = visitMembers(d->loc, d->decl); }
410 void visit(LinkDeclaration *d) { result = visitMembers(d->loc, d->decl); }
411 void visit(ProtDeclaration *d) { result = visitMembers(d->loc, d->decl); }
412 void visit(AlignDeclaration *d) { result = visitMembers(d->loc, d->decl); }
413 void visit(UserAttributeDeclaration *d) { result = visitMembers(d->loc, d->decl); }
414 void visit(ForwardingAttribDeclaration *d) { result = visitMembers(d->loc, d->decl); }
415
416 void visit(StaticAssert *) {}
417 void visit(Import *) {}
418 void visit(PragmaDeclaration *) {}
419
420 void visit(ConditionalDeclaration *d)
421 {
422 result = visitMembers(d->loc, d->include(NULL, NULL));
423 }
424
425 void visit(StaticForeachDeclaration *d)
426 {
427 assert(d->sfe && !!d->sfe->aggrfe ^ !!d->sfe->rangefe);
428 result = visitMembers(d->loc, d->include(NULL, NULL));
429 }
430
431 void visit(CompileDeclaration *d)
432 {
433 result = visitMembers(d->loc, d->include(NULL, NULL));
434 }
435 };
436
437 if (!s)
438 return NULL;
439
440 ToStmt v;
441 s->accept(&v);
442 return v.result;
443 }
444
flatten(Scope * sc)445 Statements *ExpStatement::flatten(Scope *sc)
446 {
447 /* Bugzilla 14243: expand template mixin in statement scope
448 * to handle variable destructors.
449 */
450 if (exp && exp->op == TOKdeclaration)
451 {
452 Dsymbol *d = ((DeclarationExp *)exp)->declaration;
453 if (TemplateMixin *tm = d->isTemplateMixin())
454 {
455 Expression *e = semantic(exp, sc);
456 if (e->op == TOKerror || tm->errors)
457 {
458 Statements *a = new Statements();
459 a->push(new ErrorStatement());
460 return a;
461 }
462 assert(tm->members);
463
464 Statement *s = toStatement(tm);
465 Statements *a = new Statements();
466 a->push(s);
467 return a;
468 }
469 }
470 return NULL;
471 }
472
473 /******************************** DtorExpStatement ***************************/
474
DtorExpStatement(Loc loc,Expression * exp,VarDeclaration * v)475 DtorExpStatement::DtorExpStatement(Loc loc, Expression *exp, VarDeclaration *v)
476 : ExpStatement(loc, exp)
477 {
478 this->var = v;
479 }
480
syntaxCopy()481 Statement *DtorExpStatement::syntaxCopy()
482 {
483 return new DtorExpStatement(loc, exp ? exp->syntaxCopy() : NULL, var);
484 }
485
486 /******************************** CompileStatement ***************************/
487
CompileStatement(Loc loc,Expression * exp)488 CompileStatement::CompileStatement(Loc loc, Expression *exp)
489 : Statement(loc)
490 {
491 this->exp = exp;
492 }
493
syntaxCopy()494 Statement *CompileStatement::syntaxCopy()
495 {
496 return new CompileStatement(loc, exp->syntaxCopy());
497 }
498
errorStatements()499 static Statements *errorStatements()
500 {
501 Statements *a = new Statements();
502 a->push(new ErrorStatement());
503 return a;
504 }
505
flatten(Scope * sc)506 Statements *CompileStatement::flatten(Scope *sc)
507 {
508 //printf("CompileStatement::flatten() %s\n", exp->toChars());
509 StringExp *se = semanticString(sc, exp, "argument to mixin");
510 if (!se)
511 return errorStatements();
512 se = se->toUTF8(sc);
513
514 unsigned errors = global.errors;
515 Parser p(loc, sc->_module, (utf8_t *)se->string, se->len, 0);
516 p.nextToken();
517
518 Statements *a = new Statements();
519 while (p.token.value != TOKeof)
520 {
521 Statement *s = p.parseStatement(PSsemi | PScurlyscope);
522 if (!s || p.errors)
523 {
524 assert(!p.errors || global.errors != errors); // make sure we caught all the cases
525 return errorStatements();
526 }
527 a->push(s);
528 }
529 return a;
530 }
531
532 /******************************** CompoundStatement ***************************/
533
CompoundStatement(Loc loc,Statements * s)534 CompoundStatement::CompoundStatement(Loc loc, Statements *s)
535 : Statement(loc)
536 {
537 statements = s;
538 }
539
CompoundStatement(Loc loc,Statement * s1,Statement * s2)540 CompoundStatement::CompoundStatement(Loc loc, Statement *s1, Statement *s2)
541 : Statement(loc)
542 {
543 statements = new Statements();
544 statements->reserve(2);
545 statements->push(s1);
546 statements->push(s2);
547 }
548
CompoundStatement(Loc loc,Statement * s1)549 CompoundStatement::CompoundStatement(Loc loc, Statement *s1)
550 : Statement(loc)
551 {
552 statements = new Statements();
553 statements->push(s1);
554 }
555
create(Loc loc,Statement * s1,Statement * s2)556 CompoundStatement *CompoundStatement::create(Loc loc, Statement *s1, Statement *s2)
557 {
558 return new CompoundStatement(loc, s1, s2);
559 }
560
syntaxCopy()561 Statement *CompoundStatement::syntaxCopy()
562 {
563 Statements *a = new Statements();
564 a->setDim(statements->dim);
565 for (size_t i = 0; i < statements->dim; i++)
566 {
567 Statement *s = (*statements)[i];
568 (*a)[i] = s ? s->syntaxCopy() : NULL;
569 }
570 return new CompoundStatement(loc, a);
571 }
572
flatten(Scope *)573 Statements *CompoundStatement::flatten(Scope *)
574 {
575 return statements;
576 }
577
isReturnStatement()578 ReturnStatement *CompoundStatement::isReturnStatement()
579 {
580 ReturnStatement *rs = NULL;
581
582 for (size_t i = 0; i < statements->dim; i++)
583 {
584 Statement *s = (*statements)[i];
585 if (s)
586 {
587 rs = s->isReturnStatement();
588 if (rs)
589 break;
590 }
591 }
592 return rs;
593 }
594
last()595 Statement *CompoundStatement::last()
596 {
597 Statement *s = NULL;
598
599 for (size_t i = statements->dim; i; --i)
600 { s = (*statements)[i - 1];
601 if (s)
602 {
603 s = s->last();
604 if (s)
605 break;
606 }
607 }
608 return s;
609 }
610
611 /******************************** CompoundDeclarationStatement ***************************/
612
CompoundDeclarationStatement(Loc loc,Statements * s)613 CompoundDeclarationStatement::CompoundDeclarationStatement(Loc loc, Statements *s)
614 : CompoundStatement(loc, s)
615 {
616 statements = s;
617 }
618
syntaxCopy()619 Statement *CompoundDeclarationStatement::syntaxCopy()
620 {
621 Statements *a = new Statements();
622 a->setDim(statements->dim);
623 for (size_t i = 0; i < statements->dim; i++)
624 {
625 Statement *s = (*statements)[i];
626 (*a)[i] = s ? s->syntaxCopy() : NULL;
627 }
628 return new CompoundDeclarationStatement(loc, a);
629 }
630
631 /**************************** UnrolledLoopStatement ***************************/
632
UnrolledLoopStatement(Loc loc,Statements * s)633 UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s)
634 : Statement(loc)
635 {
636 statements = s;
637 }
638
syntaxCopy()639 Statement *UnrolledLoopStatement::syntaxCopy()
640 {
641 Statements *a = new Statements();
642 a->setDim(statements->dim);
643 for (size_t i = 0; i < statements->dim; i++)
644 {
645 Statement *s = (*statements)[i];
646 (*a)[i] = s ? s->syntaxCopy() : NULL;
647 }
648 return new UnrolledLoopStatement(loc, a);
649 }
650
hasBreak()651 bool UnrolledLoopStatement::hasBreak()
652 {
653 return true;
654 }
655
hasContinue()656 bool UnrolledLoopStatement::hasContinue()
657 {
658 return true;
659 }
660
661 /******************************** ScopeStatement ***************************/
662
ScopeStatement(Loc loc,Statement * s,Loc endloc)663 ScopeStatement::ScopeStatement(Loc loc, Statement *s, Loc endloc)
664 : Statement(loc)
665 {
666 this->statement = s;
667 this->endloc = endloc;
668 }
669
syntaxCopy()670 Statement *ScopeStatement::syntaxCopy()
671 {
672 return new ScopeStatement(loc, statement ? statement->syntaxCopy() : NULL, endloc);
673 }
674
isReturnStatement()675 ReturnStatement *ScopeStatement::isReturnStatement()
676 {
677 if (statement)
678 return statement->isReturnStatement();
679 return NULL;
680 }
681
hasBreak()682 bool ScopeStatement::hasBreak()
683 {
684 //printf("ScopeStatement::hasBreak() %s\n", toChars());
685 return statement ? statement->hasBreak() : false;
686 }
687
hasContinue()688 bool ScopeStatement::hasContinue()
689 {
690 return statement ? statement->hasContinue() : false;
691 }
692
693 /******************************** ForwardingStatement **********************/
694
695 /* Statement whose symbol table contains foreach index variables in a
696 * local scope and forwards other members to the parent scope. This
697 * wraps a statement.
698 *
699 * Also see: `ddmd.attrib.ForwardingAttribDeclaration`
700 */
701
ForwardingStatement(Loc loc,ForwardingScopeDsymbol * sym,Statement * s)702 ForwardingStatement::ForwardingStatement(Loc loc, ForwardingScopeDsymbol *sym, Statement *s)
703 : Statement(loc)
704 {
705 this->sym = sym;
706 assert(s);
707 this->statement = s;
708 }
709
ForwardingStatement(Loc loc,Statement * s)710 ForwardingStatement::ForwardingStatement(Loc loc, Statement *s)
711 : Statement(loc)
712 {
713 this->sym = new ForwardingScopeDsymbol(NULL);
714 this->sym->symtab = new DsymbolTable();
715 assert(s);
716 this->statement = s;
717 }
718
syntaxCopy()719 Statement *ForwardingStatement::syntaxCopy()
720 {
721 return new ForwardingStatement(loc, statement->syntaxCopy());
722 }
723
724 /***********************
725 * ForwardingStatements are distributed over the flattened
726 * sequence of statements. This prevents flattening to be
727 * "blocked" by a ForwardingStatement and is necessary, for
728 * example, to support generating scope guards with `static
729 * foreach`:
730 *
731 * static foreach(i; 0 .. 10) scope(exit) writeln(i);
732 * writeln("this is printed first");
733 * // then, it prints 10, 9, 8, 7, ...
734 */
735
flatten(Scope * sc)736 Statements *ForwardingStatement::flatten(Scope *sc)
737 {
738 if (!statement)
739 {
740 return NULL;
741 }
742 sc = sc->push(sym);
743 Statements *a = statement->flatten(sc);
744 sc = sc->pop();
745 if (!a)
746 {
747 return a;
748 }
749 Statements *b = new Statements();
750 b->setDim(a->dim);
751 for (size_t i = 0; i < a->dim; i++)
752 {
753 Statement *s = (*a)[i];
754 (*b)[i] = s ? new ForwardingStatement(s->loc, sym, s) : NULL;
755 }
756 return b;
757 }
758
759 /******************************** WhileStatement ***************************/
760
WhileStatement(Loc loc,Expression * c,Statement * b,Loc endloc)761 WhileStatement::WhileStatement(Loc loc, Expression *c, Statement *b, Loc endloc)
762 : Statement(loc)
763 {
764 condition = c;
765 _body = b;
766 this->endloc = endloc;
767 }
768
syntaxCopy()769 Statement *WhileStatement::syntaxCopy()
770 {
771 return new WhileStatement(loc,
772 condition->syntaxCopy(),
773 _body ? _body->syntaxCopy() : NULL,
774 endloc);
775 }
776
hasBreak()777 bool WhileStatement::hasBreak()
778 {
779 return true;
780 }
781
hasContinue()782 bool WhileStatement::hasContinue()
783 {
784 return true;
785 }
786
787 /******************************** DoStatement ***************************/
788
DoStatement(Loc loc,Statement * b,Expression * c,Loc endloc)789 DoStatement::DoStatement(Loc loc, Statement *b, Expression *c, Loc endloc)
790 : Statement(loc)
791 {
792 _body = b;
793 condition = c;
794 this->endloc = endloc;
795 }
796
syntaxCopy()797 Statement *DoStatement::syntaxCopy()
798 {
799 return new DoStatement(loc,
800 _body ? _body->syntaxCopy() : NULL,
801 condition->syntaxCopy(),
802 endloc);
803 }
804
hasBreak()805 bool DoStatement::hasBreak()
806 {
807 return true;
808 }
809
hasContinue()810 bool DoStatement::hasContinue()
811 {
812 return true;
813 }
814
815 /******************************** ForStatement ***************************/
816
ForStatement(Loc loc,Statement * init,Expression * condition,Expression * increment,Statement * body,Loc endloc)817 ForStatement::ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body, Loc endloc)
818 : Statement(loc)
819 {
820 this->_init = init;
821 this->condition = condition;
822 this->increment = increment;
823 this->_body = body;
824 this->endloc = endloc;
825 this->relatedLabeled = NULL;
826 }
827
syntaxCopy()828 Statement *ForStatement::syntaxCopy()
829 {
830 return new ForStatement(loc,
831 _init ? _init->syntaxCopy() : NULL,
832 condition ? condition->syntaxCopy() : NULL,
833 increment ? increment->syntaxCopy() : NULL,
834 _body->syntaxCopy(),
835 endloc);
836 }
837
scopeCode(Scope * sc,Statement ** sentry,Statement ** sexception,Statement ** sfinally)838 Statement *ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
839 {
840 //printf("ForStatement::scopeCode()\n");
841 Statement::scopeCode(sc, sentry, sexception, sfinally);
842 return this;
843 }
844
hasBreak()845 bool ForStatement::hasBreak()
846 {
847 //printf("ForStatement::hasBreak()\n");
848 return true;
849 }
850
hasContinue()851 bool ForStatement::hasContinue()
852 {
853 return true;
854 }
855
856 /******************************** ForeachStatement ***************************/
857
ForeachStatement(Loc loc,TOK op,Parameters * parameters,Expression * aggr,Statement * body,Loc endloc)858 ForeachStatement::ForeachStatement(Loc loc, TOK op, Parameters *parameters,
859 Expression *aggr, Statement *body, Loc endloc)
860 : Statement(loc)
861 {
862 this->op = op;
863 this->parameters = parameters;
864 this->aggr = aggr;
865 this->_body = body;
866 this->endloc = endloc;
867
868 this->key = NULL;
869 this->value = NULL;
870
871 this->func = NULL;
872
873 this->cases = NULL;
874 this->gotos = NULL;
875 }
876
syntaxCopy()877 Statement *ForeachStatement::syntaxCopy()
878 {
879 return new ForeachStatement(loc, op,
880 Parameter::arraySyntaxCopy(parameters),
881 aggr->syntaxCopy(),
882 _body ? _body->syntaxCopy() : NULL,
883 endloc);
884 }
885
checkForArgTypes()886 bool ForeachStatement::checkForArgTypes()
887 {
888 bool result = false;
889
890 for (size_t i = 0; i < parameters->dim; i++)
891 {
892 Parameter *p = (*parameters)[i];
893 if (!p->type)
894 {
895 error("cannot infer type for %s", p->ident->toChars());
896 p->type = Type::terror;
897 result = true;
898 }
899 }
900 return result;
901 }
902
hasBreak()903 bool ForeachStatement::hasBreak()
904 {
905 return true;
906 }
907
hasContinue()908 bool ForeachStatement::hasContinue()
909 {
910 return true;
911 }
912
913 /**************************** ForeachRangeStatement ***************************/
914
915
ForeachRangeStatement(Loc loc,TOK op,Parameter * prm,Expression * lwr,Expression * upr,Statement * body,Loc endloc)916 ForeachRangeStatement::ForeachRangeStatement(Loc loc, TOK op, Parameter *prm,
917 Expression *lwr, Expression *upr, Statement *body, Loc endloc)
918 : Statement(loc)
919 {
920 this->op = op;
921 this->prm = prm;
922 this->lwr = lwr;
923 this->upr = upr;
924 this->_body = body;
925 this->endloc = endloc;
926
927 this->key = NULL;
928 }
929
syntaxCopy()930 Statement *ForeachRangeStatement::syntaxCopy()
931 {
932 return new ForeachRangeStatement(loc, op,
933 prm->syntaxCopy(),
934 lwr->syntaxCopy(),
935 upr->syntaxCopy(),
936 _body ? _body->syntaxCopy() : NULL,
937 endloc);
938 }
939
hasBreak()940 bool ForeachRangeStatement::hasBreak()
941 {
942 return true;
943 }
944
hasContinue()945 bool ForeachRangeStatement::hasContinue()
946 {
947 return true;
948 }
949
950 /******************************** IfStatement ***************************/
951
IfStatement(Loc loc,Parameter * prm,Expression * condition,Statement * ifbody,Statement * elsebody,Loc endloc)952 IfStatement::IfStatement(Loc loc, Parameter *prm, Expression *condition, Statement *ifbody, Statement *elsebody, Loc endloc)
953 : Statement(loc)
954 {
955 this->prm = prm;
956 this->condition = condition;
957 this->ifbody = ifbody;
958 this->elsebody = elsebody;
959 this->endloc = endloc;
960 this->match = NULL;
961 }
962
syntaxCopy()963 Statement *IfStatement::syntaxCopy()
964 {
965 return new IfStatement(loc,
966 prm ? prm->syntaxCopy() : NULL,
967 condition->syntaxCopy(),
968 ifbody ? ifbody->syntaxCopy() : NULL,
969 elsebody ? elsebody->syntaxCopy() : NULL,
970 endloc);
971 }
972
973 /******************************** ConditionalStatement ***************************/
974
ConditionalStatement(Loc loc,Condition * condition,Statement * ifbody,Statement * elsebody)975 ConditionalStatement::ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody)
976 : Statement(loc)
977 {
978 this->condition = condition;
979 this->ifbody = ifbody;
980 this->elsebody = elsebody;
981 }
982
syntaxCopy()983 Statement *ConditionalStatement::syntaxCopy()
984 {
985 return new ConditionalStatement(loc,
986 condition->syntaxCopy(),
987 ifbody->syntaxCopy(),
988 elsebody ? elsebody->syntaxCopy() : NULL);
989 }
990
flatten(Scope * sc)991 Statements *ConditionalStatement::flatten(Scope *sc)
992 {
993 Statement *s;
994
995 //printf("ConditionalStatement::flatten()\n");
996 if (condition->include(sc, NULL))
997 {
998 DebugCondition *dc = condition->isDebugCondition();
999 if (dc)
1000 s = new DebugStatement(loc, ifbody);
1001 else
1002 s = ifbody;
1003 }
1004 else
1005 s = elsebody;
1006
1007 Statements *a = new Statements();
1008 a->push(s);
1009 return a;
1010 }
1011
1012 /******************************** StaticForeachStatement ********************/
1013
1014 /* Static foreach statements, like:
1015 * void main()
1016 * {
1017 * static foreach(i; 0 .. 10)
1018 * {
1019 * pragma(msg, i);
1020 * }
1021 * }
1022 */
1023
StaticForeachStatement(Loc loc,StaticForeach * sfe)1024 StaticForeachStatement::StaticForeachStatement(Loc loc, StaticForeach *sfe)
1025 : Statement(loc)
1026 {
1027 this->sfe = sfe;
1028 }
1029
syntaxCopy()1030 Statement *StaticForeachStatement::syntaxCopy()
1031 {
1032 return new StaticForeachStatement(loc, sfe->syntaxCopy());
1033 }
1034
flatten(Scope * sc)1035 Statements *StaticForeachStatement::flatten(Scope *sc)
1036 {
1037 staticForeachPrepare(sfe, sc);
1038 if (staticForeachReady(sfe))
1039 {
1040 Statement *s = makeTupleForeachStatic(sc, sfe->aggrfe, sfe->needExpansion);
1041 Statements *result = s->flatten(sc);
1042 if (result)
1043 {
1044 return result;
1045 }
1046 result = new Statements();
1047 result->push(s);
1048 return result;
1049 }
1050 else
1051 {
1052 Statements *result = new Statements();
1053 result->push(new ErrorStatement());
1054 return result;
1055 }
1056 }
1057
1058 /******************************** PragmaStatement ***************************/
1059
PragmaStatement(Loc loc,Identifier * ident,Expressions * args,Statement * body)1060 PragmaStatement::PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body)
1061 : Statement(loc)
1062 {
1063 this->ident = ident;
1064 this->args = args;
1065 this->_body = body;
1066 }
1067
syntaxCopy()1068 Statement *PragmaStatement::syntaxCopy()
1069 {
1070 return new PragmaStatement(loc, ident,
1071 Expression::arraySyntaxCopy(args),
1072 _body ? _body->syntaxCopy() : NULL);
1073 }
1074
1075 /******************************** StaticAssertStatement ***************************/
1076
StaticAssertStatement(StaticAssert * sa)1077 StaticAssertStatement::StaticAssertStatement(StaticAssert *sa)
1078 : Statement(sa->loc)
1079 {
1080 this->sa = sa;
1081 }
1082
syntaxCopy()1083 Statement *StaticAssertStatement::syntaxCopy()
1084 {
1085 return new StaticAssertStatement((StaticAssert *)sa->syntaxCopy(NULL));
1086 }
1087
1088 /******************************** SwitchStatement ***************************/
1089
SwitchStatement(Loc loc,Expression * c,Statement * b,bool isFinal)1090 SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b, bool isFinal)
1091 : Statement(loc)
1092 {
1093 this->condition = c;
1094 this->_body = b;
1095 this->isFinal = isFinal;
1096 sdefault = NULL;
1097 tf = NULL;
1098 cases = NULL;
1099 hasNoDefault = 0;
1100 hasVars = 0;
1101 lastVar = NULL;
1102 }
1103
syntaxCopy()1104 Statement *SwitchStatement::syntaxCopy()
1105 {
1106 return new SwitchStatement(loc,
1107 condition->syntaxCopy(),
1108 _body->syntaxCopy(),
1109 isFinal);
1110 }
1111
hasBreak()1112 bool SwitchStatement::hasBreak()
1113 {
1114 return true;
1115 }
1116
checkVar(SwitchStatement * s,VarDeclaration * vd)1117 static bool checkVar(SwitchStatement *s, VarDeclaration *vd)
1118 {
1119 if (!vd || vd->isDataseg() || (vd->storage_class & STCmanifest))
1120 return false;
1121
1122 VarDeclaration *last = s->lastVar;
1123 while (last && last != vd)
1124 last = last->lastVar;
1125 if (last == vd)
1126 {
1127 // All good, the label's scope has no variables
1128 }
1129 else if (vd->storage_class & STCexptemp)
1130 {
1131 // Lifetime ends at end of expression, so no issue with skipping the statement
1132 }
1133 else if (vd->ident == Id::withSym)
1134 {
1135 s->deprecation("'switch' skips declaration of 'with' temporary at %s", vd->loc.toChars());
1136 return true;
1137 }
1138 else
1139 {
1140 s->deprecation("'switch' skips declaration of variable %s at %s", vd->toPrettyChars(), vd->loc.toChars());
1141 return true;
1142 }
1143
1144 return false;
1145 }
1146
checkLabel()1147 bool SwitchStatement::checkLabel()
1148 {
1149 const bool error = true;
1150
1151 if (sdefault && checkVar(this, sdefault->lastVar))
1152 return !error; // return error once fully deprecated
1153
1154 for (size_t i = 0; i < cases->dim; i++)
1155 {
1156 CaseStatement *scase = (*cases)[i];
1157 if (scase && checkVar(this, scase->lastVar))
1158 return !error; // return error once fully deprecated
1159 }
1160 return !error;
1161 }
1162
1163 /******************************** CaseStatement ***************************/
1164
CaseStatement(Loc loc,Expression * exp,Statement * s)1165 CaseStatement::CaseStatement(Loc loc, Expression *exp, Statement *s)
1166 : Statement(loc)
1167 {
1168 this->exp = exp;
1169 this->statement = s;
1170 index = 0;
1171 lastVar = NULL;
1172 }
1173
syntaxCopy()1174 Statement *CaseStatement::syntaxCopy()
1175 {
1176 return new CaseStatement(loc,
1177 exp->syntaxCopy(),
1178 statement->syntaxCopy());
1179 }
1180
compare(RootObject * obj)1181 int CaseStatement::compare(RootObject *obj)
1182 {
1183 // Sort cases so we can do an efficient lookup
1184 CaseStatement *cs2 = (CaseStatement *)(obj);
1185
1186 return exp->compare(cs2->exp);
1187 }
1188
1189 /******************************** CaseRangeStatement ***************************/
1190
1191
CaseRangeStatement(Loc loc,Expression * first,Expression * last,Statement * s)1192 CaseRangeStatement::CaseRangeStatement(Loc loc, Expression *first,
1193 Expression *last, Statement *s)
1194 : Statement(loc)
1195 {
1196 this->first = first;
1197 this->last = last;
1198 this->statement = s;
1199 }
1200
syntaxCopy()1201 Statement *CaseRangeStatement::syntaxCopy()
1202 {
1203 return new CaseRangeStatement(loc,
1204 first->syntaxCopy(),
1205 last->syntaxCopy(),
1206 statement->syntaxCopy());
1207 }
1208
1209 /******************************** DefaultStatement ***************************/
1210
DefaultStatement(Loc loc,Statement * s)1211 DefaultStatement::DefaultStatement(Loc loc, Statement *s)
1212 : Statement(loc)
1213 {
1214 this->statement = s;
1215 this->lastVar = NULL;
1216 }
1217
syntaxCopy()1218 Statement *DefaultStatement::syntaxCopy()
1219 {
1220 return new DefaultStatement(loc, statement->syntaxCopy());
1221 }
1222
1223 /******************************** GotoDefaultStatement ***************************/
1224
GotoDefaultStatement(Loc loc)1225 GotoDefaultStatement::GotoDefaultStatement(Loc loc)
1226 : Statement(loc)
1227 {
1228 sw = NULL;
1229 }
1230
syntaxCopy()1231 Statement *GotoDefaultStatement::syntaxCopy()
1232 {
1233 return new GotoDefaultStatement(loc);
1234 }
1235
1236 /******************************** GotoCaseStatement ***************************/
1237
GotoCaseStatement(Loc loc,Expression * exp)1238 GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp)
1239 : Statement(loc)
1240 {
1241 cs = NULL;
1242 this->exp = exp;
1243 }
1244
syntaxCopy()1245 Statement *GotoCaseStatement::syntaxCopy()
1246 {
1247 return new GotoCaseStatement(loc, exp ? exp->syntaxCopy() : NULL);
1248 }
1249
1250 /******************************** SwitchErrorStatement ***************************/
1251
SwitchErrorStatement(Loc loc)1252 SwitchErrorStatement::SwitchErrorStatement(Loc loc)
1253 : Statement(loc)
1254 {
1255 }
1256
1257 /******************************** ReturnStatement ***************************/
1258
ReturnStatement(Loc loc,Expression * exp)1259 ReturnStatement::ReturnStatement(Loc loc, Expression *exp)
1260 : Statement(loc)
1261 {
1262 this->exp = exp;
1263 this->caseDim = 0;
1264 }
1265
syntaxCopy()1266 Statement *ReturnStatement::syntaxCopy()
1267 {
1268 return new ReturnStatement(loc, exp ? exp->syntaxCopy() : NULL);
1269 }
1270
1271 /******************************** BreakStatement ***************************/
1272
BreakStatement(Loc loc,Identifier * ident)1273 BreakStatement::BreakStatement(Loc loc, Identifier *ident)
1274 : Statement(loc)
1275 {
1276 this->ident = ident;
1277 }
1278
syntaxCopy()1279 Statement *BreakStatement::syntaxCopy()
1280 {
1281 return new BreakStatement(loc, ident);
1282 }
1283
1284 /******************************** ContinueStatement ***************************/
1285
ContinueStatement(Loc loc,Identifier * ident)1286 ContinueStatement::ContinueStatement(Loc loc, Identifier *ident)
1287 : Statement(loc)
1288 {
1289 this->ident = ident;
1290 }
1291
syntaxCopy()1292 Statement *ContinueStatement::syntaxCopy()
1293 {
1294 return new ContinueStatement(loc, ident);
1295 }
1296
1297 /******************************** SynchronizedStatement ***************************/
1298
SynchronizedStatement(Loc loc,Expression * exp,Statement * body)1299 SynchronizedStatement::SynchronizedStatement(Loc loc, Expression *exp, Statement *body)
1300 : Statement(loc)
1301 {
1302 this->exp = exp;
1303 this->_body = body;
1304 }
1305
syntaxCopy()1306 Statement *SynchronizedStatement::syntaxCopy()
1307 {
1308 return new SynchronizedStatement(loc,
1309 exp ? exp->syntaxCopy() : NULL,
1310 _body ? _body->syntaxCopy() : NULL);
1311 }
1312
hasBreak()1313 bool SynchronizedStatement::hasBreak()
1314 {
1315 return false; //true;
1316 }
1317
hasContinue()1318 bool SynchronizedStatement::hasContinue()
1319 {
1320 return false; //true;
1321 }
1322
1323 /******************************** WithStatement ***************************/
1324
WithStatement(Loc loc,Expression * exp,Statement * body,Loc endloc)1325 WithStatement::WithStatement(Loc loc, Expression *exp, Statement *body, Loc endloc)
1326 : Statement(loc)
1327 {
1328 this->exp = exp;
1329 this->_body = body;
1330 this->endloc = endloc;
1331 wthis = NULL;
1332 }
1333
syntaxCopy()1334 Statement *WithStatement::syntaxCopy()
1335 {
1336 return new WithStatement(loc,
1337 exp->syntaxCopy(),
1338 _body ? _body->syntaxCopy() : NULL, endloc);
1339 }
1340
1341 /******************************** TryCatchStatement ***************************/
1342
TryCatchStatement(Loc loc,Statement * body,Catches * catches)1343 TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Catches *catches)
1344 : Statement(loc)
1345 {
1346 this->_body = body;
1347 this->catches = catches;
1348 }
1349
syntaxCopy()1350 Statement *TryCatchStatement::syntaxCopy()
1351 {
1352 Catches *a = new Catches();
1353 a->setDim(catches->dim);
1354 for (size_t i = 0; i < a->dim; i++)
1355 {
1356 Catch *c = (*catches)[i];
1357 (*a)[i] = c->syntaxCopy();
1358 }
1359 return new TryCatchStatement(loc, _body->syntaxCopy(), a);
1360 }
1361
hasBreak()1362 bool TryCatchStatement::hasBreak()
1363 {
1364 return false;
1365 }
1366
1367 /******************************** Catch ***************************/
1368
Catch(Loc loc,Type * t,Identifier * id,Statement * handler)1369 Catch::Catch(Loc loc, Type *t, Identifier *id, Statement *handler)
1370 {
1371 //printf("Catch(%s, loc = %s)\n", id->toChars(), loc.toChars());
1372 this->loc = loc;
1373 this->type = t;
1374 this->ident = id;
1375 this->handler = handler;
1376 var = NULL;
1377 errors = false;
1378 internalCatch = false;
1379 }
1380
syntaxCopy()1381 Catch *Catch::syntaxCopy()
1382 {
1383 Catch *c = new Catch(loc,
1384 type ? type->syntaxCopy() : getThrowable(),
1385 ident,
1386 (handler ? handler->syntaxCopy() : NULL));
1387 c->internalCatch = internalCatch;
1388 return c;
1389 }
1390
1391 /****************************** TryFinallyStatement ***************************/
1392
TryFinallyStatement(Loc loc,Statement * body,Statement * finalbody)1393 TryFinallyStatement::TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody)
1394 : Statement(loc)
1395 {
1396 this->_body = body;
1397 this->finalbody = finalbody;
1398 }
1399
create(Loc loc,Statement * body,Statement * finalbody)1400 TryFinallyStatement *TryFinallyStatement::create(Loc loc, Statement *body, Statement *finalbody)
1401 {
1402 return new TryFinallyStatement(loc, body, finalbody);
1403 }
1404
syntaxCopy()1405 Statement *TryFinallyStatement::syntaxCopy()
1406 {
1407 return new TryFinallyStatement(loc,
1408 _body->syntaxCopy(), finalbody->syntaxCopy());
1409 }
1410
hasBreak()1411 bool TryFinallyStatement::hasBreak()
1412 {
1413 return false; //true;
1414 }
1415
hasContinue()1416 bool TryFinallyStatement::hasContinue()
1417 {
1418 return false; //true;
1419 }
1420
1421 /****************************** OnScopeStatement ***************************/
1422
OnScopeStatement(Loc loc,TOK tok,Statement * statement)1423 OnScopeStatement::OnScopeStatement(Loc loc, TOK tok, Statement *statement)
1424 : Statement(loc)
1425 {
1426 this->tok = tok;
1427 this->statement = statement;
1428 }
1429
syntaxCopy()1430 Statement *OnScopeStatement::syntaxCopy()
1431 {
1432 return new OnScopeStatement(loc, tok, statement->syntaxCopy());
1433 }
1434
scopeCode(Scope * sc,Statement ** sentry,Statement ** sexception,Statement ** sfinally)1435 Statement *OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
1436 {
1437 //printf("OnScopeStatement::scopeCode()\n");
1438 //print();
1439 *sentry = NULL;
1440 *sexception = NULL;
1441 *sfinally = NULL;
1442
1443 Statement *s = new PeelStatement(statement);
1444
1445 switch (tok)
1446 {
1447 case TOKon_scope_exit:
1448 *sfinally = s;
1449 break;
1450
1451 case TOKon_scope_failure:
1452 *sexception = s;
1453 break;
1454
1455 case TOKon_scope_success:
1456 {
1457 /* Create:
1458 * sentry: bool x = false;
1459 * sexception: x = true;
1460 * sfinally: if (!x) statement;
1461 */
1462 VarDeclaration *v = copyToTemp(0, "__os", new IntegerExp(Loc(), 0, Type::tbool));
1463 v->semantic(sc);
1464 *sentry = new ExpStatement(loc, v);
1465
1466 Expression *e = new IntegerExp(Loc(), 1, Type::tbool);
1467 e = new AssignExp(Loc(), new VarExp(Loc(), v), e);
1468 *sexception = new ExpStatement(Loc(), e);
1469
1470 e = new VarExp(Loc(), v);
1471 e = new NotExp(Loc(), e);
1472 *sfinally = new IfStatement(Loc(), NULL, e, s, NULL, Loc());
1473
1474 break;
1475 }
1476
1477 default:
1478 assert(0);
1479 }
1480 return NULL;
1481 }
1482
1483 /******************************** ThrowStatement ***************************/
1484
ThrowStatement(Loc loc,Expression * exp)1485 ThrowStatement::ThrowStatement(Loc loc, Expression *exp)
1486 : Statement(loc)
1487 {
1488 this->exp = exp;
1489 this->internalThrow = false;
1490 }
1491
syntaxCopy()1492 Statement *ThrowStatement::syntaxCopy()
1493 {
1494 ThrowStatement *s = new ThrowStatement(loc, exp->syntaxCopy());
1495 s->internalThrow = internalThrow;
1496 return s;
1497 }
1498
1499 /******************************** DebugStatement **************************/
1500
DebugStatement(Loc loc,Statement * statement)1501 DebugStatement::DebugStatement(Loc loc, Statement *statement)
1502 : Statement(loc)
1503 {
1504 this->statement = statement;
1505 }
1506
syntaxCopy()1507 Statement *DebugStatement::syntaxCopy()
1508 {
1509 return new DebugStatement(loc,
1510 statement ? statement->syntaxCopy() : NULL);
1511 }
1512
flatten(Scope * sc)1513 Statements *DebugStatement::flatten(Scope *sc)
1514 {
1515 Statements *a = statement ? statement->flatten(sc) : NULL;
1516 if (a)
1517 {
1518 for (size_t i = 0; i < a->dim; i++)
1519 { Statement *s = (*a)[i];
1520
1521 s = new DebugStatement(loc, s);
1522 (*a)[i] = s;
1523 }
1524 }
1525
1526 return a;
1527 }
1528
1529 /******************************** GotoStatement ***************************/
1530
GotoStatement(Loc loc,Identifier * ident)1531 GotoStatement::GotoStatement(Loc loc, Identifier *ident)
1532 : Statement(loc)
1533 {
1534 this->ident = ident;
1535 this->label = NULL;
1536 this->tf = NULL;
1537 this->os = NULL;
1538 this->lastVar = NULL;
1539 }
1540
syntaxCopy()1541 Statement *GotoStatement::syntaxCopy()
1542 {
1543 return new GotoStatement(loc, ident);
1544 }
1545
checkLabel()1546 bool GotoStatement::checkLabel()
1547 {
1548 if (!label->statement)
1549 {
1550 error("label '%s' is undefined", label->toChars());
1551 return true;
1552 }
1553
1554 if (label->statement->os != os)
1555 {
1556 if (os && os->tok == TOKon_scope_failure && !label->statement->os)
1557 {
1558 // Jump out from scope(failure) block is allowed.
1559 }
1560 else
1561 {
1562 if (label->statement->os)
1563 error("cannot goto in to %s block", Token::toChars(label->statement->os->tok));
1564 else
1565 error("cannot goto out of %s block", Token::toChars(os->tok));
1566 return true;
1567 }
1568 }
1569
1570 if (label->statement->tf != tf)
1571 {
1572 error("cannot goto in or out of finally block");
1573 return true;
1574 }
1575
1576 VarDeclaration *vd = label->statement->lastVar;
1577 if (!vd || vd->isDataseg() || (vd->storage_class & STCmanifest))
1578 return false;
1579
1580 VarDeclaration *last = lastVar;
1581 while (last && last != vd)
1582 last = last->lastVar;
1583 if (last == vd)
1584 {
1585 // All good, the label's scope has no variables
1586 }
1587 else if (vd->ident == Id::withSym)
1588 {
1589 error("goto skips declaration of with temporary at %s", vd->loc.toChars());
1590 return true;
1591 }
1592 else
1593 {
1594 error("goto skips declaration of variable %s at %s", vd->toPrettyChars(), vd->loc.toChars());
1595 return true;
1596 }
1597
1598 return false;
1599 }
1600
1601 /******************************** LabelStatement ***************************/
1602
LabelStatement(Loc loc,Identifier * ident,Statement * statement)1603 LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement)
1604 : Statement(loc)
1605 {
1606 this->ident = ident;
1607 this->statement = statement;
1608 this->tf = NULL;
1609 this->os = NULL;
1610 this->lastVar = NULL;
1611 this->gotoTarget = NULL;
1612 this->breaks = false;
1613 }
1614
syntaxCopy()1615 Statement *LabelStatement::syntaxCopy()
1616 {
1617 return new LabelStatement(loc, ident, statement ? statement->syntaxCopy() : NULL);
1618 }
1619
scopeCode(Scope * sc,Statement ** sentry,Statement ** sexit,Statement ** sfinally)1620 Statement *LabelStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally)
1621 {
1622 //printf("LabelStatement::scopeCode()\n");
1623 if (statement)
1624 statement = statement->scopeCode(sc, sentry, sexit, sfinally);
1625 else
1626 {
1627 *sentry = NULL;
1628 *sexit = NULL;
1629 *sfinally = NULL;
1630 }
1631 return this;
1632 }
1633
flatten(Scope * sc)1634 Statements *LabelStatement::flatten(Scope *sc)
1635 {
1636 Statements *a = NULL;
1637
1638 if (statement)
1639 {
1640 a = statement->flatten(sc);
1641 if (a)
1642 {
1643 if (!a->dim)
1644 {
1645 a->push(new ExpStatement(loc, (Expression *)NULL));
1646 }
1647
1648 // reuse 'this' LabelStatement
1649 this->statement = (*a)[0];
1650 (*a)[0] = this;
1651 }
1652 }
1653
1654 return a;
1655 }
1656
1657 /******************************** LabelDsymbol ***************************/
1658
LabelDsymbol(Identifier * ident)1659 LabelDsymbol::LabelDsymbol(Identifier *ident)
1660 : Dsymbol(ident)
1661 {
1662 statement = NULL;
1663 }
1664
create(Identifier * ident)1665 LabelDsymbol *LabelDsymbol::create(Identifier *ident)
1666 {
1667 return new LabelDsymbol(ident);
1668 }
1669
isLabel()1670 LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()?
1671 {
1672 return this;
1673 }
1674
1675
1676 /************************ AsmStatement ***************************************/
1677
AsmStatement(Loc loc,Token * tokens)1678 AsmStatement::AsmStatement(Loc loc, Token *tokens)
1679 : Statement(loc)
1680 {
1681 this->tokens = tokens;
1682 }
1683
syntaxCopy()1684 Statement *AsmStatement::syntaxCopy()
1685 {
1686 return new AsmStatement(loc, tokens);
1687 }
1688
1689
1690 /************************ InlineAsmStatement **********************************/
1691
InlineAsmStatement(Loc loc,Token * tokens)1692 InlineAsmStatement::InlineAsmStatement(Loc loc, Token *tokens)
1693 : AsmStatement(loc, tokens)
1694 {
1695 asmcode = NULL;
1696 asmalign = 0;
1697 refparam = false;
1698 naked = false;
1699 regs = 0;
1700 }
1701
syntaxCopy()1702 Statement *InlineAsmStatement::syntaxCopy()
1703 {
1704 return new InlineAsmStatement(loc, tokens);
1705 }
1706
1707
1708 /************************ GccAsmStatement ***************************************/
1709
GccAsmStatement(Loc loc,Token * tokens)1710 GccAsmStatement::GccAsmStatement(Loc loc, Token *tokens)
1711 : AsmStatement(loc, tokens)
1712 {
1713 this->stc = STCundefined;
1714 this->insn = NULL;
1715 this->args = NULL;
1716 this->outputargs = 0;
1717 this->names = NULL;
1718 this->constraints = NULL;
1719 this->clobbers = NULL;
1720 this->labels = NULL;
1721 this->gotos = NULL;
1722 }
1723
syntaxCopy()1724 Statement *GccAsmStatement::syntaxCopy()
1725 {
1726 return new GccAsmStatement(loc, tokens);
1727 }
1728
1729 /************************ CompoundAsmStatement ***************************************/
1730
CompoundAsmStatement(Loc loc,Statements * s,StorageClass stc)1731 CompoundAsmStatement::CompoundAsmStatement(Loc loc, Statements *s, StorageClass stc)
1732 : CompoundStatement(loc, s)
1733 {
1734 this->stc = stc;
1735 }
1736
syntaxCopy()1737 CompoundAsmStatement *CompoundAsmStatement::syntaxCopy()
1738 {
1739 Statements *a = new Statements();
1740 a->setDim(statements->dim);
1741 for (size_t i = 0; i < statements->dim; i++)
1742 {
1743 Statement *s = (*statements)[i];
1744 (*a)[i] = s ? s->syntaxCopy() : NULL;
1745 }
1746 return new CompoundAsmStatement(loc, a, stc);
1747 }
1748
flatten(Scope *)1749 Statements *CompoundAsmStatement::flatten(Scope *)
1750 {
1751 return NULL;
1752 }
1753
1754 /************************ ImportStatement ***************************************/
1755
ImportStatement(Loc loc,Dsymbols * imports)1756 ImportStatement::ImportStatement(Loc loc, Dsymbols *imports)
1757 : Statement(loc)
1758 {
1759 this->imports = imports;
1760 }
1761
syntaxCopy()1762 Statement *ImportStatement::syntaxCopy()
1763 {
1764 Dsymbols *m = new Dsymbols();
1765 m->setDim(imports->dim);
1766 for (size_t i = 0; i < imports->dim; i++)
1767 {
1768 Dsymbol *s = (*imports)[i];
1769 (*m)[i] = s->syntaxCopy(NULL);
1770 }
1771 return new ImportStatement(loc, m);
1772 }
1773