]>
git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/d/dmd/statement.c
2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2018 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 Expression
*semantic(Expression
*e
, Scope
*sc
);
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
.extractString();
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 void Statement::print()
112 fprintf(stderr
, "%s\n", toChars());
116 const char *Statement::toChars()
121 ::toCBuffer(this, &buf
, &hgs
);
122 return buf
.extractString();
126 void Statement::error(const char *format
, ...)
129 va_start(ap
, format
);
130 ::verror(loc
, format
, ap
);
134 void Statement::warning(const char *format
, ...)
137 va_start(ap
, format
);
138 ::vwarning(loc
, format
, ap
);
142 void Statement::deprecation(const char *format
, ...)
145 va_start(ap
, format
);
146 ::vdeprecation(loc
, format
, ap
);
150 bool Statement::hasBreak()
152 //printf("Statement::hasBreak()\n");
156 bool Statement::hasContinue()
161 /* ============================================== */
162 // true if statement uses exception handling
164 bool Statement::usesEH()
166 class UsesEH
: public StoppableVisitor
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; }
177 return walkPostorder(this, &ueh
);
180 /* ============================================== */
181 // true if statement 'comes from' somewhere else, like a goto
183 bool Statement::comeFrom()
185 class ComeFrom
: public StoppableVisitor
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; }
196 return walkPostorder(this, &cf
);
199 /* ============================================== */
200 // Return true if statement has executable code.
202 bool Statement::hasCode()
204 class HasCode
: public StoppableVisitor
207 void visit(Statement
*)
212 void visit(ExpStatement
*s
)
216 stop
= s
->exp
->hasCode();
220 void visit(CompoundStatement
*) {}
221 void visit(ScopeStatement
*) {}
222 void visit(ImportStatement
*) {}
226 return walkPostorder(this, &hc
);
229 Statement
*Statement::last()
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
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
244 Statement
*Statement::scopeCode(Scope
*, Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
246 //printf("Statement::scopeCode()\n");
254 /*********************************
255 * Flatten out the scope by presenting the statement
256 * as an array of statements.
257 * Returns NULL if no flattening necessary.
260 Statements
*Statement::flatten(Scope
*)
266 /******************************** ErrorStatement ***************************/
268 ErrorStatement::ErrorStatement()
271 assert(global
.gaggedErrors
|| global
.errors
);
274 Statement
*ErrorStatement::syntaxCopy()
279 /******************************** PeelStatement ***************************/
281 PeelStatement::PeelStatement(Statement
*s
)
287 /******************************** ExpStatement ***************************/
289 ExpStatement::ExpStatement(Loc loc
, Expression
*exp
)
295 ExpStatement::ExpStatement(Loc loc
, Dsymbol
*declaration
)
298 this->exp
= new DeclarationExp(loc
, declaration
);
301 ExpStatement
*ExpStatement::create(Loc loc
, Expression
*exp
)
303 return new ExpStatement(loc
, exp
);
306 Statement
*ExpStatement::syntaxCopy()
308 return new ExpStatement(loc
, exp
? exp
->syntaxCopy() : NULL
);
311 Statement
*ExpStatement::scopeCode(Scope
*, Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
313 //printf("ExpStatement::scopeCode()\n");
322 if (exp
->op
== TOKdeclaration
)
324 DeclarationExp
*de
= (DeclarationExp
*)(exp
);
325 VarDeclaration
*v
= de
->declaration
->isVarDeclaration();
326 if (v
&& !v
->isDataseg())
328 if (v
->needsScopeDtor())
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
340 /****************************************
341 * Convert TemplateMixin members (== Dsymbols) to Statements.
343 Statement
*toStatement(Dsymbol
*s
)
345 class ToStmt
: public Visitor
355 Statement
*visitMembers(Loc loc
, Dsymbols
*a
)
360 Statements
*statements
= new Statements();
361 for (size_t i
= 0; i
< a
->dim
; i
++)
363 statements
->push(toStatement((*a
)[i
]));
365 return new CompoundStatement(loc
, statements
);
368 void visit(Dsymbol
*s
)
370 ::error(Loc(), "Internal Compiler Error: cannot mixin %s %s\n", s
->kind(), s
->toChars());
371 result
= new ErrorStatement();
374 void visit(TemplateMixin
*tm
)
376 Statements
*a
= new Statements();
377 for (size_t i
= 0; i
< tm
->members
->dim
; i
++)
379 Statement
*s
= toStatement((*tm
->members
)[i
]);
383 result
= new CompoundStatement(tm
->loc
, a
);
386 /* An actual declaration symbol will be converted to DeclarationExp
389 Statement
*declStmt(Dsymbol
*s
)
391 DeclarationExp
*de
= new DeclarationExp(s
->loc
, s
);
392 de
->type
= Type::tvoid
; // avoid repeated semantic
393 return new ExpStatement(s
->loc
, de
);
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
); }
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.
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
); }
413 void visit(StaticAssert
*) {}
414 void visit(Import
*) {}
415 void visit(PragmaDeclaration
*) {}
417 void visit(ConditionalDeclaration
*d
)
419 result
= visitMembers(d
->loc
, d
->include(NULL
, NULL
));
422 void visit(CompileDeclaration
*d
)
424 result
= visitMembers(d
->loc
, d
->include(NULL
, NULL
));
436 Statements
*ExpStatement::flatten(Scope
*sc
)
438 /* Bugzilla 14243: expand template mixin in statement scope
439 * to handle variable destructors.
441 if (exp
&& exp
->op
== TOKdeclaration
)
443 Dsymbol
*d
= ((DeclarationExp
*)exp
)->declaration
;
444 if (TemplateMixin
*tm
= d
->isTemplateMixin())
446 Expression
*e
= semantic(exp
, sc
);
447 if (e
->op
== TOKerror
|| tm
->errors
)
449 Statements
*a
= new Statements();
450 a
->push(new ErrorStatement());
455 Statement
*s
= toStatement(tm
);
456 Statements
*a
= new Statements();
464 /******************************** DtorExpStatement ***************************/
466 DtorExpStatement::DtorExpStatement(Loc loc
, Expression
*exp
, VarDeclaration
*v
)
467 : ExpStatement(loc
, exp
)
472 Statement
*DtorExpStatement::syntaxCopy()
474 return new DtorExpStatement(loc
, exp
? exp
->syntaxCopy() : NULL
, var
);
477 /******************************** CompileStatement ***************************/
479 CompileStatement::CompileStatement(Loc loc
, Expression
*exp
)
485 Statement
*CompileStatement::syntaxCopy()
487 return new CompileStatement(loc
, exp
->syntaxCopy());
490 Statements
*CompileStatement::flatten(Scope
*sc
)
492 //printf("CompileStatement::flatten() %s\n", exp->toChars());
493 sc
= sc
->startCTFE();
494 exp
= semantic(exp
, sc
);
495 exp
= resolveProperties(sc
, exp
);
498 Statements
*a
= new Statements();
499 if (exp
->op
!= TOKerror
)
501 Expression
*e
= exp
->ctfeInterpret();
502 if (e
->op
== TOKerror
) // Bugzilla 15974
504 StringExp
*se
= e
->toStringExp();
506 error("argument to mixin must be a string, not (%s) of type %s", exp
->toChars(), exp
->type
->toChars());
510 unsigned errors
= global
.errors
;
511 Parser
p(loc
, sc
->_module
, (utf8_t
*)se
->string
, se
->len
, 0);
514 while (p
.token
.value
!= TOKeof
)
516 Statement
*s
= p
.parseStatement(PSsemi
| PScurlyscope
);
519 assert(!p
.errors
|| global
.errors
!= errors
); // make sure we caught all the cases
528 a
->push(new ErrorStatement());
532 /******************************** CompoundStatement ***************************/
534 CompoundStatement::CompoundStatement(Loc loc
, Statements
*s
)
540 CompoundStatement::CompoundStatement(Loc loc
, Statement
*s1
, Statement
*s2
)
543 statements
= new Statements();
544 statements
->reserve(2);
545 statements
->push(s1
);
546 statements
->push(s2
);
549 CompoundStatement::CompoundStatement(Loc loc
, Statement
*s1
)
552 statements
= new Statements();
553 statements
->push(s1
);
556 CompoundStatement
*CompoundStatement::create(Loc loc
, Statement
*s1
, Statement
*s2
)
558 return new CompoundStatement(loc
, s1
, s2
);
561 Statement
*CompoundStatement::syntaxCopy()
563 Statements
*a
= new Statements();
564 a
->setDim(statements
->dim
);
565 for (size_t i
= 0; i
< statements
->dim
; i
++)
567 Statement
*s
= (*statements
)[i
];
568 (*a
)[i
] = s
? s
->syntaxCopy() : NULL
;
570 return new CompoundStatement(loc
, a
);
573 Statements
*CompoundStatement::flatten(Scope
*)
578 ReturnStatement
*CompoundStatement::isReturnStatement()
580 ReturnStatement
*rs
= NULL
;
582 for (size_t i
= 0; i
< statements
->dim
; i
++)
584 Statement
*s
= (*statements
)[i
];
587 rs
= s
->isReturnStatement();
595 Statement
*CompoundStatement::last()
599 for (size_t i
= statements
->dim
; i
; --i
)
600 { s
= (*statements
)[i
- 1];
611 /******************************** CompoundDeclarationStatement ***************************/
613 CompoundDeclarationStatement::CompoundDeclarationStatement(Loc loc
, Statements
*s
)
614 : CompoundStatement(loc
, s
)
619 Statement
*CompoundDeclarationStatement::syntaxCopy()
621 Statements
*a
= new Statements();
622 a
->setDim(statements
->dim
);
623 for (size_t i
= 0; i
< statements
->dim
; i
++)
625 Statement
*s
= (*statements
)[i
];
626 (*a
)[i
] = s
? s
->syntaxCopy() : NULL
;
628 return new CompoundDeclarationStatement(loc
, a
);
631 /**************************** UnrolledLoopStatement ***************************/
633 UnrolledLoopStatement::UnrolledLoopStatement(Loc loc
, Statements
*s
)
639 Statement
*UnrolledLoopStatement::syntaxCopy()
641 Statements
*a
= new Statements();
642 a
->setDim(statements
->dim
);
643 for (size_t i
= 0; i
< statements
->dim
; i
++)
645 Statement
*s
= (*statements
)[i
];
646 (*a
)[i
] = s
? s
->syntaxCopy() : NULL
;
648 return new UnrolledLoopStatement(loc
, a
);
651 bool UnrolledLoopStatement::hasBreak()
656 bool UnrolledLoopStatement::hasContinue()
661 /******************************** ScopeStatement ***************************/
663 ScopeStatement::ScopeStatement(Loc loc
, Statement
*s
, Loc endloc
)
667 this->endloc
= endloc
;
670 Statement
*ScopeStatement::syntaxCopy()
672 return new ScopeStatement(loc
, statement
? statement
->syntaxCopy() : NULL
, endloc
);
675 ReturnStatement
*ScopeStatement::isReturnStatement()
678 return statement
->isReturnStatement();
682 bool ScopeStatement::hasBreak()
684 //printf("ScopeStatement::hasBreak() %s\n", toChars());
685 return statement
? statement
->hasBreak() : false;
688 bool ScopeStatement::hasContinue()
690 return statement
? statement
->hasContinue() : false;
693 /******************************** WhileStatement ***************************/
695 WhileStatement::WhileStatement(Loc loc
, Expression
*c
, Statement
*b
, Loc endloc
)
700 this->endloc
= endloc
;
703 Statement
*WhileStatement::syntaxCopy()
705 return new WhileStatement(loc
,
706 condition
->syntaxCopy(),
707 _body
? _body
->syntaxCopy() : NULL
,
711 bool WhileStatement::hasBreak()
716 bool WhileStatement::hasContinue()
721 /******************************** DoStatement ***************************/
723 DoStatement::DoStatement(Loc loc
, Statement
*b
, Expression
*c
, Loc endloc
)
728 this->endloc
= endloc
;
731 Statement
*DoStatement::syntaxCopy()
733 return new DoStatement(loc
,
734 _body
? _body
->syntaxCopy() : NULL
,
735 condition
->syntaxCopy(),
739 bool DoStatement::hasBreak()
744 bool DoStatement::hasContinue()
749 /******************************** ForStatement ***************************/
751 ForStatement::ForStatement(Loc loc
, Statement
*init
, Expression
*condition
, Expression
*increment
, Statement
*body
, Loc endloc
)
755 this->condition
= condition
;
756 this->increment
= increment
;
758 this->endloc
= endloc
;
759 this->relatedLabeled
= NULL
;
762 Statement
*ForStatement::syntaxCopy()
764 return new ForStatement(loc
,
765 _init
? _init
->syntaxCopy() : NULL
,
766 condition
? condition
->syntaxCopy() : NULL
,
767 increment
? increment
->syntaxCopy() : NULL
,
772 Statement
*ForStatement::scopeCode(Scope
*sc
, Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
774 //printf("ForStatement::scopeCode()\n");
775 Statement::scopeCode(sc
, sentry
, sexception
, sfinally
);
779 bool ForStatement::hasBreak()
781 //printf("ForStatement::hasBreak()\n");
785 bool ForStatement::hasContinue()
790 /******************************** ForeachStatement ***************************/
792 ForeachStatement::ForeachStatement(Loc loc
, TOK op
, Parameters
*parameters
,
793 Expression
*aggr
, Statement
*body
, Loc endloc
)
797 this->parameters
= parameters
;
800 this->endloc
= endloc
;
811 Statement
*ForeachStatement::syntaxCopy()
813 return new ForeachStatement(loc
, op
,
814 Parameter::arraySyntaxCopy(parameters
),
816 _body
? _body
->syntaxCopy() : NULL
,
820 bool ForeachStatement::checkForArgTypes()
824 for (size_t i
= 0; i
< parameters
->dim
; i
++)
826 Parameter
*p
= (*parameters
)[i
];
829 error("cannot infer type for %s", p
->ident
->toChars());
830 p
->type
= Type::terror
;
837 bool ForeachStatement::hasBreak()
842 bool ForeachStatement::hasContinue()
847 /**************************** ForeachRangeStatement ***************************/
850 ForeachRangeStatement::ForeachRangeStatement(Loc loc
, TOK op
, Parameter
*prm
,
851 Expression
*lwr
, Expression
*upr
, Statement
*body
, Loc endloc
)
859 this->endloc
= endloc
;
864 Statement
*ForeachRangeStatement::syntaxCopy()
866 return new ForeachRangeStatement(loc
, op
,
870 _body
? _body
->syntaxCopy() : NULL
,
874 bool ForeachRangeStatement::hasBreak()
879 bool ForeachRangeStatement::hasContinue()
884 /******************************** IfStatement ***************************/
886 IfStatement::IfStatement(Loc loc
, Parameter
*prm
, Expression
*condition
, Statement
*ifbody
, Statement
*elsebody
, Loc endloc
)
890 this->condition
= condition
;
891 this->ifbody
= ifbody
;
892 this->elsebody
= elsebody
;
893 this->endloc
= endloc
;
897 Statement
*IfStatement::syntaxCopy()
899 return new IfStatement(loc
,
900 prm
? prm
->syntaxCopy() : NULL
,
901 condition
->syntaxCopy(),
902 ifbody
? ifbody
->syntaxCopy() : NULL
,
903 elsebody
? elsebody
->syntaxCopy() : NULL
,
907 /******************************** ConditionalStatement ***************************/
909 ConditionalStatement::ConditionalStatement(Loc loc
, Condition
*condition
, Statement
*ifbody
, Statement
*elsebody
)
912 this->condition
= condition
;
913 this->ifbody
= ifbody
;
914 this->elsebody
= elsebody
;
917 Statement
*ConditionalStatement::syntaxCopy()
919 return new ConditionalStatement(loc
,
920 condition
->syntaxCopy(),
921 ifbody
->syntaxCopy(),
922 elsebody
? elsebody
->syntaxCopy() : NULL
);
925 Statements
*ConditionalStatement::flatten(Scope
*sc
)
929 //printf("ConditionalStatement::flatten()\n");
930 if (condition
->include(sc
, NULL
))
932 DebugCondition
*dc
= condition
->isDebugCondition();
934 s
= new DebugStatement(loc
, ifbody
);
941 Statements
*a
= new Statements();
946 /******************************** PragmaStatement ***************************/
948 PragmaStatement::PragmaStatement(Loc loc
, Identifier
*ident
, Expressions
*args
, Statement
*body
)
956 Statement
*PragmaStatement::syntaxCopy()
958 return new PragmaStatement(loc
, ident
,
959 Expression::arraySyntaxCopy(args
),
960 _body
? _body
->syntaxCopy() : NULL
);
963 /******************************** StaticAssertStatement ***************************/
965 StaticAssertStatement::StaticAssertStatement(StaticAssert
*sa
)
971 Statement
*StaticAssertStatement::syntaxCopy()
973 return new StaticAssertStatement((StaticAssert
*)sa
->syntaxCopy(NULL
));
976 /******************************** SwitchStatement ***************************/
978 SwitchStatement::SwitchStatement(Loc loc
, Expression
*c
, Statement
*b
, bool isFinal
)
983 this->isFinal
= isFinal
;
992 Statement
*SwitchStatement::syntaxCopy()
994 return new SwitchStatement(loc
,
995 condition
->syntaxCopy(),
1000 bool SwitchStatement::hasBreak()
1005 static bool checkVar(SwitchStatement
*s
, VarDeclaration
*vd
)
1007 if (!vd
|| vd
->isDataseg() || (vd
->storage_class
& STCmanifest
))
1010 VarDeclaration
*last
= s
->lastVar
;
1011 while (last
&& last
!= vd
)
1012 last
= last
->lastVar
;
1015 // All good, the label's scope has no variables
1017 else if (vd
->storage_class
& STCexptemp
)
1019 // Lifetime ends at end of expression, so no issue with skipping the statement
1021 else if (vd
->ident
== Id::withSym
)
1023 s
->deprecation("'switch' skips declaration of 'with' temporary at %s", vd
->loc
.toChars());
1028 s
->deprecation("'switch' skips declaration of variable %s at %s", vd
->toPrettyChars(), vd
->loc
.toChars());
1035 bool SwitchStatement::checkLabel()
1037 const bool error
= true;
1039 if (sdefault
&& checkVar(this, sdefault
->lastVar
))
1040 return !error
; // return error once fully deprecated
1042 for (size_t i
= 0; i
< cases
->dim
; i
++)
1044 CaseStatement
*scase
= (*cases
)[i
];
1045 if (scase
&& checkVar(this, scase
->lastVar
))
1046 return !error
; // return error once fully deprecated
1051 /******************************** CaseStatement ***************************/
1053 CaseStatement::CaseStatement(Loc loc
, Expression
*exp
, Statement
*s
)
1057 this->statement
= s
;
1062 Statement
*CaseStatement::syntaxCopy()
1064 return new CaseStatement(loc
,
1066 statement
->syntaxCopy());
1069 int CaseStatement::compare(RootObject
*obj
)
1071 // Sort cases so we can do an efficient lookup
1072 CaseStatement
*cs2
= (CaseStatement
*)(obj
);
1074 return exp
->compare(cs2
->exp
);
1077 /******************************** CaseRangeStatement ***************************/
1080 CaseRangeStatement::CaseRangeStatement(Loc loc
, Expression
*first
,
1081 Expression
*last
, Statement
*s
)
1084 this->first
= first
;
1086 this->statement
= s
;
1089 Statement
*CaseRangeStatement::syntaxCopy()
1091 return new CaseRangeStatement(loc
,
1092 first
->syntaxCopy(),
1094 statement
->syntaxCopy());
1097 /******************************** DefaultStatement ***************************/
1099 DefaultStatement::DefaultStatement(Loc loc
, Statement
*s
)
1102 this->statement
= s
;
1103 this->lastVar
= NULL
;
1106 Statement
*DefaultStatement::syntaxCopy()
1108 return new DefaultStatement(loc
, statement
->syntaxCopy());
1111 /******************************** GotoDefaultStatement ***************************/
1113 GotoDefaultStatement::GotoDefaultStatement(Loc loc
)
1119 Statement
*GotoDefaultStatement::syntaxCopy()
1121 return new GotoDefaultStatement(loc
);
1124 /******************************** GotoCaseStatement ***************************/
1126 GotoCaseStatement::GotoCaseStatement(Loc loc
, Expression
*exp
)
1133 Statement
*GotoCaseStatement::syntaxCopy()
1135 return new GotoCaseStatement(loc
, exp
? exp
->syntaxCopy() : NULL
);
1138 /******************************** SwitchErrorStatement ***************************/
1140 SwitchErrorStatement::SwitchErrorStatement(Loc loc
)
1145 /******************************** ReturnStatement ***************************/
1147 ReturnStatement::ReturnStatement(Loc loc
, Expression
*exp
)
1154 Statement
*ReturnStatement::syntaxCopy()
1156 return new ReturnStatement(loc
, exp
? exp
->syntaxCopy() : NULL
);
1159 /******************************** BreakStatement ***************************/
1161 BreakStatement::BreakStatement(Loc loc
, Identifier
*ident
)
1164 this->ident
= ident
;
1167 Statement
*BreakStatement::syntaxCopy()
1169 return new BreakStatement(loc
, ident
);
1172 /******************************** ContinueStatement ***************************/
1174 ContinueStatement::ContinueStatement(Loc loc
, Identifier
*ident
)
1177 this->ident
= ident
;
1180 Statement
*ContinueStatement::syntaxCopy()
1182 return new ContinueStatement(loc
, ident
);
1185 /******************************** SynchronizedStatement ***************************/
1187 SynchronizedStatement::SynchronizedStatement(Loc loc
, Expression
*exp
, Statement
*body
)
1194 Statement
*SynchronizedStatement::syntaxCopy()
1196 return new SynchronizedStatement(loc
,
1197 exp
? exp
->syntaxCopy() : NULL
,
1198 _body
? _body
->syntaxCopy() : NULL
);
1201 bool SynchronizedStatement::hasBreak()
1203 return false; //true;
1206 bool SynchronizedStatement::hasContinue()
1208 return false; //true;
1211 /******************************** WithStatement ***************************/
1213 WithStatement::WithStatement(Loc loc
, Expression
*exp
, Statement
*body
, Loc endloc
)
1218 this->endloc
= endloc
;
1222 Statement
*WithStatement::syntaxCopy()
1224 return new WithStatement(loc
,
1226 _body
? _body
->syntaxCopy() : NULL
, endloc
);
1229 /******************************** TryCatchStatement ***************************/
1231 TryCatchStatement::TryCatchStatement(Loc loc
, Statement
*body
, Catches
*catches
)
1235 this->catches
= catches
;
1238 Statement
*TryCatchStatement::syntaxCopy()
1240 Catches
*a
= new Catches();
1241 a
->setDim(catches
->dim
);
1242 for (size_t i
= 0; i
< a
->dim
; i
++)
1244 Catch
*c
= (*catches
)[i
];
1245 (*a
)[i
] = c
->syntaxCopy();
1247 return new TryCatchStatement(loc
, _body
->syntaxCopy(), a
);
1250 bool TryCatchStatement::hasBreak()
1255 /******************************** Catch ***************************/
1257 Catch::Catch(Loc loc
, Type
*t
, Identifier
*id
, Statement
*handler
)
1259 //printf("Catch(%s, loc = %s)\n", id->toChars(), loc.toChars());
1263 this->handler
= handler
;
1266 internalCatch
= false;
1269 Catch
*Catch::syntaxCopy()
1271 Catch
*c
= new Catch(loc
,
1272 type
? type
->syntaxCopy() : getThrowable(),
1274 (handler
? handler
->syntaxCopy() : NULL
));
1275 c
->internalCatch
= internalCatch
;
1279 /****************************** TryFinallyStatement ***************************/
1281 TryFinallyStatement::TryFinallyStatement(Loc loc
, Statement
*body
, Statement
*finalbody
)
1285 this->finalbody
= finalbody
;
1288 TryFinallyStatement
*TryFinallyStatement::create(Loc loc
, Statement
*body
, Statement
*finalbody
)
1290 return new TryFinallyStatement(loc
, body
, finalbody
);
1293 Statement
*TryFinallyStatement::syntaxCopy()
1295 return new TryFinallyStatement(loc
,
1296 _body
->syntaxCopy(), finalbody
->syntaxCopy());
1299 bool TryFinallyStatement::hasBreak()
1301 return false; //true;
1304 bool TryFinallyStatement::hasContinue()
1306 return false; //true;
1309 /****************************** OnScopeStatement ***************************/
1311 OnScopeStatement::OnScopeStatement(Loc loc
, TOK tok
, Statement
*statement
)
1315 this->statement
= statement
;
1318 Statement
*OnScopeStatement::syntaxCopy()
1320 return new OnScopeStatement(loc
, tok
, statement
->syntaxCopy());
1323 Statement
*OnScopeStatement::scopeCode(Scope
*, Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
1325 //printf("OnScopeStatement::scopeCode()\n");
1331 Statement
*s
= new PeelStatement(statement
);
1335 case TOKon_scope_exit
:
1339 case TOKon_scope_failure
:
1343 case TOKon_scope_success
:
1346 * sentry: bool x = false;
1347 * sexception: x = true;
1348 * sfinally: if (!x) statement;
1350 VarDeclaration
*v
= copyToTemp(0, "__os", new IntegerExp(Loc(), 0, Type::tbool
));
1351 *sentry
= new ExpStatement(loc
, v
);
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
);
1357 e
= new VarExp(Loc(), v
);
1358 e
= new NotExp(Loc(), e
);
1359 *sfinally
= new IfStatement(Loc(), NULL
, e
, s
, NULL
, Loc());
1370 /******************************** ThrowStatement ***************************/
1372 ThrowStatement::ThrowStatement(Loc loc
, Expression
*exp
)
1376 this->internalThrow
= false;
1379 Statement
*ThrowStatement::syntaxCopy()
1381 ThrowStatement
*s
= new ThrowStatement(loc
, exp
->syntaxCopy());
1382 s
->internalThrow
= internalThrow
;
1386 /******************************** DebugStatement **************************/
1388 DebugStatement::DebugStatement(Loc loc
, Statement
*statement
)
1391 this->statement
= statement
;
1394 Statement
*DebugStatement::syntaxCopy()
1396 return new DebugStatement(loc
,
1397 statement
? statement
->syntaxCopy() : NULL
);
1400 Statements
*DebugStatement::flatten(Scope
*sc
)
1402 Statements
*a
= statement
? statement
->flatten(sc
) : NULL
;
1405 for (size_t i
= 0; i
< a
->dim
; i
++)
1406 { Statement
*s
= (*a
)[i
];
1408 s
= new DebugStatement(loc
, s
);
1416 /******************************** GotoStatement ***************************/
1418 GotoStatement::GotoStatement(Loc loc
, Identifier
*ident
)
1421 this->ident
= ident
;
1425 this->lastVar
= NULL
;
1428 Statement
*GotoStatement::syntaxCopy()
1430 return new GotoStatement(loc
, ident
);
1433 bool GotoStatement::checkLabel()
1435 if (!label
->statement
)
1437 error("label '%s' is undefined", label
->toChars());
1441 if (label
->statement
->os
!= os
)
1443 if (os
&& os
->tok
== TOKon_scope_failure
&& !label
->statement
->os
)
1445 // Jump out from scope(failure) block is allowed.
1449 if (label
->statement
->os
)
1450 error("cannot goto in to %s block", Token::toChars(label
->statement
->os
->tok
));
1452 error("cannot goto out of %s block", Token::toChars(os
->tok
));
1457 if (label
->statement
->tf
!= tf
)
1459 error("cannot goto in or out of finally block");
1463 VarDeclaration
*vd
= label
->statement
->lastVar
;
1464 if (!vd
|| vd
->isDataseg() || (vd
->storage_class
& STCmanifest
))
1467 VarDeclaration
*last
= lastVar
;
1468 while (last
&& last
!= vd
)
1469 last
= last
->lastVar
;
1472 // All good, the label's scope has no variables
1474 else if (vd
->ident
== Id::withSym
)
1476 error("goto skips declaration of with temporary at %s", vd
->loc
.toChars());
1481 error("goto skips declaration of variable %s at %s", vd
->toPrettyChars(), vd
->loc
.toChars());
1488 /******************************** LabelStatement ***************************/
1490 LabelStatement::LabelStatement(Loc loc
, Identifier
*ident
, Statement
*statement
)
1493 this->ident
= ident
;
1494 this->statement
= statement
;
1497 this->lastVar
= NULL
;
1498 this->gotoTarget
= NULL
;
1499 this->breaks
= false;
1502 Statement
*LabelStatement::syntaxCopy()
1504 return new LabelStatement(loc
, ident
, statement
? statement
->syntaxCopy() : NULL
);
1507 Statement
*LabelStatement::scopeCode(Scope
*sc
, Statement
**sentry
, Statement
**sexit
, Statement
**sfinally
)
1509 //printf("LabelStatement::scopeCode()\n");
1511 statement
= statement
->scopeCode(sc
, sentry
, sexit
, sfinally
);
1521 Statements
*LabelStatement::flatten(Scope
*sc
)
1523 Statements
*a
= NULL
;
1527 a
= statement
->flatten(sc
);
1532 a
->push(new ExpStatement(loc
, (Expression
*)NULL
));
1535 // reuse 'this' LabelStatement
1536 this->statement
= (*a
)[0];
1544 /******************************** LabelDsymbol ***************************/
1546 LabelDsymbol::LabelDsymbol(Identifier
*ident
)
1552 LabelDsymbol
*LabelDsymbol::create(Identifier
*ident
)
1554 return new LabelDsymbol(ident
);
1557 LabelDsymbol
*LabelDsymbol::isLabel() // is this a LabelDsymbol()?
1563 /************************ AsmStatement ***************************************/
1565 AsmStatement::AsmStatement(Loc loc
, Token
*tokens
)
1568 this->tokens
= tokens
;
1571 Statement
*AsmStatement::syntaxCopy()
1573 return new AsmStatement(loc
, tokens
);
1577 /************************ InlineAsmStatement **********************************/
1579 InlineAsmStatement::InlineAsmStatement(Loc loc
, Token
*tokens
)
1580 : AsmStatement(loc
, tokens
)
1589 Statement
*InlineAsmStatement::syntaxCopy()
1591 return new InlineAsmStatement(loc
, tokens
);
1595 /************************ GccAsmStatement ***************************************/
1597 GccAsmStatement::GccAsmStatement(Loc loc
, Token
*tokens
)
1598 : AsmStatement(loc
, tokens
)
1600 this->stc
= STCundefined
;
1603 this->outputargs
= 0;
1605 this->constraints
= NULL
;
1606 this->clobbers
= NULL
;
1607 this->labels
= NULL
;
1611 Statement
*GccAsmStatement::syntaxCopy()
1613 return new GccAsmStatement(loc
, tokens
);
1616 /************************ CompoundAsmStatement ***************************************/
1618 CompoundAsmStatement::CompoundAsmStatement(Loc loc
, Statements
*s
, StorageClass stc
)
1619 : CompoundStatement(loc
, s
)
1624 CompoundAsmStatement
*CompoundAsmStatement::syntaxCopy()
1626 Statements
*a
= new Statements();
1627 a
->setDim(statements
->dim
);
1628 for (size_t i
= 0; i
< statements
->dim
; i
++)
1630 Statement
*s
= (*statements
)[i
];
1631 (*a
)[i
] = s
? s
->syntaxCopy() : NULL
;
1633 return new CompoundAsmStatement(loc
, a
, stc
);
1636 Statements
*CompoundAsmStatement::flatten(Scope
*)
1641 /************************ ImportStatement ***************************************/
1643 ImportStatement::ImportStatement(Loc loc
, Dsymbols
*imports
)
1646 this->imports
= imports
;
1649 Statement
*ImportStatement::syntaxCopy()
1651 Dsymbols
*m
= new Dsymbols();
1652 m
->setDim(imports
->dim
);
1653 for (size_t i
= 0; i
< imports
->dim
; i
++)
1655 Dsymbol
*s
= (*imports
)[i
];
1656 (*m
)[i
] = s
->syntaxCopy(NULL
);
1658 return new ImportStatement(loc
, m
);