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