]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/d/dmd/statement.c
d: Merge upstream dmd 7132b3537
[thirdparty/gcc.git] / gcc / d / dmd / statement.c
CommitLineData
b4c522fa
IB
1
2/* Compiler implementation of the D programming language
a3b38b77 3 * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
b4c522fa
IB
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
f9ab59ff 11#include "root/dsystem.h"
b4c522fa
IB
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);
5b74dd0a 33Statement *makeTupleForeachStatic(Scope *sc, ForeachStatement *fs, bool needExpansion);
b4c522fa
IB
34
35Identifier *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
fced594b 50 const char *name = buf.extractChars();
b4c522fa
IB
51 ident = Identifier::idPool(name);
52 }
53 return ident;
54}
55
56LabelStatement *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 */
73Expression *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'
87TypeIdentifier *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
97Statement::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
104Statement *Statement::syntaxCopy()
105{
106 assert(0);
107 return NULL;
108}
109
acae7b21
IB
110/*************************************
111 * Do syntax copy of an array of Statement's.
112 */
113Statements *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
b4c522fa
IB
128void Statement::print()
129{
130 fprintf(stderr, "%s\n", toChars());
131 fflush(stderr);
132}
133
134const char *Statement::toChars()
135{
136 HdrGenState hgs;
137
138 OutBuffer buf;
139 ::toCBuffer(this, &buf, &hgs);
fced594b 140 return buf.extractChars();
b4c522fa
IB
141}
142
143
144void 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
152void 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
160void 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
168bool Statement::hasBreak()
169{
170 //printf("Statement::hasBreak()\n");
171 return false;
172}
173
174bool Statement::hasContinue()
175{
176 return false;
177}
178
179/* ============================================== */
180// true if statement uses exception handling
181
182bool 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; }
72acf751 190 void visit(ScopeGuardStatement *) { stop = true; }
b4c522fa
IB
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
201bool 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
220bool 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
247Statement *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
262Statement *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
278Statements *Statement::flatten(Scope *)
279{
280 return NULL;
281}
282
283
284/******************************** ErrorStatement ***************************/
285
286ErrorStatement::ErrorStatement()
287 : Statement(Loc())
288{
289 assert(global.gaggedErrors || global.errors);
290}
291
292Statement *ErrorStatement::syntaxCopy()
293{
294 return this;
295}
296
297/******************************** PeelStatement ***************************/
298
299PeelStatement::PeelStatement(Statement *s)
300 : Statement(s->loc)
301{
302 this->s = s;
303}
304
305/******************************** ExpStatement ***************************/
306
307ExpStatement::ExpStatement(Loc loc, Expression *exp)
308 : Statement(loc)
309{
310 this->exp = exp;
311}
312
313ExpStatement::ExpStatement(Loc loc, Dsymbol *declaration)
314 : Statement(loc)
315{
316 this->exp = new DeclarationExp(loc, declaration);
317}
318
319ExpStatement *ExpStatement::create(Loc loc, Expression *exp)
320{
321 return new ExpStatement(loc, exp);
322}
323
324Statement *ExpStatement::syntaxCopy()
325{
326 return new ExpStatement(loc, exp ? exp->syntaxCopy() : NULL);
327}
328
329Statement *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 */
361Statement *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();
2cbc99d1 379 for (size_t i = 0; i < a->length; i++)
b4c522fa
IB
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();
2cbc99d1 395 for (size_t i = 0; i < tm->members->length; i++)
b4c522fa
IB
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); }
5b74dd0a 430 void visit(ForwardingAttribDeclaration *d) { result = visitMembers(d->loc, d->decl); }
b4c522fa
IB
431
432 void visit(StaticAssert *) {}
433 void visit(Import *) {}
434 void visit(PragmaDeclaration *) {}
435
436 void visit(ConditionalDeclaration *d)
437 {
d3da83f6 438 result = visitMembers(d->loc, d->include(NULL));
b4c522fa
IB
439 }
440
5b74dd0a
IB
441 void visit(StaticForeachDeclaration *d)
442 {
443 assert(d->sfe && !!d->sfe->aggrfe ^ !!d->sfe->rangefe);
d3da83f6 444 result = visitMembers(d->loc, d->include(NULL));
5b74dd0a
IB
445 }
446
b4c522fa
IB
447 void visit(CompileDeclaration *d)
448 {
d3da83f6 449 result = visitMembers(d->loc, d->include(NULL));
b4c522fa
IB
450 }
451 };
452
453 if (!s)
454 return NULL;
455
456 ToStmt v;
457 s->accept(&v);
458 return v.result;
459}
460
461Statements *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 {
a3b38b77 471 Expression *e = expressionSemantic(exp, sc);
b4c522fa
IB
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
491DtorExpStatement::DtorExpStatement(Loc loc, Expression *exp, VarDeclaration *v)
492 : ExpStatement(loc, exp)
493{
494 this->var = v;
495}
496
497Statement *DtorExpStatement::syntaxCopy()
498{
499 return new DtorExpStatement(loc, exp ? exp->syntaxCopy() : NULL, var);
500}
501
502/******************************** CompileStatement ***************************/
503
504CompileStatement::CompileStatement(Loc loc, Expression *exp)
505 : Statement(loc)
506{
507 this->exp = exp;
508}
509
510Statement *CompileStatement::syntaxCopy()
511{
512 return new CompileStatement(loc, exp->syntaxCopy());
513}
514
8f5439be
IB
515static Statements *errorStatements()
516{
517 Statements *a = new Statements();
518 a->push(new ErrorStatement());
519 return a;
520}
521
b4c522fa
IB
522Statements *CompileStatement::flatten(Scope *sc)
523{
524 //printf("CompileStatement::flatten() %s\n", exp->toChars());
8f5439be
IB
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();
b4c522fa
IB
533
534 Statements *a = new Statements();
8f5439be 535 while (p.token.value != TOKeof)
b4c522fa 536 {
8f5439be
IB
537 Statement *s = p.parseStatement(PSsemi | PScurlyscope);
538 if (!s || p.errors)
b4c522fa 539 {
8f5439be
IB
540 assert(!p.errors || global.errors != errors); // make sure we caught all the cases
541 return errorStatements();
b4c522fa 542 }
8f5439be 543 a->push(s);
b4c522fa 544 }
b4c522fa
IB
545 return a;
546}
547
548/******************************** CompoundStatement ***************************/
549
550CompoundStatement::CompoundStatement(Loc loc, Statements *s)
551 : Statement(loc)
552{
553 statements = s;
554}
555
556CompoundStatement::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
565CompoundStatement::CompoundStatement(Loc loc, Statement *s1)
566 : Statement(loc)
567{
568 statements = new Statements();
569 statements->push(s1);
570}
571
572CompoundStatement *CompoundStatement::create(Loc loc, Statement *s1, Statement *s2)
573{
574 return new CompoundStatement(loc, s1, s2);
575}
576
577Statement *CompoundStatement::syntaxCopy()
578{
acae7b21 579 return new CompoundStatement(loc, Statement::arraySyntaxCopy(statements));
b4c522fa
IB
580}
581
582Statements *CompoundStatement::flatten(Scope *)
583{
584 return statements;
585}
586
587ReturnStatement *CompoundStatement::isReturnStatement()
588{
589 ReturnStatement *rs = NULL;
590
2cbc99d1 591 for (size_t i = 0; i < statements->length; i++)
b4c522fa
IB
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
604Statement *CompoundStatement::last()
605{
606 Statement *s = NULL;
607
2cbc99d1 608 for (size_t i = statements->length; i; --i)
b4c522fa
IB
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
622CompoundDeclarationStatement::CompoundDeclarationStatement(Loc loc, Statements *s)
623 : CompoundStatement(loc, s)
624{
625 statements = s;
626}
627
628Statement *CompoundDeclarationStatement::syntaxCopy()
629{
630 Statements *a = new Statements();
2cbc99d1
IB
631 a->setDim(statements->length);
632 for (size_t i = 0; i < statements->length; i++)
b4c522fa
IB
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
642UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s)
643 : Statement(loc)
644{
645 statements = s;
646}
647
648Statement *UnrolledLoopStatement::syntaxCopy()
649{
650 Statements *a = new Statements();
2cbc99d1
IB
651 a->setDim(statements->length);
652 for (size_t i = 0; i < statements->length; i++)
b4c522fa
IB
653 {
654 Statement *s = (*statements)[i];
655 (*a)[i] = s ? s->syntaxCopy() : NULL;
656 }
657 return new UnrolledLoopStatement(loc, a);
658}
659
660bool UnrolledLoopStatement::hasBreak()
661{
662 return true;
663}
664
665bool UnrolledLoopStatement::hasContinue()
666{
667 return true;
668}
669
670/******************************** ScopeStatement ***************************/
671
672ScopeStatement::ScopeStatement(Loc loc, Statement *s, Loc endloc)
673 : Statement(loc)
674{
675 this->statement = s;
676 this->endloc = endloc;
677}
678
679Statement *ScopeStatement::syntaxCopy()
680{
681 return new ScopeStatement(loc, statement ? statement->syntaxCopy() : NULL, endloc);
682}
683
684ReturnStatement *ScopeStatement::isReturnStatement()
685{
686 if (statement)
687 return statement->isReturnStatement();
688 return NULL;
689}
690
691bool ScopeStatement::hasBreak()
692{
693 //printf("ScopeStatement::hasBreak() %s\n", toChars());
694 return statement ? statement->hasBreak() : false;
695}
696
697bool ScopeStatement::hasContinue()
698{
699 return statement ? statement->hasContinue() : false;
700}
701
5b74dd0a
IB
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
711ForwardingStatement::ForwardingStatement(Loc loc, ForwardingScopeDsymbol *sym, Statement *s)
712 : Statement(loc)
713{
714 this->sym = sym;
715 assert(s);
716 this->statement = s;
717}
718
719ForwardingStatement::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
728Statement *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
745Statements *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();
2cbc99d1
IB
759 b->setDim(a->length);
760 for (size_t i = 0; i < a->length; i++)
5b74dd0a
IB
761 {
762 Statement *s = (*a)[i];
763 (*b)[i] = s ? new ForwardingStatement(s->loc, sym, s) : NULL;
764 }
765 return b;
766}
767
b4c522fa
IB
768/******************************** WhileStatement ***************************/
769
770WhileStatement::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
778Statement *WhileStatement::syntaxCopy()
779{
780 return new WhileStatement(loc,
781 condition->syntaxCopy(),
782 _body ? _body->syntaxCopy() : NULL,
783 endloc);
784}
785
786bool WhileStatement::hasBreak()
787{
788 return true;
789}
790
791bool WhileStatement::hasContinue()
792{
793 return true;
794}
795
796/******************************** DoStatement ***************************/
797
798DoStatement::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
806Statement *DoStatement::syntaxCopy()
807{
808 return new DoStatement(loc,
809 _body ? _body->syntaxCopy() : NULL,
810 condition->syntaxCopy(),
811 endloc);
812}
813
814bool DoStatement::hasBreak()
815{
816 return true;
817}
818
819bool DoStatement::hasContinue()
820{
821 return true;
822}
823
824/******************************** ForStatement ***************************/
825
826ForStatement::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
837Statement *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
847Statement *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
854bool ForStatement::hasBreak()
855{
856 //printf("ForStatement::hasBreak()\n");
857 return true;
858}
859
860bool ForStatement::hasContinue()
861{
862 return true;
863}
864
865/******************************** ForeachStatement ***************************/
866
867ForeachStatement::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
886Statement *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
895bool ForeachStatement::checkForArgTypes()
896{
897 bool result = false;
898
2cbc99d1 899 for (size_t i = 0; i < parameters->length; i++)
b4c522fa
IB
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
912bool ForeachStatement::hasBreak()
913{
914 return true;
915}
916
917bool ForeachStatement::hasContinue()
918{
919 return true;
920}
921
922/**************************** ForeachRangeStatement ***************************/
923
924
925ForeachRangeStatement::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
939Statement *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
949bool ForeachRangeStatement::hasBreak()
950{
951 return true;
952}
953
954bool ForeachRangeStatement::hasContinue()
955{
956 return true;
957}
958
959/******************************** IfStatement ***************************/
960
961IfStatement::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
972Statement *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
984ConditionalStatement::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
992Statement *ConditionalStatement::syntaxCopy()
993{
994 return new ConditionalStatement(loc,
995 condition->syntaxCopy(),
996 ifbody->syntaxCopy(),
997 elsebody ? elsebody->syntaxCopy() : NULL);
998}
999
1000Statements *ConditionalStatement::flatten(Scope *sc)
1001{
1002 Statement *s;
1003
1004 //printf("ConditionalStatement::flatten()\n");
d3da83f6 1005 if (condition->include(sc))
b4c522fa
IB
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
5b74dd0a
IB
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
1033StaticForeachStatement::StaticForeachStatement(Loc loc, StaticForeach *sfe)
1034 : Statement(loc)
1035{
1036 this->sfe = sfe;
1037}
1038
1039Statement *StaticForeachStatement::syntaxCopy()
1040{
1041 return new StaticForeachStatement(loc, sfe->syntaxCopy());
1042}
1043
1044Statements *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
b4c522fa
IB
1067/******************************** PragmaStatement ***************************/
1068
1069PragmaStatement::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
1077Statement *PragmaStatement::syntaxCopy()
1078{
1079 return new PragmaStatement(loc, ident,
1080 Expression::arraySyntaxCopy(args),
1081 _body ? _body->syntaxCopy() : NULL);
1082}
1083
1084/******************************** StaticAssertStatement ***************************/
1085
1086StaticAssertStatement::StaticAssertStatement(StaticAssert *sa)
1087 : Statement(sa->loc)
1088{
1089 this->sa = sa;
1090}
1091
1092Statement *StaticAssertStatement::syntaxCopy()
1093{
1094 return new StaticAssertStatement((StaticAssert *)sa->syntaxCopy(NULL));
1095}
1096
1097/******************************** SwitchStatement ***************************/
1098
1099SwitchStatement::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
1113Statement *SwitchStatement::syntaxCopy()
1114{
1115 return new SwitchStatement(loc,
1116 condition->syntaxCopy(),
1117 _body->syntaxCopy(),
1118 isFinal);
1119}
1120
1121bool SwitchStatement::hasBreak()
1122{
1123 return true;
1124}
1125
1126static 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 {
a3b38b77 1144 s->deprecation("`switch` skips declaration of `with` temporary at %s", vd->loc.toChars());
b4c522fa
IB
1145 return true;
1146 }
1147 else
1148 {
a3b38b77 1149 s->deprecation("`switch` skips declaration of variable %s at %s", vd->toPrettyChars(), vd->loc.toChars());
b4c522fa
IB
1150 return true;
1151 }
1152
1153 return false;
1154}
1155
1156bool 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
2cbc99d1 1163 for (size_t i = 0; i < cases->length; i++)
b4c522fa
IB
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
1174CaseStatement::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
1183Statement *CaseStatement::syntaxCopy()
1184{
1185 return new CaseStatement(loc,
1186 exp->syntaxCopy(),
1187 statement->syntaxCopy());
1188}
1189
1190int 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
1201CaseRangeStatement::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
1210Statement *CaseRangeStatement::syntaxCopy()
1211{
1212 return new CaseRangeStatement(loc,
1213 first->syntaxCopy(),
1214 last->syntaxCopy(),
1215 statement->syntaxCopy());
1216}
1217
1218/******************************** DefaultStatement ***************************/
1219
1220DefaultStatement::DefaultStatement(Loc loc, Statement *s)
1221 : Statement(loc)
1222{
1223 this->statement = s;
1224 this->lastVar = NULL;
1225}
1226
1227Statement *DefaultStatement::syntaxCopy()
1228{
1229 return new DefaultStatement(loc, statement->syntaxCopy());
1230}
1231
1232/******************************** GotoDefaultStatement ***************************/
1233
1234GotoDefaultStatement::GotoDefaultStatement(Loc loc)
1235 : Statement(loc)
1236{
1237 sw = NULL;
1238}
1239
1240Statement *GotoDefaultStatement::syntaxCopy()
1241{
1242 return new GotoDefaultStatement(loc);
1243}
1244
1245/******************************** GotoCaseStatement ***************************/
1246
1247GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp)
1248 : Statement(loc)
1249{
1250 cs = NULL;
1251 this->exp = exp;
1252}
1253
1254Statement *GotoCaseStatement::syntaxCopy()
1255{
1256 return new GotoCaseStatement(loc, exp ? exp->syntaxCopy() : NULL);
1257}
1258
1259/******************************** SwitchErrorStatement ***************************/
1260
1261SwitchErrorStatement::SwitchErrorStatement(Loc loc)
1262 : Statement(loc)
1263{
1264}
1265
1266/******************************** ReturnStatement ***************************/
1267
1268ReturnStatement::ReturnStatement(Loc loc, Expression *exp)
1269 : Statement(loc)
1270{
1271 this->exp = exp;
1272 this->caseDim = 0;
1273}
1274
1275Statement *ReturnStatement::syntaxCopy()
1276{
1277 return new ReturnStatement(loc, exp ? exp->syntaxCopy() : NULL);
1278}
1279
1280/******************************** BreakStatement ***************************/
1281
1282BreakStatement::BreakStatement(Loc loc, Identifier *ident)
1283 : Statement(loc)
1284{
1285 this->ident = ident;
1286}
1287
1288Statement *BreakStatement::syntaxCopy()
1289{
1290 return new BreakStatement(loc, ident);
1291}
1292
1293/******************************** ContinueStatement ***************************/
1294
1295ContinueStatement::ContinueStatement(Loc loc, Identifier *ident)
1296 : Statement(loc)
1297{
1298 this->ident = ident;
1299}
1300
1301Statement *ContinueStatement::syntaxCopy()
1302{
1303 return new ContinueStatement(loc, ident);
1304}
1305
1306/******************************** SynchronizedStatement ***************************/
1307
1308SynchronizedStatement::SynchronizedStatement(Loc loc, Expression *exp, Statement *body)
1309 : Statement(loc)
1310{
1311 this->exp = exp;
1312 this->_body = body;
1313}
1314
1315Statement *SynchronizedStatement::syntaxCopy()
1316{
1317 return new SynchronizedStatement(loc,
1318 exp ? exp->syntaxCopy() : NULL,
1319 _body ? _body->syntaxCopy() : NULL);
1320}
1321
1322bool SynchronizedStatement::hasBreak()
1323{
1324 return false; //true;
1325}
1326
1327bool SynchronizedStatement::hasContinue()
1328{
1329 return false; //true;
1330}
1331
1332/******************************** WithStatement ***************************/
1333
1334WithStatement::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
1343Statement *WithStatement::syntaxCopy()
1344{
1345 return new WithStatement(loc,
1346 exp->syntaxCopy(),
1347 _body ? _body->syntaxCopy() : NULL, endloc);
1348}
1349
1350/******************************** TryCatchStatement ***************************/
1351
1352TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Catches *catches)
1353 : Statement(loc)
1354{
1355 this->_body = body;
1356 this->catches = catches;
1357}
1358
1359Statement *TryCatchStatement::syntaxCopy()
1360{
1361 Catches *a = new Catches();
2cbc99d1
IB
1362 a->setDim(catches->length);
1363 for (size_t i = 0; i < a->length; i++)
b4c522fa
IB
1364 {
1365 Catch *c = (*catches)[i];
1366 (*a)[i] = c->syntaxCopy();
1367 }
1368 return new TryCatchStatement(loc, _body->syntaxCopy(), a);
1369}
1370
1371bool TryCatchStatement::hasBreak()
1372{
1373 return false;
1374}
1375
1376/******************************** Catch ***************************/
1377
1378Catch::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
1390Catch *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
1402TryFinallyStatement::TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody)
1403 : Statement(loc)
1404{
1405 this->_body = body;
1406 this->finalbody = finalbody;
1407}
1408
1409TryFinallyStatement *TryFinallyStatement::create(Loc loc, Statement *body, Statement *finalbody)
1410{
1411 return new TryFinallyStatement(loc, body, finalbody);
1412}
1413
1414Statement *TryFinallyStatement::syntaxCopy()
1415{
1416 return new TryFinallyStatement(loc,
1417 _body->syntaxCopy(), finalbody->syntaxCopy());
1418}
1419
1420bool TryFinallyStatement::hasBreak()
1421{
1422 return false; //true;
1423}
1424
1425bool TryFinallyStatement::hasContinue()
1426{
1427 return false; //true;
1428}
1429
72acf751 1430/****************************** ScopeGuardStatement ***************************/
b4c522fa 1431
72acf751 1432ScopeGuardStatement::ScopeGuardStatement(Loc loc, TOK tok, Statement *statement)
b4c522fa
IB
1433 : Statement(loc)
1434{
1435 this->tok = tok;
1436 this->statement = statement;
1437}
1438
72acf751 1439Statement *ScopeGuardStatement::syntaxCopy()
b4c522fa 1440{
72acf751 1441 return new ScopeGuardStatement(loc, tok, statement->syntaxCopy());
b4c522fa
IB
1442}
1443
72acf751 1444Statement *ScopeGuardStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
b4c522fa 1445{
72acf751 1446 //printf("ScopeGuardStatement::scopeCode()\n");
b4c522fa
IB
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));
a3b38b77 1472 dsymbolSemantic(v, sc);
b4c522fa
IB
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
1494ThrowStatement::ThrowStatement(Loc loc, Expression *exp)
1495 : Statement(loc)
1496{
1497 this->exp = exp;
1498 this->internalThrow = false;
1499}
1500
1501Statement *ThrowStatement::syntaxCopy()
1502{
1503 ThrowStatement *s = new ThrowStatement(loc, exp->syntaxCopy());
1504 s->internalThrow = internalThrow;
1505 return s;
1506}
1507
1508/******************************** DebugStatement **************************/
1509
1510DebugStatement::DebugStatement(Loc loc, Statement *statement)
1511 : Statement(loc)
1512{
1513 this->statement = statement;
1514}
1515
1516Statement *DebugStatement::syntaxCopy()
1517{
1518 return new DebugStatement(loc,
1519 statement ? statement->syntaxCopy() : NULL);
1520}
1521
1522Statements *DebugStatement::flatten(Scope *sc)
1523{
1524 Statements *a = statement ? statement->flatten(sc) : NULL;
1525 if (a)
1526 {
2cbc99d1 1527 for (size_t i = 0; i < a->length; i++)
b4c522fa
IB
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
1540GotoStatement::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
1550Statement *GotoStatement::syntaxCopy()
1551{
1552 return new GotoStatement(loc, ident);
1553}
1554
1555bool GotoStatement::checkLabel()
1556{
1557 if (!label->statement)
1558 {
a3b38b77 1559 error("label `%s` is undefined", label->toChars());
b4c522fa
IB
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
1612LabelStatement::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
1624Statement *LabelStatement::syntaxCopy()
1625{
1626 return new LabelStatement(loc, ident, statement ? statement->syntaxCopy() : NULL);
1627}
1628
1629Statement *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
1643Statements *LabelStatement::flatten(Scope *sc)
1644{
1645 Statements *a = NULL;
1646
1647 if (statement)
1648 {
1649 a = statement->flatten(sc);
1650 if (a)
1651 {
2cbc99d1 1652 if (!a->length)
b4c522fa
IB
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
1668LabelDsymbol::LabelDsymbol(Identifier *ident)
1669 : Dsymbol(ident)
1670{
1671 statement = NULL;
1672}
1673
1674LabelDsymbol *LabelDsymbol::create(Identifier *ident)
1675{
1676 return new LabelDsymbol(ident);
1677}
1678
1679LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()?
1680{
1681 return this;
1682}
1683
1684
1685/************************ AsmStatement ***************************************/
1686
1687AsmStatement::AsmStatement(Loc loc, Token *tokens)
1688 : Statement(loc)
1689{
1690 this->tokens = tokens;
1691}
1692
1693Statement *AsmStatement::syntaxCopy()
1694{
1695 return new AsmStatement(loc, tokens);
1696}
1697
1698
1699/************************ InlineAsmStatement **********************************/
1700
1701InlineAsmStatement::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
1711Statement *InlineAsmStatement::syntaxCopy()
1712{
1713 return new InlineAsmStatement(loc, tokens);
1714}
1715
1716
1717/************************ GccAsmStatement ***************************************/
1718
1719GccAsmStatement::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
1733Statement *GccAsmStatement::syntaxCopy()
1734{
1735 return new GccAsmStatement(loc, tokens);
1736}
1737
1738/************************ CompoundAsmStatement ***************************************/
1739
1740CompoundAsmStatement::CompoundAsmStatement(Loc loc, Statements *s, StorageClass stc)
1741 : CompoundStatement(loc, s)
1742{
1743 this->stc = stc;
1744}
1745
1746CompoundAsmStatement *CompoundAsmStatement::syntaxCopy()
1747{
1748 Statements *a = new Statements();
2cbc99d1
IB
1749 a->setDim(statements->length);
1750 for (size_t i = 0; i < statements->length; i++)
b4c522fa
IB
1751 {
1752 Statement *s = (*statements)[i];
1753 (*a)[i] = s ? s->syntaxCopy() : NULL;
1754 }
1755 return new CompoundAsmStatement(loc, a, stc);
1756}
1757
1758Statements *CompoundAsmStatement::flatten(Scope *)
1759{
1760 return NULL;
1761}
1762
1763/************************ ImportStatement ***************************************/
1764
1765ImportStatement::ImportStatement(Loc loc, Dsymbols *imports)
1766 : Statement(loc)
1767{
1768 this->imports = imports;
1769}
1770
1771Statement *ImportStatement::syntaxCopy()
1772{
1773 Dsymbols *m = new Dsymbols();
2cbc99d1
IB
1774 m->setDim(imports->length);
1775 for (size_t i = 0; i < imports->length; i++)
b4c522fa
IB
1776 {
1777 Dsymbol *s = (*imports)[i];
1778 (*m)[i] = s->syntaxCopy(NULL);
1779 }
1780 return new ImportStatement(loc, m);
1781}