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