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