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
29bool walkPostorder(Statement *s, StoppableVisitor *v);
30StorageClass mergeFuncAttrs(StorageClass s1, FuncDeclaration *f);
31bool checkEscapeRef(Scope *sc, Expression *e, bool gag);
32VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e);
33Expression *semantic(Expression *e, Scope *sc);
34StringExp *semanticString(Scope *sc, Expression *exp, const char *s);
35Statement *makeTupleForeachStatic(Scope *sc, ForeachStatement *fs, bool needExpansion);
36
37Identifier *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
58LabelStatement *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 */
75Expression *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'
89TypeIdentifier *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
99Statement::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
106Statement *Statement::syntaxCopy()
107{
108    assert(0);
109    return NULL;
110}
111
112void Statement::print()
113{
114    fprintf(stderr, "%s\n", toChars());
115    fflush(stderr);
116}
117
118const char *Statement::toChars()
119{
120    HdrGenState hgs;
121
122    OutBuffer buf;
123    ::toCBuffer(this, &buf, &hgs);
124    return buf.extractString();
125}
126
127
128void 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
136void 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
144void 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
152bool Statement::hasBreak()
153{
154    //printf("Statement::hasBreak()\n");
155    return false;
156}
157
158bool Statement::hasContinue()
159{
160    return false;
161}
162
163/* ============================================== */
164// true if statement uses exception handling
165
166bool 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
185bool 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
204bool 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
231Statement *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
246Statement *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
262Statements *Statement::flatten(Scope *)
263{
264    return NULL;
265}
266
267
268/******************************** ErrorStatement ***************************/
269
270ErrorStatement::ErrorStatement()
271    : Statement(Loc())
272{
273    assert(global.gaggedErrors || global.errors);
274}
275
276Statement *ErrorStatement::syntaxCopy()
277{
278    return this;
279}
280
281/******************************** PeelStatement ***************************/
282
283PeelStatement::PeelStatement(Statement *s)
284    : Statement(s->loc)
285{
286    this->s = s;
287}
288
289/******************************** ExpStatement ***************************/
290
291ExpStatement::ExpStatement(Loc loc, Expression *exp)
292    : Statement(loc)
293{
294    this->exp = exp;
295}
296
297ExpStatement::ExpStatement(Loc loc, Dsymbol *declaration)
298    : Statement(loc)
299{
300    this->exp = new DeclarationExp(loc, declaration);
301}
302
303ExpStatement *ExpStatement::create(Loc loc, Expression *exp)
304{
305    return new ExpStatement(loc, exp);
306}
307
308Statement *ExpStatement::syntaxCopy()
309{
310    return new ExpStatement(loc, exp ? exp->syntaxCopy() : NULL);
311}
312
313Statement *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 */
345Statement *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
445Statements *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
475DtorExpStatement::DtorExpStatement(Loc loc, Expression *exp, VarDeclaration *v)
476    : ExpStatement(loc, exp)
477{
478    this->var = v;
479}
480
481Statement *DtorExpStatement::syntaxCopy()
482{
483    return new DtorExpStatement(loc, exp ? exp->syntaxCopy() : NULL, var);
484}
485
486/******************************** CompileStatement ***************************/
487
488CompileStatement::CompileStatement(Loc loc, Expression *exp)
489    : Statement(loc)
490{
491    this->exp = exp;
492}
493
494Statement *CompileStatement::syntaxCopy()
495{
496    return new CompileStatement(loc, exp->syntaxCopy());
497}
498
499static Statements *errorStatements()
500{
501    Statements *a = new Statements();
502    a->push(new ErrorStatement());
503    return a;
504}
505
506Statements *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
534CompoundStatement::CompoundStatement(Loc loc, Statements *s)
535    : Statement(loc)
536{
537    statements = s;
538}
539
540CompoundStatement::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
549CompoundStatement::CompoundStatement(Loc loc, Statement *s1)
550    : Statement(loc)
551{
552    statements = new Statements();
553    statements->push(s1);
554}
555
556CompoundStatement *CompoundStatement::create(Loc loc, Statement *s1, Statement *s2)
557{
558    return new CompoundStatement(loc, s1, s2);
559}
560
561Statement *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
573Statements *CompoundStatement::flatten(Scope *)
574{
575    return statements;
576}
577
578ReturnStatement *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
595Statement *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
613CompoundDeclarationStatement::CompoundDeclarationStatement(Loc loc, Statements *s)
614    : CompoundStatement(loc, s)
615{
616    statements = s;
617}
618
619Statement *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
633UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s)
634    : Statement(loc)
635{
636    statements = s;
637}
638
639Statement *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
651bool UnrolledLoopStatement::hasBreak()
652{
653    return true;
654}
655
656bool UnrolledLoopStatement::hasContinue()
657{
658    return true;
659}
660
661/******************************** ScopeStatement ***************************/
662
663ScopeStatement::ScopeStatement(Loc loc, Statement *s, Loc endloc)
664    : Statement(loc)
665{
666    this->statement = s;
667    this->endloc = endloc;
668}
669
670Statement *ScopeStatement::syntaxCopy()
671{
672    return new ScopeStatement(loc, statement ? statement->syntaxCopy() : NULL, endloc);
673}
674
675ReturnStatement *ScopeStatement::isReturnStatement()
676{
677    if (statement)
678        return statement->isReturnStatement();
679    return NULL;
680}
681
682bool ScopeStatement::hasBreak()
683{
684    //printf("ScopeStatement::hasBreak() %s\n", toChars());
685    return statement ? statement->hasBreak() : false;
686}
687
688bool 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
702ForwardingStatement::ForwardingStatement(Loc loc, ForwardingScopeDsymbol *sym, Statement *s)
703    : Statement(loc)
704{
705    this->sym = sym;
706    assert(s);
707    this->statement = s;
708}
709
710ForwardingStatement::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
719Statement *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
736Statements *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
761WhileStatement::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
769Statement *WhileStatement::syntaxCopy()
770{
771    return new WhileStatement(loc,
772        condition->syntaxCopy(),
773        _body ? _body->syntaxCopy() : NULL,
774        endloc);
775}
776
777bool WhileStatement::hasBreak()
778{
779    return true;
780}
781
782bool WhileStatement::hasContinue()
783{
784    return true;
785}
786
787/******************************** DoStatement ***************************/
788
789DoStatement::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
797Statement *DoStatement::syntaxCopy()
798{
799    return new DoStatement(loc,
800        _body ? _body->syntaxCopy() : NULL,
801        condition->syntaxCopy(),
802        endloc);
803}
804
805bool DoStatement::hasBreak()
806{
807    return true;
808}
809
810bool DoStatement::hasContinue()
811{
812    return true;
813}
814
815/******************************** ForStatement ***************************/
816
817ForStatement::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
828Statement *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
838Statement *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
845bool ForStatement::hasBreak()
846{
847    //printf("ForStatement::hasBreak()\n");
848    return true;
849}
850
851bool ForStatement::hasContinue()
852{
853    return true;
854}
855
856/******************************** ForeachStatement ***************************/
857
858ForeachStatement::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
877Statement *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
886bool 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
903bool ForeachStatement::hasBreak()
904{
905    return true;
906}
907
908bool ForeachStatement::hasContinue()
909{
910    return true;
911}
912
913/**************************** ForeachRangeStatement ***************************/
914
915
916ForeachRangeStatement::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
930Statement *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
940bool ForeachRangeStatement::hasBreak()
941{
942    return true;
943}
944
945bool ForeachRangeStatement::hasContinue()
946{
947    return true;
948}
949
950/******************************** IfStatement ***************************/
951
952IfStatement::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
963Statement *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
975ConditionalStatement::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
983Statement *ConditionalStatement::syntaxCopy()
984{
985    return new ConditionalStatement(loc,
986        condition->syntaxCopy(),
987        ifbody->syntaxCopy(),
988        elsebody ? elsebody->syntaxCopy() : NULL);
989}
990
991Statements *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
1024StaticForeachStatement::StaticForeachStatement(Loc loc, StaticForeach *sfe)
1025    : Statement(loc)
1026{
1027    this->sfe = sfe;
1028}
1029
1030Statement *StaticForeachStatement::syntaxCopy()
1031{
1032    return new StaticForeachStatement(loc, sfe->syntaxCopy());
1033}
1034
1035Statements *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
1060PragmaStatement::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
1068Statement *PragmaStatement::syntaxCopy()
1069{
1070    return new PragmaStatement(loc, ident,
1071        Expression::arraySyntaxCopy(args),
1072        _body ? _body->syntaxCopy() : NULL);
1073}
1074
1075/******************************** StaticAssertStatement ***************************/
1076
1077StaticAssertStatement::StaticAssertStatement(StaticAssert *sa)
1078    : Statement(sa->loc)
1079{
1080    this->sa = sa;
1081}
1082
1083Statement *StaticAssertStatement::syntaxCopy()
1084{
1085    return new StaticAssertStatement((StaticAssert *)sa->syntaxCopy(NULL));
1086}
1087
1088/******************************** SwitchStatement ***************************/
1089
1090SwitchStatement::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
1104Statement *SwitchStatement::syntaxCopy()
1105{
1106    return new SwitchStatement(loc,
1107        condition->syntaxCopy(),
1108        _body->syntaxCopy(),
1109        isFinal);
1110}
1111
1112bool SwitchStatement::hasBreak()
1113{
1114    return true;
1115}
1116
1117static 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
1147bool 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
1165CaseStatement::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
1174Statement *CaseStatement::syntaxCopy()
1175{
1176    return new CaseStatement(loc,
1177        exp->syntaxCopy(),
1178        statement->syntaxCopy());
1179}
1180
1181int 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
1192CaseRangeStatement::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
1201Statement *CaseRangeStatement::syntaxCopy()
1202{
1203    return new CaseRangeStatement(loc,
1204        first->syntaxCopy(),
1205        last->syntaxCopy(),
1206        statement->syntaxCopy());
1207}
1208
1209/******************************** DefaultStatement ***************************/
1210
1211DefaultStatement::DefaultStatement(Loc loc, Statement *s)
1212    : Statement(loc)
1213{
1214    this->statement = s;
1215    this->lastVar = NULL;
1216}
1217
1218Statement *DefaultStatement::syntaxCopy()
1219{
1220    return new DefaultStatement(loc, statement->syntaxCopy());
1221}
1222
1223/******************************** GotoDefaultStatement ***************************/
1224
1225GotoDefaultStatement::GotoDefaultStatement(Loc loc)
1226    : Statement(loc)
1227{
1228    sw = NULL;
1229}
1230
1231Statement *GotoDefaultStatement::syntaxCopy()
1232{
1233    return new GotoDefaultStatement(loc);
1234}
1235
1236/******************************** GotoCaseStatement ***************************/
1237
1238GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp)
1239    : Statement(loc)
1240{
1241    cs = NULL;
1242    this->exp = exp;
1243}
1244
1245Statement *GotoCaseStatement::syntaxCopy()
1246{
1247    return new GotoCaseStatement(loc, exp ? exp->syntaxCopy() : NULL);
1248}
1249
1250/******************************** SwitchErrorStatement ***************************/
1251
1252SwitchErrorStatement::SwitchErrorStatement(Loc loc)
1253    : Statement(loc)
1254{
1255}
1256
1257/******************************** ReturnStatement ***************************/
1258
1259ReturnStatement::ReturnStatement(Loc loc, Expression *exp)
1260    : Statement(loc)
1261{
1262    this->exp = exp;
1263    this->caseDim = 0;
1264}
1265
1266Statement *ReturnStatement::syntaxCopy()
1267{
1268    return new ReturnStatement(loc, exp ? exp->syntaxCopy() : NULL);
1269}
1270
1271/******************************** BreakStatement ***************************/
1272
1273BreakStatement::BreakStatement(Loc loc, Identifier *ident)
1274    : Statement(loc)
1275{
1276    this->ident = ident;
1277}
1278
1279Statement *BreakStatement::syntaxCopy()
1280{
1281    return new BreakStatement(loc, ident);
1282}
1283
1284/******************************** ContinueStatement ***************************/
1285
1286ContinueStatement::ContinueStatement(Loc loc, Identifier *ident)
1287    : Statement(loc)
1288{
1289    this->ident = ident;
1290}
1291
1292Statement *ContinueStatement::syntaxCopy()
1293{
1294    return new ContinueStatement(loc, ident);
1295}
1296
1297/******************************** SynchronizedStatement ***************************/
1298
1299SynchronizedStatement::SynchronizedStatement(Loc loc, Expression *exp, Statement *body)
1300    : Statement(loc)
1301{
1302    this->exp = exp;
1303    this->_body = body;
1304}
1305
1306Statement *SynchronizedStatement::syntaxCopy()
1307{
1308    return new SynchronizedStatement(loc,
1309        exp ? exp->syntaxCopy() : NULL,
1310        _body ? _body->syntaxCopy() : NULL);
1311}
1312
1313bool SynchronizedStatement::hasBreak()
1314{
1315    return false; //true;
1316}
1317
1318bool SynchronizedStatement::hasContinue()
1319{
1320    return false; //true;
1321}
1322
1323/******************************** WithStatement ***************************/
1324
1325WithStatement::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
1334Statement *WithStatement::syntaxCopy()
1335{
1336    return new WithStatement(loc,
1337        exp->syntaxCopy(),
1338        _body ? _body->syntaxCopy() : NULL, endloc);
1339}
1340
1341/******************************** TryCatchStatement ***************************/
1342
1343TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Catches *catches)
1344    : Statement(loc)
1345{
1346    this->_body = body;
1347    this->catches = catches;
1348}
1349
1350Statement *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
1362bool TryCatchStatement::hasBreak()
1363{
1364    return false;
1365}
1366
1367/******************************** Catch ***************************/
1368
1369Catch::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
1381Catch *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
1393TryFinallyStatement::TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody)
1394    : Statement(loc)
1395{
1396    this->_body = body;
1397    this->finalbody = finalbody;
1398}
1399
1400TryFinallyStatement *TryFinallyStatement::create(Loc loc, Statement *body, Statement *finalbody)
1401{
1402    return new TryFinallyStatement(loc, body, finalbody);
1403}
1404
1405Statement *TryFinallyStatement::syntaxCopy()
1406{
1407    return new TryFinallyStatement(loc,
1408        _body->syntaxCopy(), finalbody->syntaxCopy());
1409}
1410
1411bool TryFinallyStatement::hasBreak()
1412{
1413    return false; //true;
1414}
1415
1416bool TryFinallyStatement::hasContinue()
1417{
1418    return false; //true;
1419}
1420
1421/****************************** OnScopeStatement ***************************/
1422
1423OnScopeStatement::OnScopeStatement(Loc loc, TOK tok, Statement *statement)
1424    : Statement(loc)
1425{
1426    this->tok = tok;
1427    this->statement = statement;
1428}
1429
1430Statement *OnScopeStatement::syntaxCopy()
1431{
1432    return new OnScopeStatement(loc, tok, statement->syntaxCopy());
1433}
1434
1435Statement *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
1485ThrowStatement::ThrowStatement(Loc loc, Expression *exp)
1486    : Statement(loc)
1487{
1488    this->exp = exp;
1489    this->internalThrow = false;
1490}
1491
1492Statement *ThrowStatement::syntaxCopy()
1493{
1494    ThrowStatement *s = new ThrowStatement(loc, exp->syntaxCopy());
1495    s->internalThrow = internalThrow;
1496    return s;
1497}
1498
1499/******************************** DebugStatement **************************/
1500
1501DebugStatement::DebugStatement(Loc loc, Statement *statement)
1502    : Statement(loc)
1503{
1504    this->statement = statement;
1505}
1506
1507Statement *DebugStatement::syntaxCopy()
1508{
1509    return new DebugStatement(loc,
1510        statement ? statement->syntaxCopy() : NULL);
1511}
1512
1513Statements *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
1531GotoStatement::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
1541Statement *GotoStatement::syntaxCopy()
1542{
1543    return new GotoStatement(loc, ident);
1544}
1545
1546bool 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
1603LabelStatement::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
1615Statement *LabelStatement::syntaxCopy()
1616{
1617    return new LabelStatement(loc, ident, statement ? statement->syntaxCopy() : NULL);
1618}
1619
1620Statement *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
1634Statements *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
1659LabelDsymbol::LabelDsymbol(Identifier *ident)
1660        : Dsymbol(ident)
1661{
1662    statement = NULL;
1663}
1664
1665LabelDsymbol *LabelDsymbol::create(Identifier *ident)
1666{
1667    return new LabelDsymbol(ident);
1668}
1669
1670LabelDsymbol *LabelDsymbol::isLabel()           // is this a LabelDsymbol()?
1671{
1672    return this;
1673}
1674
1675
1676/************************ AsmStatement ***************************************/
1677
1678AsmStatement::AsmStatement(Loc loc, Token *tokens)
1679    : Statement(loc)
1680{
1681    this->tokens = tokens;
1682}
1683
1684Statement *AsmStatement::syntaxCopy()
1685{
1686    return new AsmStatement(loc, tokens);
1687}
1688
1689
1690/************************ InlineAsmStatement **********************************/
1691
1692InlineAsmStatement::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
1702Statement *InlineAsmStatement::syntaxCopy()
1703{
1704    return new InlineAsmStatement(loc, tokens);
1705}
1706
1707
1708/************************ GccAsmStatement ***************************************/
1709
1710GccAsmStatement::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
1724Statement *GccAsmStatement::syntaxCopy()
1725{
1726    return new GccAsmStatement(loc, tokens);
1727}
1728
1729/************************ CompoundAsmStatement ***************************************/
1730
1731CompoundAsmStatement::CompoundAsmStatement(Loc loc, Statements *s, StorageClass stc)
1732    : CompoundStatement(loc, s)
1733{
1734    this->stc = stc;
1735}
1736
1737CompoundAsmStatement *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
1749Statements *CompoundAsmStatement::flatten(Scope *)
1750{
1751    return NULL;
1752}
1753
1754/************************ ImportStatement ***************************************/
1755
1756ImportStatement::ImportStatement(Loc loc, Dsymbols *imports)
1757    : Statement(loc)
1758{
1759    this->imports = imports;
1760}
1761
1762Statement *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