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
11 #include "root/dsystem.h"
13 #include "statement.h"
15 #include "expression.h"
18 #include "staticassert.h"
20 #include "declaration.h"
21 #include "aggregate.h"
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
);
35 Identifier
*fixupLabelName(Scope
*sc
, Identifier
*ident
)
37 unsigned flags
= (sc
->flags
& SCOPEcontract
);
38 const char *id
= ident
->toChars();
39 if (flags
&& flags
!= SCOPEinvariant
&&
40 !(id
[0] == '_' && id
[1] == '_'))
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.
46 const char *prefix
= flags
== SCOPErequire
? "__in_" : "__out_";
48 buf
.printf("%s%s", prefix
, ident
->toChars());
50 const char *name
= buf
.extractChars();
51 ident
= Identifier::idPool(name
);
56 LabelStatement
*checkLabeledLoop(Scope
*sc
, Statement
*statement
)
58 if (sc
->slabel
&& sc
->slabel
->statement
== statement
)
65 /***********************************************************
66 * Check an assignment is used as a condition.
67 * Intended to be use before the `semantic` call on `e`.
69 * e = condition expression which is not yet run semantic analysis.
73 Expression
*checkAssignmentAsCondition(Expression
*e
)
76 while (ec
->op
== TOKcomma
)
77 ec
= ((CommaExp
*)ec
)->e2
;
78 if (ec
->op
== TOKassign
)
80 ec
->error("assignment cannot be used as a condition, perhaps == was meant?");
81 return new ErrorExp();
86 /// Return a type identifier reference to 'object.Throwable'
87 TypeIdentifier
*getThrowable()
89 TypeIdentifier
*tid
= new TypeIdentifier(Loc(), Id::empty
);
90 tid
->addIdent(Id::object
);
91 tid
->addIdent(Id::Throwable
);
95 /******************************** Statement ***************************/
97 Statement::Statement(Loc loc
)
100 // If this is an in{} contract scope statement (skip for determining
101 // inlineStatus of a function body for header content)
104 Statement
*Statement::syntaxCopy()
110 /*************************************
111 * Do syntax copy of an array of Statement's.
113 Statements
*Statement::arraySyntaxCopy(Statements
*a
)
115 Statements
*b
= NULL
;
119 for (size_t i
= 0; i
< a
->length
; i
++)
121 Statement
*s
= (*a
)[i
];
122 (*b
)[i
] = s
? s
->syntaxCopy() : NULL
;
128 void Statement::print()
130 fprintf(stderr
, "%s\n", toChars());
134 const char *Statement::toChars()
139 ::toCBuffer(this, &buf
, &hgs
);
140 return buf
.extractChars();
144 void Statement::error(const char *format
, ...)
147 va_start(ap
, format
);
148 ::verror(loc
, format
, ap
);
152 void Statement::warning(const char *format
, ...)
155 va_start(ap
, format
);
156 ::vwarning(loc
, format
, ap
);
160 void Statement::deprecation(const char *format
, ...)
163 va_start(ap
, format
);
164 ::vdeprecation(loc
, format
, ap
);
168 bool Statement::hasBreak()
170 //printf("Statement::hasBreak()\n");
174 bool Statement::hasContinue()
179 /* ============================================== */
180 // true if statement uses exception handling
182 bool Statement::usesEH()
184 class UsesEH
: public StoppableVisitor
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; }
195 return walkPostorder(this, &ueh
);
198 /* ============================================== */
199 // true if statement 'comes from' somewhere else, like a goto
201 bool Statement::comeFrom()
203 class ComeFrom
: public StoppableVisitor
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; }
214 return walkPostorder(this, &cf
);
217 /* ============================================== */
218 // Return true if statement has executable code.
220 bool Statement::hasCode()
222 class HasCode
: public StoppableVisitor
225 void visit(Statement
*)
230 void visit(ExpStatement
*s
)
234 stop
= s
->exp
->hasCode();
238 void visit(CompoundStatement
*) {}
239 void visit(ScopeStatement
*) {}
240 void visit(ImportStatement
*) {}
244 return walkPostorder(this, &hc
);
247 Statement
*Statement::last()
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
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
262 Statement
*Statement::scopeCode(Scope
*, Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
264 //printf("Statement::scopeCode()\n");
272 /*********************************
273 * Flatten out the scope by presenting the statement
274 * as an array of statements.
275 * Returns NULL if no flattening necessary.
278 Statements
*Statement::flatten(Scope
*)
284 /******************************** ErrorStatement ***************************/
286 ErrorStatement::ErrorStatement()
289 assert(global
.gaggedErrors
|| global
.errors
);
292 Statement
*ErrorStatement::syntaxCopy()
297 /******************************** PeelStatement ***************************/
299 PeelStatement::PeelStatement(Statement
*s
)
305 /******************************** ExpStatement ***************************/
307 ExpStatement::ExpStatement(Loc loc
, Expression
*exp
)
313 ExpStatement::ExpStatement(Loc loc
, Dsymbol
*declaration
)
316 this->exp
= new DeclarationExp(loc
, declaration
);
319 ExpStatement
*ExpStatement::create(Loc loc
, Expression
*exp
)
321 return new ExpStatement(loc
, exp
);
324 Statement
*ExpStatement::syntaxCopy()
326 return new ExpStatement(loc
, exp
? exp
->syntaxCopy() : NULL
);
329 Statement
*ExpStatement::scopeCode(Scope
*, Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
331 //printf("ExpStatement::scopeCode()\n");
340 if (exp
->op
== TOKdeclaration
)
342 DeclarationExp
*de
= (DeclarationExp
*)(exp
);
343 VarDeclaration
*v
= de
->declaration
->isVarDeclaration();
344 if (v
&& !v
->isDataseg())
346 if (v
->needsScopeDtor())
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
358 /****************************************
359 * Convert TemplateMixin members (== Dsymbols) to Statements.
361 Statement
*toStatement(Dsymbol
*s
)
363 class ToStmt
: public Visitor
373 Statement
*visitMembers(Loc loc
, Dsymbols
*a
)
378 Statements
*statements
= new Statements();
379 for (size_t i
= 0; i
< a
->length
; i
++)
381 statements
->push(toStatement((*a
)[i
]));
383 return new CompoundStatement(loc
, statements
);
386 void visit(Dsymbol
*s
)
388 ::error(Loc(), "Internal Compiler Error: cannot mixin %s %s\n", s
->kind(), s
->toChars());
389 result
= new ErrorStatement();
392 void visit(TemplateMixin
*tm
)
394 Statements
*a
= new Statements();
395 for (size_t i
= 0; i
< tm
->members
->length
; i
++)
397 Statement
*s
= toStatement((*tm
->members
)[i
]);
401 result
= new CompoundStatement(tm
->loc
, a
);
404 /* An actual declaration symbol will be converted to DeclarationExp
407 Statement
*declStmt(Dsymbol
*s
)
409 DeclarationExp
*de
= new DeclarationExp(s
->loc
, s
);
410 de
->type
= Type::tvoid
; // avoid repeated semantic
411 return new ExpStatement(s
->loc
, de
);
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
); }
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.
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
); }
432 void visit(StaticAssert
*) {}
433 void visit(Import
*) {}
434 void visit(PragmaDeclaration
*) {}
436 void visit(ConditionalDeclaration
*d
)
438 result
= visitMembers(d
->loc
, d
->include(NULL
));
441 void visit(StaticForeachDeclaration
*d
)
443 assert(d
->sfe
&& !!d
->sfe
->aggrfe
^ !!d
->sfe
->rangefe
);
444 result
= visitMembers(d
->loc
, d
->include(NULL
));
447 void visit(CompileDeclaration
*d
)
449 result
= visitMembers(d
->loc
, d
->include(NULL
));
461 Statements
*ExpStatement::flatten(Scope
*sc
)
463 /* Bugzilla 14243: expand template mixin in statement scope
464 * to handle variable destructors.
466 if (exp
&& exp
->op
== TOKdeclaration
)
468 Dsymbol
*d
= ((DeclarationExp
*)exp
)->declaration
;
469 if (TemplateMixin
*tm
= d
->isTemplateMixin())
471 Expression
*e
= expressionSemantic(exp
, sc
);
472 if (e
->op
== TOKerror
|| tm
->errors
)
474 Statements
*a
= new Statements();
475 a
->push(new ErrorStatement());
480 Statement
*s
= toStatement(tm
);
481 Statements
*a
= new Statements();
489 /******************************** DtorExpStatement ***************************/
491 DtorExpStatement::DtorExpStatement(Loc loc
, Expression
*exp
, VarDeclaration
*v
)
492 : ExpStatement(loc
, exp
)
497 Statement
*DtorExpStatement::syntaxCopy()
499 return new DtorExpStatement(loc
, exp
? exp
->syntaxCopy() : NULL
, var
);
502 /******************************** CompileStatement ***************************/
504 CompileStatement::CompileStatement(Loc loc
, Expression
*exp
)
510 Statement
*CompileStatement::syntaxCopy()
512 return new CompileStatement(loc
, exp
->syntaxCopy());
515 static Statements
*errorStatements()
517 Statements
*a
= new Statements();
518 a
->push(new ErrorStatement());
522 Statements
*CompileStatement::flatten(Scope
*sc
)
524 //printf("CompileStatement::flatten() %s\n", exp->toChars());
525 StringExp
*se
= semanticString(sc
, exp
, "argument to mixin");
527 return errorStatements();
530 unsigned errors
= global
.errors
;
531 Parser
p(loc
, sc
->_module
, (utf8_t
*)se
->string
, se
->len
, 0);
534 Statements
*a
= new Statements();
535 while (p
.token
.value
!= TOKeof
)
537 Statement
*s
= p
.parseStatement(PSsemi
| PScurlyscope
);
540 assert(!p
.errors
|| global
.errors
!= errors
); // make sure we caught all the cases
541 return errorStatements();
548 /******************************** CompoundStatement ***************************/
550 CompoundStatement::CompoundStatement(Loc loc
, Statements
*s
)
556 CompoundStatement::CompoundStatement(Loc loc
, Statement
*s1
, Statement
*s2
)
559 statements
= new Statements();
560 statements
->reserve(2);
561 statements
->push(s1
);
562 statements
->push(s2
);
565 CompoundStatement::CompoundStatement(Loc loc
, Statement
*s1
)
568 statements
= new Statements();
569 statements
->push(s1
);
572 CompoundStatement
*CompoundStatement::create(Loc loc
, Statement
*s1
, Statement
*s2
)
574 return new CompoundStatement(loc
, s1
, s2
);
577 Statement
*CompoundStatement::syntaxCopy()
579 return new CompoundStatement(loc
, Statement::arraySyntaxCopy(statements
));
582 Statements
*CompoundStatement::flatten(Scope
*)
587 ReturnStatement
*CompoundStatement::isReturnStatement()
589 ReturnStatement
*rs
= NULL
;
591 for (size_t i
= 0; i
< statements
->length
; i
++)
593 Statement
*s
= (*statements
)[i
];
596 rs
= s
->isReturnStatement();
604 Statement
*CompoundStatement::last()
608 for (size_t i
= statements
->length
; i
; --i
)
609 { s
= (*statements
)[i
- 1];
620 /******************************** CompoundDeclarationStatement ***************************/
622 CompoundDeclarationStatement::CompoundDeclarationStatement(Loc loc
, Statements
*s
)
623 : CompoundStatement(loc
, s
)
628 Statement
*CompoundDeclarationStatement::syntaxCopy()
630 Statements
*a
= new Statements();
631 a
->setDim(statements
->length
);
632 for (size_t i
= 0; i
< statements
->length
; i
++)
634 Statement
*s
= (*statements
)[i
];
635 (*a
)[i
] = s
? s
->syntaxCopy() : NULL
;
637 return new CompoundDeclarationStatement(loc
, a
);
640 /**************************** UnrolledLoopStatement ***************************/
642 UnrolledLoopStatement::UnrolledLoopStatement(Loc loc
, Statements
*s
)
648 Statement
*UnrolledLoopStatement::syntaxCopy()
650 Statements
*a
= new Statements();
651 a
->setDim(statements
->length
);
652 for (size_t i
= 0; i
< statements
->length
; i
++)
654 Statement
*s
= (*statements
)[i
];
655 (*a
)[i
] = s
? s
->syntaxCopy() : NULL
;
657 return new UnrolledLoopStatement(loc
, a
);
660 bool UnrolledLoopStatement::hasBreak()
665 bool UnrolledLoopStatement::hasContinue()
670 /******************************** ScopeStatement ***************************/
672 ScopeStatement::ScopeStatement(Loc loc
, Statement
*s
, Loc endloc
)
676 this->endloc
= endloc
;
679 Statement
*ScopeStatement::syntaxCopy()
681 return new ScopeStatement(loc
, statement
? statement
->syntaxCopy() : NULL
, endloc
);
684 ReturnStatement
*ScopeStatement::isReturnStatement()
687 return statement
->isReturnStatement();
691 bool ScopeStatement::hasBreak()
693 //printf("ScopeStatement::hasBreak() %s\n", toChars());
694 return statement
? statement
->hasBreak() : false;
697 bool ScopeStatement::hasContinue()
699 return statement
? statement
->hasContinue() : false;
702 /******************************** ForwardingStatement **********************/
704 /* Statement whose symbol table contains foreach index variables in a
705 * local scope and forwards other members to the parent scope. This
708 * Also see: `ddmd.attrib.ForwardingAttribDeclaration`
711 ForwardingStatement::ForwardingStatement(Loc loc
, ForwardingScopeDsymbol
*sym
, Statement
*s
)
719 ForwardingStatement::ForwardingStatement(Loc loc
, Statement
*s
)
722 this->sym
= new ForwardingScopeDsymbol(NULL
);
723 this->sym
->symtab
= new DsymbolTable();
728 Statement
*ForwardingStatement::syntaxCopy()
730 return new ForwardingStatement(loc
, statement
->syntaxCopy());
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
740 * static foreach(i; 0 .. 10) scope(exit) writeln(i);
741 * writeln("this is printed first");
742 * // then, it prints 10, 9, 8, 7, ...
745 Statements
*ForwardingStatement::flatten(Scope
*sc
)
752 Statements
*a
= statement
->flatten(sc
);
758 Statements
*b
= new Statements();
759 b
->setDim(a
->length
);
760 for (size_t i
= 0; i
< a
->length
; i
++)
762 Statement
*s
= (*a
)[i
];
763 (*b
)[i
] = s
? new ForwardingStatement(s
->loc
, sym
, s
) : NULL
;
768 /******************************** WhileStatement ***************************/
770 WhileStatement::WhileStatement(Loc loc
, Expression
*c
, Statement
*b
, Loc endloc
)
775 this->endloc
= endloc
;
778 Statement
*WhileStatement::syntaxCopy()
780 return new WhileStatement(loc
,
781 condition
->syntaxCopy(),
782 _body
? _body
->syntaxCopy() : NULL
,
786 bool WhileStatement::hasBreak()
791 bool WhileStatement::hasContinue()
796 /******************************** DoStatement ***************************/
798 DoStatement::DoStatement(Loc loc
, Statement
*b
, Expression
*c
, Loc endloc
)
803 this->endloc
= endloc
;
806 Statement
*DoStatement::syntaxCopy()
808 return new DoStatement(loc
,
809 _body
? _body
->syntaxCopy() : NULL
,
810 condition
->syntaxCopy(),
814 bool DoStatement::hasBreak()
819 bool DoStatement::hasContinue()
824 /******************************** ForStatement ***************************/
826 ForStatement::ForStatement(Loc loc
, Statement
*init
, Expression
*condition
, Expression
*increment
, Statement
*body
, Loc endloc
)
830 this->condition
= condition
;
831 this->increment
= increment
;
833 this->endloc
= endloc
;
834 this->relatedLabeled
= NULL
;
837 Statement
*ForStatement::syntaxCopy()
839 return new ForStatement(loc
,
840 _init
? _init
->syntaxCopy() : NULL
,
841 condition
? condition
->syntaxCopy() : NULL
,
842 increment
? increment
->syntaxCopy() : NULL
,
847 Statement
*ForStatement::scopeCode(Scope
*sc
, Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
849 //printf("ForStatement::scopeCode()\n");
850 Statement::scopeCode(sc
, sentry
, sexception
, sfinally
);
854 bool ForStatement::hasBreak()
856 //printf("ForStatement::hasBreak()\n");
860 bool ForStatement::hasContinue()
865 /******************************** ForeachStatement ***************************/
867 ForeachStatement::ForeachStatement(Loc loc
, TOK op
, Parameters
*parameters
,
868 Expression
*aggr
, Statement
*body
, Loc endloc
)
872 this->parameters
= parameters
;
875 this->endloc
= endloc
;
886 Statement
*ForeachStatement::syntaxCopy()
888 return new ForeachStatement(loc
, op
,
889 Parameter::arraySyntaxCopy(parameters
),
891 _body
? _body
->syntaxCopy() : NULL
,
895 bool ForeachStatement::checkForArgTypes()
899 for (size_t i
= 0; i
< parameters
->length
; i
++)
901 Parameter
*p
= (*parameters
)[i
];
904 error("cannot infer type for %s", p
->ident
->toChars());
905 p
->type
= Type::terror
;
912 bool ForeachStatement::hasBreak()
917 bool ForeachStatement::hasContinue()
922 /**************************** ForeachRangeStatement ***************************/
925 ForeachRangeStatement::ForeachRangeStatement(Loc loc
, TOK op
, Parameter
*prm
,
926 Expression
*lwr
, Expression
*upr
, Statement
*body
, Loc endloc
)
934 this->endloc
= endloc
;
939 Statement
*ForeachRangeStatement::syntaxCopy()
941 return new ForeachRangeStatement(loc
, op
,
945 _body
? _body
->syntaxCopy() : NULL
,
949 bool ForeachRangeStatement::hasBreak()
954 bool ForeachRangeStatement::hasContinue()
959 /******************************** IfStatement ***************************/
961 IfStatement::IfStatement(Loc loc
, Parameter
*prm
, Expression
*condition
, Statement
*ifbody
, Statement
*elsebody
, Loc endloc
)
965 this->condition
= condition
;
966 this->ifbody
= ifbody
;
967 this->elsebody
= elsebody
;
968 this->endloc
= endloc
;
972 Statement
*IfStatement::syntaxCopy()
974 return new IfStatement(loc
,
975 prm
? prm
->syntaxCopy() : NULL
,
976 condition
->syntaxCopy(),
977 ifbody
? ifbody
->syntaxCopy() : NULL
,
978 elsebody
? elsebody
->syntaxCopy() : NULL
,
982 /******************************** ConditionalStatement ***************************/
984 ConditionalStatement::ConditionalStatement(Loc loc
, Condition
*condition
, Statement
*ifbody
, Statement
*elsebody
)
987 this->condition
= condition
;
988 this->ifbody
= ifbody
;
989 this->elsebody
= elsebody
;
992 Statement
*ConditionalStatement::syntaxCopy()
994 return new ConditionalStatement(loc
,
995 condition
->syntaxCopy(),
996 ifbody
->syntaxCopy(),
997 elsebody
? elsebody
->syntaxCopy() : NULL
);
1000 Statements
*ConditionalStatement::flatten(Scope
*sc
)
1004 //printf("ConditionalStatement::flatten()\n");
1005 if (condition
->include(sc
))
1007 DebugCondition
*dc
= condition
->isDebugCondition();
1009 s
= new DebugStatement(loc
, ifbody
);
1016 Statements
*a
= new Statements();
1021 /******************************** StaticForeachStatement ********************/
1023 /* Static foreach statements, like:
1026 * static foreach(i; 0 .. 10)
1033 StaticForeachStatement::StaticForeachStatement(Loc loc
, StaticForeach
*sfe
)
1039 Statement
*StaticForeachStatement::syntaxCopy()
1041 return new StaticForeachStatement(loc
, sfe
->syntaxCopy());
1044 Statements
*StaticForeachStatement::flatten(Scope
*sc
)
1046 staticForeachPrepare(sfe
, sc
);
1047 if (staticForeachReady(sfe
))
1049 Statement
*s
= makeTupleForeachStatic(sc
, sfe
->aggrfe
, sfe
->needExpansion
);
1050 Statements
*result
= s
->flatten(sc
);
1055 result
= new Statements();
1061 Statements
*result
= new Statements();
1062 result
->push(new ErrorStatement());
1067 /******************************** PragmaStatement ***************************/
1069 PragmaStatement::PragmaStatement(Loc loc
, Identifier
*ident
, Expressions
*args
, Statement
*body
)
1072 this->ident
= ident
;
1077 Statement
*PragmaStatement::syntaxCopy()
1079 return new PragmaStatement(loc
, ident
,
1080 Expression::arraySyntaxCopy(args
),
1081 _body
? _body
->syntaxCopy() : NULL
);
1084 /******************************** StaticAssertStatement ***************************/
1086 StaticAssertStatement::StaticAssertStatement(StaticAssert
*sa
)
1087 : Statement(sa
->loc
)
1092 Statement
*StaticAssertStatement::syntaxCopy()
1094 return new StaticAssertStatement((StaticAssert
*)sa
->syntaxCopy(NULL
));
1097 /******************************** SwitchStatement ***************************/
1099 SwitchStatement::SwitchStatement(Loc loc
, Expression
*c
, Statement
*b
, bool isFinal
)
1102 this->condition
= c
;
1104 this->isFinal
= isFinal
;
1113 Statement
*SwitchStatement::syntaxCopy()
1115 return new SwitchStatement(loc
,
1116 condition
->syntaxCopy(),
1117 _body
->syntaxCopy(),
1121 bool SwitchStatement::hasBreak()
1126 static bool checkVar(SwitchStatement
*s
, VarDeclaration
*vd
)
1128 if (!vd
|| vd
->isDataseg() || (vd
->storage_class
& STCmanifest
))
1131 VarDeclaration
*last
= s
->lastVar
;
1132 while (last
&& last
!= vd
)
1133 last
= last
->lastVar
;
1136 // All good, the label's scope has no variables
1138 else if (vd
->storage_class
& STCexptemp
)
1140 // Lifetime ends at end of expression, so no issue with skipping the statement
1142 else if (vd
->ident
== Id::withSym
)
1144 s
->deprecation("`switch` skips declaration of `with` temporary at %s", vd
->loc
.toChars());
1149 s
->deprecation("`switch` skips declaration of variable %s at %s", vd
->toPrettyChars(), vd
->loc
.toChars());
1156 bool SwitchStatement::checkLabel()
1158 const bool error
= true;
1160 if (sdefault
&& checkVar(this, sdefault
->lastVar
))
1161 return !error
; // return error once fully deprecated
1163 for (size_t i
= 0; i
< cases
->length
; i
++)
1165 CaseStatement
*scase
= (*cases
)[i
];
1166 if (scase
&& checkVar(this, scase
->lastVar
))
1167 return !error
; // return error once fully deprecated
1172 /******************************** CaseStatement ***************************/
1174 CaseStatement::CaseStatement(Loc loc
, Expression
*exp
, Statement
*s
)
1178 this->statement
= s
;
1183 Statement
*CaseStatement::syntaxCopy()
1185 return new CaseStatement(loc
,
1187 statement
->syntaxCopy());
1190 int CaseStatement::compare(RootObject
*obj
)
1192 // Sort cases so we can do an efficient lookup
1193 CaseStatement
*cs2
= (CaseStatement
*)(obj
);
1195 return exp
->compare(cs2
->exp
);
1198 /******************************** CaseRangeStatement ***************************/
1201 CaseRangeStatement::CaseRangeStatement(Loc loc
, Expression
*first
,
1202 Expression
*last
, Statement
*s
)
1205 this->first
= first
;
1207 this->statement
= s
;
1210 Statement
*CaseRangeStatement::syntaxCopy()
1212 return new CaseRangeStatement(loc
,
1213 first
->syntaxCopy(),
1215 statement
->syntaxCopy());
1218 /******************************** DefaultStatement ***************************/
1220 DefaultStatement::DefaultStatement(Loc loc
, Statement
*s
)
1223 this->statement
= s
;
1224 this->lastVar
= NULL
;
1227 Statement
*DefaultStatement::syntaxCopy()
1229 return new DefaultStatement(loc
, statement
->syntaxCopy());
1232 /******************************** GotoDefaultStatement ***************************/
1234 GotoDefaultStatement::GotoDefaultStatement(Loc loc
)
1240 Statement
*GotoDefaultStatement::syntaxCopy()
1242 return new GotoDefaultStatement(loc
);
1245 /******************************** GotoCaseStatement ***************************/
1247 GotoCaseStatement::GotoCaseStatement(Loc loc
, Expression
*exp
)
1254 Statement
*GotoCaseStatement::syntaxCopy()
1256 return new GotoCaseStatement(loc
, exp
? exp
->syntaxCopy() : NULL
);
1259 /******************************** SwitchErrorStatement ***************************/
1261 SwitchErrorStatement::SwitchErrorStatement(Loc loc
)
1266 /******************************** ReturnStatement ***************************/
1268 ReturnStatement::ReturnStatement(Loc loc
, Expression
*exp
)
1275 Statement
*ReturnStatement::syntaxCopy()
1277 return new ReturnStatement(loc
, exp
? exp
->syntaxCopy() : NULL
);
1280 /******************************** BreakStatement ***************************/
1282 BreakStatement::BreakStatement(Loc loc
, Identifier
*ident
)
1285 this->ident
= ident
;
1288 Statement
*BreakStatement::syntaxCopy()
1290 return new BreakStatement(loc
, ident
);
1293 /******************************** ContinueStatement ***************************/
1295 ContinueStatement::ContinueStatement(Loc loc
, Identifier
*ident
)
1298 this->ident
= ident
;
1301 Statement
*ContinueStatement::syntaxCopy()
1303 return new ContinueStatement(loc
, ident
);
1306 /******************************** SynchronizedStatement ***************************/
1308 SynchronizedStatement::SynchronizedStatement(Loc loc
, Expression
*exp
, Statement
*body
)
1315 Statement
*SynchronizedStatement::syntaxCopy()
1317 return new SynchronizedStatement(loc
,
1318 exp
? exp
->syntaxCopy() : NULL
,
1319 _body
? _body
->syntaxCopy() : NULL
);
1322 bool SynchronizedStatement::hasBreak()
1324 return false; //true;
1327 bool SynchronizedStatement::hasContinue()
1329 return false; //true;
1332 /******************************** WithStatement ***************************/
1334 WithStatement::WithStatement(Loc loc
, Expression
*exp
, Statement
*body
, Loc endloc
)
1339 this->endloc
= endloc
;
1343 Statement
*WithStatement::syntaxCopy()
1345 return new WithStatement(loc
,
1347 _body
? _body
->syntaxCopy() : NULL
, endloc
);
1350 /******************************** TryCatchStatement ***************************/
1352 TryCatchStatement::TryCatchStatement(Loc loc
, Statement
*body
, Catches
*catches
)
1356 this->catches
= catches
;
1359 Statement
*TryCatchStatement::syntaxCopy()
1361 Catches
*a
= new Catches();
1362 a
->setDim(catches
->length
);
1363 for (size_t i
= 0; i
< a
->length
; i
++)
1365 Catch
*c
= (*catches
)[i
];
1366 (*a
)[i
] = c
->syntaxCopy();
1368 return new TryCatchStatement(loc
, _body
->syntaxCopy(), a
);
1371 bool TryCatchStatement::hasBreak()
1376 /******************************** Catch ***************************/
1378 Catch::Catch(Loc loc
, Type
*t
, Identifier
*id
, Statement
*handler
)
1380 //printf("Catch(%s, loc = %s)\n", id->toChars(), loc.toChars());
1384 this->handler
= handler
;
1387 internalCatch
= false;
1390 Catch
*Catch::syntaxCopy()
1392 Catch
*c
= new Catch(loc
,
1393 type
? type
->syntaxCopy() : getThrowable(),
1395 (handler
? handler
->syntaxCopy() : NULL
));
1396 c
->internalCatch
= internalCatch
;
1400 /****************************** TryFinallyStatement ***************************/
1402 TryFinallyStatement::TryFinallyStatement(Loc loc
, Statement
*body
, Statement
*finalbody
)
1406 this->finalbody
= finalbody
;
1409 TryFinallyStatement
*TryFinallyStatement::create(Loc loc
, Statement
*body
, Statement
*finalbody
)
1411 return new TryFinallyStatement(loc
, body
, finalbody
);
1414 Statement
*TryFinallyStatement::syntaxCopy()
1416 return new TryFinallyStatement(loc
,
1417 _body
->syntaxCopy(), finalbody
->syntaxCopy());
1420 bool TryFinallyStatement::hasBreak()
1422 return false; //true;
1425 bool TryFinallyStatement::hasContinue()
1427 return false; //true;
1430 /****************************** ScopeGuardStatement ***************************/
1432 ScopeGuardStatement::ScopeGuardStatement(Loc loc
, TOK tok
, Statement
*statement
)
1436 this->statement
= statement
;
1439 Statement
*ScopeGuardStatement::syntaxCopy()
1441 return new ScopeGuardStatement(loc
, tok
, statement
->syntaxCopy());
1444 Statement
*ScopeGuardStatement::scopeCode(Scope
*sc
, Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
1446 //printf("ScopeGuardStatement::scopeCode()\n");
1452 Statement
*s
= new PeelStatement(statement
);
1456 case TOKon_scope_exit
:
1460 case TOKon_scope_failure
:
1464 case TOKon_scope_success
:
1467 * sentry: bool x = false;
1468 * sexception: x = true;
1469 * sfinally: if (!x) statement;
1471 VarDeclaration
*v
= copyToTemp(0, "__os", new IntegerExp(Loc(), 0, Type::tbool
));
1472 dsymbolSemantic(v
, sc
);
1473 *sentry
= new ExpStatement(loc
, v
);
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
);
1479 e
= new VarExp(Loc(), v
);
1480 e
= new NotExp(Loc(), e
);
1481 *sfinally
= new IfStatement(Loc(), NULL
, e
, s
, NULL
, Loc());
1492 /******************************** ThrowStatement ***************************/
1494 ThrowStatement::ThrowStatement(Loc loc
, Expression
*exp
)
1498 this->internalThrow
= false;
1501 Statement
*ThrowStatement::syntaxCopy()
1503 ThrowStatement
*s
= new ThrowStatement(loc
, exp
->syntaxCopy());
1504 s
->internalThrow
= internalThrow
;
1508 /******************************** DebugStatement **************************/
1510 DebugStatement::DebugStatement(Loc loc
, Statement
*statement
)
1513 this->statement
= statement
;
1516 Statement
*DebugStatement::syntaxCopy()
1518 return new DebugStatement(loc
,
1519 statement
? statement
->syntaxCopy() : NULL
);
1522 Statements
*DebugStatement::flatten(Scope
*sc
)
1524 Statements
*a
= statement
? statement
->flatten(sc
) : NULL
;
1527 for (size_t i
= 0; i
< a
->length
; i
++)
1528 { Statement
*s
= (*a
)[i
];
1530 s
= new DebugStatement(loc
, s
);
1538 /******************************** GotoStatement ***************************/
1540 GotoStatement::GotoStatement(Loc loc
, Identifier
*ident
)
1543 this->ident
= ident
;
1547 this->lastVar
= NULL
;
1550 Statement
*GotoStatement::syntaxCopy()
1552 return new GotoStatement(loc
, ident
);
1555 bool GotoStatement::checkLabel()
1557 if (!label
->statement
)
1559 error("label `%s` is undefined", label
->toChars());
1563 if (label
->statement
->os
!= os
)
1565 if (os
&& os
->tok
== TOKon_scope_failure
&& !label
->statement
->os
)
1567 // Jump out from scope(failure) block is allowed.
1571 if (label
->statement
->os
)
1572 error("cannot goto in to %s block", Token::toChars(label
->statement
->os
->tok
));
1574 error("cannot goto out of %s block", Token::toChars(os
->tok
));
1579 if (label
->statement
->tf
!= tf
)
1581 error("cannot goto in or out of finally block");
1585 VarDeclaration
*vd
= label
->statement
->lastVar
;
1586 if (!vd
|| vd
->isDataseg() || (vd
->storage_class
& STCmanifest
))
1589 VarDeclaration
*last
= lastVar
;
1590 while (last
&& last
!= vd
)
1591 last
= last
->lastVar
;
1594 // All good, the label's scope has no variables
1596 else if (vd
->ident
== Id::withSym
)
1598 error("goto skips declaration of with temporary at %s", vd
->loc
.toChars());
1603 error("goto skips declaration of variable %s at %s", vd
->toPrettyChars(), vd
->loc
.toChars());
1610 /******************************** LabelStatement ***************************/
1612 LabelStatement::LabelStatement(Loc loc
, Identifier
*ident
, Statement
*statement
)
1615 this->ident
= ident
;
1616 this->statement
= statement
;
1619 this->lastVar
= NULL
;
1620 this->gotoTarget
= NULL
;
1621 this->breaks
= false;
1624 Statement
*LabelStatement::syntaxCopy()
1626 return new LabelStatement(loc
, ident
, statement
? statement
->syntaxCopy() : NULL
);
1629 Statement
*LabelStatement::scopeCode(Scope
*sc
, Statement
**sentry
, Statement
**sexit
, Statement
**sfinally
)
1631 //printf("LabelStatement::scopeCode()\n");
1633 statement
= statement
->scopeCode(sc
, sentry
, sexit
, sfinally
);
1643 Statements
*LabelStatement::flatten(Scope
*sc
)
1645 Statements
*a
= NULL
;
1649 a
= statement
->flatten(sc
);
1654 a
->push(new ExpStatement(loc
, (Expression
*)NULL
));
1657 // reuse 'this' LabelStatement
1658 this->statement
= (*a
)[0];
1666 /******************************** LabelDsymbol ***************************/
1668 LabelDsymbol::LabelDsymbol(Identifier
*ident
)
1674 LabelDsymbol
*LabelDsymbol::create(Identifier
*ident
)
1676 return new LabelDsymbol(ident
);
1679 LabelDsymbol
*LabelDsymbol::isLabel() // is this a LabelDsymbol()?
1685 /************************ AsmStatement ***************************************/
1687 AsmStatement::AsmStatement(Loc loc
, Token
*tokens
)
1690 this->tokens
= tokens
;
1693 Statement
*AsmStatement::syntaxCopy()
1695 return new AsmStatement(loc
, tokens
);
1699 /************************ InlineAsmStatement **********************************/
1701 InlineAsmStatement::InlineAsmStatement(Loc loc
, Token
*tokens
)
1702 : AsmStatement(loc
, tokens
)
1711 Statement
*InlineAsmStatement::syntaxCopy()
1713 return new InlineAsmStatement(loc
, tokens
);
1717 /************************ GccAsmStatement ***************************************/
1719 GccAsmStatement::GccAsmStatement(Loc loc
, Token
*tokens
)
1720 : AsmStatement(loc
, tokens
)
1722 this->stc
= STCundefined
;
1725 this->outputargs
= 0;
1727 this->constraints
= NULL
;
1728 this->clobbers
= NULL
;
1729 this->labels
= NULL
;
1733 Statement
*GccAsmStatement::syntaxCopy()
1735 return new GccAsmStatement(loc
, tokens
);
1738 /************************ CompoundAsmStatement ***************************************/
1740 CompoundAsmStatement::CompoundAsmStatement(Loc loc
, Statements
*s
, StorageClass stc
)
1741 : CompoundStatement(loc
, s
)
1746 CompoundAsmStatement
*CompoundAsmStatement::syntaxCopy()
1748 Statements
*a
= new Statements();
1749 a
->setDim(statements
->length
);
1750 for (size_t i
= 0; i
< statements
->length
; i
++)
1752 Statement
*s
= (*statements
)[i
];
1753 (*a
)[i
] = s
? s
->syntaxCopy() : NULL
;
1755 return new CompoundAsmStatement(loc
, a
, stc
);
1758 Statements
*CompoundAsmStatement::flatten(Scope
*)
1763 /************************ ImportStatement ***************************************/
1765 ImportStatement::ImportStatement(Loc loc
, Dsymbols
*imports
)
1768 this->imports
= imports
;
1771 Statement
*ImportStatement::syntaxCopy()
1773 Dsymbols
*m
= new Dsymbols();
1774 m
->setDim(imports
->length
);
1775 for (size_t i
= 0; i
< imports
->length
; i
++)
1777 Dsymbol
*s
= (*imports
)[i
];
1778 (*m
)[i
] = s
->syntaxCopy(NULL
);
1780 return new ImportStatement(loc
, m
);