2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 by Digital Mars
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
11 /* NOTE: This file has been patched from the original DMD distribution to
12 work with the GDC compiler.
14 Modified by David Friedman, September 2004
23 #include "statement.h"
24 #include "expression.h"
27 #include "staticassert.h"
30 #include "declaration.h"
31 #include "aggregate.h"
37 /******************************** Statement ***************************/
39 Statement::Statement(Loc loc
)
43 // If this is an in{} contract scope statement (skip for determining
44 // inlineStatus of a function body for header content)
49 Statement
*Statement::syntaxCopy()
55 void Statement::print()
57 fprintf(stdmsg
, "%s\n", toChars());
61 char *Statement::toChars()
65 buf
= new OutBuffer();
67 return buf
->toChars();
70 void Statement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
72 buf
->printf("Statement::toCBuffer()");
76 Statement
*Statement::semantic(Scope
*sc
)
81 // Same as semantic(), but do create a new scope
83 Statement
*Statement::semanticScope(Scope
*sc
, Statement
*sbreak
, Statement
*scontinue
)
91 scd
->scontinue
= scontinue
;
97 void Statement::error(const char *format
, ...)
100 va_start(ap
, format
);
101 ::verror(loc
, format
, ap
);
105 int Statement::hasBreak()
107 //printf("Statement::hasBreak()\n");
111 int Statement::hasContinue()
116 // TRUE if statement uses exception handling
118 int Statement::usesEH()
123 /* Only valid after semantic analysis
125 int Statement::blockExit()
127 printf("Statement::blockExit(%p)\n", this);
128 printf("%s\n", toChars());
133 // TRUE if statement may fall off the end without a throw or return
135 int Statement::fallOffEnd()
140 // TRUE if statement 'comes from' somewhere else, like a goto
142 int Statement::comeFrom()
144 //printf("Statement::comeFrom()\n");
148 /****************************************
149 * If this statement has code that needs to run in a finally clause
150 * at the end of the current scope, return that code in the form of
153 * *sentry code executed upon entry to the scope
154 * *sexception code executed upon exit from the scope via exception
155 * *sfinally code executed in finally block
158 void Statement::scopeCode(Scope
*sc
, Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
160 //printf("Statement::scopeCode()\n");
167 /*********************************
168 * Flatten out the scope by presenting the statement
169 * as an array of statements.
170 * Returns NULL if no flattening necessary.
173 Statements
*Statement::flatten(Scope
*sc
)
179 /******************************** ExpStatement ***************************/
181 ExpStatement::ExpStatement(Loc loc
, Expression
*exp
)
187 Statement
*ExpStatement::syntaxCopy()
189 Expression
*e
= exp
? exp
->syntaxCopy() : NULL
;
190 ExpStatement
*es
= new ExpStatement(loc
, e
);
194 void ExpStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
197 exp
->toCBuffer(buf
, hgs
);
199 if (!hgs
->FLinit
.init
)
203 Statement
*ExpStatement::semantic(Scope
*sc
)
207 //printf("ExpStatement::semantic() %s\n", exp->toChars());
208 exp
= exp
->semantic(sc
);
209 exp
= resolveProperties(sc
, exp
);
210 exp
->checkSideEffect(0);
211 exp
= exp
->optimize(0);
212 //exp = exp->optimize(isDeclarationStatement() ? WANTvalue : 0);
217 int ExpStatement::blockExit()
218 { int result
= BEfallthru
;
222 if (exp
->op
== TOKhalt
)
224 if (exp
->op
== TOKassert
)
225 { AssertExp
*a
= (AssertExp
*)exp
;
227 if (a
->e1
->isBool(FALSE
)) // if it's an assert(0)
236 int ExpStatement::fallOffEnd()
240 if (exp
->op
== TOKassert
)
241 { AssertExp
*a
= (AssertExp
*)exp
;
243 if (a
->e1
->isBool(FALSE
)) // if it's an assert(0)
246 else if (exp
->op
== TOKhalt
)
252 /******************************** CompileStatement ***************************/
254 CompileStatement::CompileStatement(Loc loc
, Expression
*exp
)
260 Statement
*CompileStatement::syntaxCopy()
262 Expression
*e
= exp
->syntaxCopy();
263 CompileStatement
*es
= new CompileStatement(loc
, e
);
267 void CompileStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
269 buf
->writestring("mixin(");
270 exp
->toCBuffer(buf
, hgs
);
271 buf
->writestring(");");
272 if (!hgs
->FLinit
.init
)
276 Statement
*CompileStatement::semantic(Scope
*sc
)
278 //printf("CompileStatement::semantic() %s\n", exp->toChars());
279 exp
= exp
->semantic(sc
);
280 exp
= resolveProperties(sc
, exp
);
281 exp
= exp
->optimize(WANTvalue
| WANTinterpret
);
282 if (exp
->op
!= TOKstring
)
283 { error("argument to mixin must be a string, not (%s)", exp
->toChars());
286 StringExp
*se
= (StringExp
*)exp
;
288 Parser
p(sc
->module
, (unsigned char *)se
->string
, se
->len
, 0);
292 Statements
*statements
= new Statements();
293 while (p
.token
.value
!= TOKeof
)
295 Statement
*s
= p
.parseStatement(PSsemi
| PScurlyscope
);
299 Statement
*s
= new CompoundStatement(loc
, statements
);
300 return s
->semantic(sc
);
304 /******************************** DeclarationStatement ***************************/
306 DeclarationStatement::DeclarationStatement(Loc loc
, Dsymbol
*declaration
)
307 : ExpStatement(loc
, new DeclarationExp(loc
, declaration
))
311 DeclarationStatement::DeclarationStatement(Loc loc
, Expression
*exp
)
312 : ExpStatement(loc
, exp
)
316 Statement
*DeclarationStatement::syntaxCopy()
318 DeclarationStatement
*ds
= new DeclarationStatement(loc
, exp
->syntaxCopy());
322 void DeclarationStatement::scopeCode(Scope
*sc
, Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
324 //printf("DeclarationStatement::scopeCode()\n");
333 if (exp
->op
== TOKdeclaration
)
335 DeclarationExp
*de
= (DeclarationExp
*)(exp
);
336 VarDeclaration
*v
= de
->declaration
->isVarDeclaration();
340 e
= v
->callAutoDtor(sc
);
343 //printf("dtor is: "); e->print();
344 *sfinally
= new ExpStatement(loc
, e
);
351 void DeclarationStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
353 exp
->toCBuffer(buf
, hgs
);
357 /******************************** InjectorMainBody ***************************/
359 static Expressions
*getAutoArgs(Loc loc
, Arguments
*arguments
) {
360 Expressions
*args
= new Expressions();
362 Expression
*externals
= new IdentifierExp(loc
, Id::externals
);
363 // Collect all the objects we need for the constructor's arguments
364 for (int i
= 0; i
< arguments
->dim
; i
++) {
365 Argument
*arg
= (Argument
*) arguments
->data
[i
];
366 if (arg
->ident
== Id::args
) {
367 // For 'args', just pass through the string[] passed to main()
368 args
->push(new IdentifierExp(loc
, arg
->ident
));
370 // For everything else, call a getter in the _externals module
371 Expression
*getter
= new DotIdExp(loc
, externals
, arg
->ident
);
379 InjectorMainBody::InjectorMainBody(Loc loc
, ClassDeclaration
*mainClass
)
380 : Statement(loc
), mainClass(mainClass
)
384 Statement
*InjectorMainBody::semantic(Scope
*sc
)
386 // Find the constructor and the main method
387 CtorDeclaration
*ctor
= NULL
;
388 FuncDeclaration
*mainDecl
= NULL
;
389 for (int i
= 0; i
< mainClass
->members
->dim
; i
++) {
392 s
= (Dsymbol
*)mainClass
->members
->data
[i
];
394 CtorDeclaration
*thisCtor
= s
->isCtorDeclaration();
397 error("Multiple constructors for Main class!");
404 FuncDeclaration
*thisMethod
= s
->isFuncDeclaration();
405 if (thisMethod
&& thisMethod
->ident
== Id::main
) {
407 error("Multiple main methods for Main class!");
410 mainDecl
= thisMethod
;
415 if (mainDecl
== NULL
) {
416 error("No main method in Main class!");
420 // Externals externals = new _externals.Externals()
421 TypeIdentifier
*extType
= new TypeIdentifier(loc
, Id::dlt
);
422 extType
->addIdent(Id::_externals
);
423 extType
->addIdent(Id::Externals
);
425 Expression
*newExt
= new NewExp(loc
, NULL
, NULL
, extType
, NULL
);
426 VarDeclaration
*v
= new VarDeclaration(loc
, extType
, Id::externals
,
427 new ExpInitializer(loc
, newExt
));
428 Statement
*assignExt
= new DeclarationStatement(loc
, v
);
429 Expression
*newMain
= new NewExp(loc
, NULL
, NULL
, mainClass
->getType(),
430 ctor
? getAutoArgs(ctor
->loc
, ctor
->arguments
) : NULL
);
432 // Then invoke the main() method inside it
433 // mainObject.main(...)
434 Expression
*mainMethod
= new DotIdExp(mainDecl
->loc
, newMain
, Id::main
);
435 Expression
*mainCall
= new CallExp(mainMethod
->loc
, mainMethod
,
436 getAutoArgs(mainDecl
->loc
,
437 ((TypeFunction
*) mainDecl
->type
)->parameters
));
439 Statement
*s
= new ExpStatement(loc
, mainCall
);
440 Statement
*runMain
= new CompoundStatement(loc
, assignExt
, s
);
442 // catch (SystemExit)
443 Array
*catches
= new Array();
444 Statement
*handler
= new ExpStatement(loc
, new CallExp(loc
,
446 new IdentifierExp(loc
, Id::externals
),
448 new IdentifierExp(loc
, Id::result
)));
449 Catch
*c
= new Catch(loc
, new TypeIdentifier(loc
, Id::SystemExit
), Id::result
, handler
);
451 Statement
*body
= new TryCatchStatement(loc
, runMain
, catches
);
452 return body
->semantic(sc
);
455 /******************************** CompoundStatement ***************************/
457 CompoundStatement::CompoundStatement(Loc loc
, Statements
*s
)
463 CompoundStatement::CompoundStatement(Loc loc
, Statement
*s1
, Statement
*s2
)
466 statements
= new Statements();
467 statements
->reserve(2);
468 statements
->push(s1
);
469 statements
->push(s2
);
472 Statement
*CompoundStatement::syntaxCopy()
474 Statements
*a
= new Statements();
475 a
->setDim(statements
->dim
);
476 for (size_t i
= 0; i
< statements
->dim
; i
++)
477 { Statement
*s
= (Statement
*)statements
->data
[i
];
482 CompoundStatement
*cs
= new CompoundStatement(loc
, a
);
487 Statement
*CompoundStatement::semantic(Scope
*sc
)
490 //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", this, sc);
492 for (size_t i
= 0; i
< statements
->dim
; )
494 s
= (Statement
*) statements
->data
[i
];
496 { Statements
*a
= s
->flatten(sc
);
500 statements
->remove(i
);
501 statements
->insert(i
, a
);
505 statements
->data
[i
] = s
;
509 Statement
*sexception
;
512 s
->scopeCode(sc
, &sentry
, &sexception
, &sfinally
);
515 sentry
= sentry
->semantic(sc
);
516 statements
->data
[i
] = sentry
;
520 if (i
+ 1 == statements
->dim
&& !sfinally
)
523 sexception
= sexception
->semantic(sc
);
525 statements
->push(sexception
);
527 // Assume sexception does not throw
528 statements
->push(sfinally
);
539 * { sexception; throw __o; }
542 Statements
*a
= new Statements();
544 for (int j
= i
+ 1; j
< statements
->dim
; j
++)
546 a
->push(statements
->data
[j
]);
548 body
= new CompoundStatement(0, a
);
549 body
= new ScopeStatement(0, body
);
551 Identifier
*id
= Lexer::uniqueId("__o");
553 Statement
*handler
= new ThrowStatement(0, new IdentifierExp(0, id
));
554 handler
= new CompoundStatement(0, sexception
, handler
);
556 Array
*catches
= new Array();
557 Catch
*ctch
= new Catch(0, NULL
, id
, handler
);
559 s
= new TryCatchStatement(0, body
, catches
);
562 s
= new TryFinallyStatement(0, s
, sfinally
);
564 statements
->setDim(i
+ 1);
571 if (0 && i
+ 1 == statements
->dim
)
573 statements
->push(sfinally
);
580 * s; try { s1; s2; } finally { sfinally; }
583 Statements
*a
= new Statements();
585 for (int j
= i
+ 1; j
< statements
->dim
; j
++)
587 a
->push(statements
->data
[j
]);
589 body
= new CompoundStatement(0, a
);
590 s
= new TryFinallyStatement(0, body
, sfinally
);
592 statements
->setDim(i
+ 1);
601 if (statements
->dim
== 1)
606 Statements
*CompoundStatement::flatten(Scope
*sc
)
611 ReturnStatement
*CompoundStatement::isReturnStatement()
613 ReturnStatement
*rs
= NULL
;
615 for (i
= 0; i
< statements
->dim
; i
++)
618 s
= (Statement
*) statements
->data
[i
];
621 rs
= s
->isReturnStatement();
629 void CompoundStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
632 for (i
= 0; i
< statements
->dim
; i
++)
635 s
= (Statement
*) statements
->data
[i
];
637 s
->toCBuffer(buf
, hgs
);
641 int CompoundStatement::usesEH()
643 for (int i
= 0; i
< statements
->dim
; i
++)
646 s
= (Statement
*) statements
->data
[i
];
647 if (s
&& s
->usesEH())
653 int CompoundStatement::blockExit()
655 //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim);
656 int result
= BEfallthru
;
657 for (size_t i
= 0; i
< statements
->dim
; i
++)
658 { Statement
*s
= (Statement
*) statements
->data
[i
];
661 //printf("result = x%x\n", result);
662 //printf("%s\n", s->toChars());
663 if (!(result
& BEfallthru
) && !s
->comeFrom())
665 if (global
.params
.warnings
)
666 { fprintf(stdmsg
, "warning - ");
667 s
->error("statement is not reachable");
671 result
&= ~BEfallthru
;
672 result
|= s
->blockExit();
678 int CompoundStatement::fallOffEnd()
679 { int falloff
= TRUE
;
681 //printf("CompoundStatement::fallOffEnd()\n");
682 for (int i
= 0; i
< statements
->dim
; i
++)
683 { Statement
*s
= (Statement
*)statements
->data
[i
];
689 if (!falloff
&& global
.params
.warnings
&& !s
->comeFrom())
691 fprintf(stdmsg
, "warning - ");
692 s
->error("statement is not reachable");
695 falloff
= s
->fallOffEnd();
700 int CompoundStatement::comeFrom()
701 { int comefrom
= FALSE
;
703 //printf("CompoundStatement::comeFrom()\n");
704 for (int i
= 0; i
< statements
->dim
; i
++)
705 { Statement
*s
= (Statement
*)statements
->data
[i
];
710 comefrom
|= s
->comeFrom();
716 /**************************** UnrolledLoopStatement ***************************/
718 UnrolledLoopStatement::UnrolledLoopStatement(Loc loc
, Statements
*s
)
724 Statement
*UnrolledLoopStatement::syntaxCopy()
726 Statements
*a
= new Statements();
727 a
->setDim(statements
->dim
);
728 for (size_t i
= 0; i
< statements
->dim
; i
++)
729 { Statement
*s
= (Statement
*)statements
->data
[i
];
734 UnrolledLoopStatement
*cs
= new UnrolledLoopStatement(loc
, a
);
739 Statement
*UnrolledLoopStatement::semantic(Scope
*sc
)
741 //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc);
744 Scope
*scd
= sc
->push();
746 scd
->scontinue
= this;
748 for (size_t i
= 0; i
< statements
->dim
; i
++)
750 Statement
*s
= (Statement
*) statements
->data
[i
];
753 s
= s
->semantic(scd
);
754 statements
->data
[i
] = s
;
763 void UnrolledLoopStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
765 buf
->writestring("unrolled {");
768 for (size_t i
= 0; i
< statements
->dim
; i
++)
771 s
= (Statement
*) statements
->data
[i
];
773 s
->toCBuffer(buf
, hgs
);
780 int UnrolledLoopStatement::hasBreak()
785 int UnrolledLoopStatement::hasContinue()
790 int UnrolledLoopStatement::usesEH()
792 for (size_t i
= 0; i
< statements
->dim
; i
++)
793 { Statement
*s
= (Statement
*) statements
->data
[i
];
794 if (s
&& s
->usesEH())
800 int UnrolledLoopStatement::blockExit()
802 int result
= BEfallthru
;
803 for (size_t i
= 0; i
< statements
->dim
; i
++)
804 { Statement
*s
= (Statement
*) statements
->data
[i
];
807 int r
= s
->blockExit();
808 result
|= r
& ~(BEbreak
| BEcontinue
);
814 int UnrolledLoopStatement::fallOffEnd()
816 //printf("UnrolledLoopStatement::fallOffEnd()\n");
817 for (size_t i
= 0; i
< statements
->dim
; i
++)
818 { Statement
*s
= (Statement
*)statements
->data
[i
];
826 int UnrolledLoopStatement::comeFrom()
827 { int comefrom
= FALSE
;
829 //printf("UnrolledLoopStatement::comeFrom()\n");
830 for (size_t i
= 0; i
< statements
->dim
; i
++)
831 { Statement
*s
= (Statement
*)statements
->data
[i
];
836 comefrom
|= s
->comeFrom();
842 /******************************** ScopeStatement ***************************/
844 ScopeStatement::ScopeStatement(Loc loc
, Statement
*s
)
850 Statement
*ScopeStatement::syntaxCopy()
854 s
= statement
? statement
->syntaxCopy() : NULL
;
855 s
= new ScopeStatement(loc
, s
);
860 Statement
*ScopeStatement::semantic(Scope
*sc
)
863 //printf("ScopeStatement::semantic(sc = %p)\n", sc);
867 sym
= new ScopeDsymbol();
868 sym
->parent
= sc
->scopesym
;
871 a
= statement
->flatten(sc
);
874 statement
= new CompoundStatement(loc
, a
);
877 statement
= statement
->semantic(sc
);
881 Statement
*sexception
;
884 statement
->scopeCode(sc
, &sentry
, &sexception
, &sfinally
);
887 //printf("adding sfinally\n");
888 statement
= new CompoundStatement(loc
, statement
, sfinally
);
897 int ScopeStatement::hasBreak()
899 //printf("ScopeStatement::hasBreak() %s\n", toChars());
900 return statement
? statement
->hasBreak() : FALSE
;
903 int ScopeStatement::hasContinue()
905 return statement
? statement
->hasContinue() : FALSE
;
908 int ScopeStatement::usesEH()
910 return statement
? statement
->usesEH() : FALSE
;
913 int ScopeStatement::blockExit()
915 //printf("ScopeStatement::blockExit(%p)\n", statement);
916 return statement
? statement
->blockExit() : BEfallthru
;
919 int ScopeStatement::fallOffEnd()
921 return statement
? statement
->fallOffEnd() : TRUE
;
924 int ScopeStatement::comeFrom()
926 //printf("ScopeStatement::comeFrom()\n");
927 return statement
? statement
->comeFrom() : FALSE
;
930 void ScopeStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
936 statement
->toCBuffer(buf
, hgs
);
942 /******************************** WhileStatement ***************************/
944 WhileStatement::WhileStatement(Loc loc
, Expression
*c
, Statement
*b
)
951 Statement
*WhileStatement::syntaxCopy()
953 WhileStatement
*s
= new WhileStatement(loc
, condition
->syntaxCopy(), body
? body
->syntaxCopy() : NULL
);
958 Statement
*WhileStatement::semantic(Scope
*sc
)
961 if (condition
->op
== TOKmatch
)
963 /* Rewrite while (condition) body as:
967 * while ((_match = _match.opNext), _match);
970 Expression
*ew
= new IdentifierExp(0, Id::_match
);
971 ew
= new DotIdExp(0, ew
, Id::next
);
972 ew
= new AssignExp(0, new IdentifierExp(0, Id::_match
), ew
);
973 ////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0));
974 Expression
*ev
= new IdentifierExp(0, Id::_match
);
975 //ev = new CastExp(0, ev, Type::tvoidptr);
976 ew
= new CommaExp(0, ew
, ev
);
977 Statement
*sw
= new DoStatement(loc
, body
, ew
);
978 Statement
*si
= new IfStatement(loc
, condition
, sw
, NULL
);
979 return si
->semantic(sc
);
983 condition
= condition
->semantic(sc
);
984 condition
= resolveProperties(sc
, condition
);
985 condition
= condition
->optimize(WANTvalue
);
986 condition
= condition
->checkToBoolean();
990 Scope
*scd
= sc
->push();
992 scd
->scontinue
= this;
994 body
= body
->semantic(scd
);
1002 int WhileStatement::hasBreak()
1007 int WhileStatement::hasContinue()
1012 int WhileStatement::usesEH()
1014 return body
? body
->usesEH() : 0;
1017 int WhileStatement::blockExit()
1019 //printf("WhileStatement::blockExit(%p)\n", this);
1021 int result
= BEnone
;
1022 if (condition
->canThrow())
1025 { result
|= body
->blockExit();
1026 if (result
& BEbreak
)
1027 result
|= BEfallthru
;
1028 result
&= ~(BEbreak
| BEcontinue
);
1031 result
|= BEfallthru
;
1035 int WhileStatement::fallOffEnd()
1042 int WhileStatement::comeFrom()
1045 return body
->comeFrom();
1049 void WhileStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1051 buf
->writestring("while (");
1052 condition
->toCBuffer(buf
, hgs
);
1053 buf
->writebyte(')');
1056 body
->toCBuffer(buf
, hgs
);
1059 /******************************** DoStatement ***************************/
1061 DoStatement::DoStatement(Loc loc
, Statement
*b
, Expression
*c
)
1068 Statement
*DoStatement::syntaxCopy()
1070 DoStatement
*s
= new DoStatement(loc
, body
? body
->syntaxCopy() : NULL
, condition
->syntaxCopy());
1075 Statement
*DoStatement::semantic(Scope
*sc
)
1079 body
= body
->semanticScope(sc
, this, this);
1081 condition
= condition
->semantic(sc
);
1082 condition
= resolveProperties(sc
, condition
);
1083 condition
= condition
->optimize(WANTvalue
);
1085 condition
= condition
->checkToBoolean();
1090 int DoStatement::hasBreak()
1095 int DoStatement::hasContinue()
1100 int DoStatement::usesEH()
1102 return body
? body
->usesEH() : 0;
1105 int DoStatement::blockExit()
1109 { result
= body
->blockExit();
1110 if (result
& BEbreak
)
1112 if (result
== BEbreak
)
1114 result
|= BEfallthru
;
1116 if (result
& BEcontinue
)
1117 result
|= BEfallthru
;
1118 result
&= ~(BEbreak
| BEcontinue
);
1121 result
= BEfallthru
;
1122 if (result
& BEfallthru
&& condition
->canThrow())
1127 int DoStatement::fallOffEnd()
1134 int DoStatement::comeFrom()
1137 return body
->comeFrom();
1141 void DoStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1143 buf
->writestring("do");
1146 body
->toCBuffer(buf
, hgs
);
1147 buf
->writestring("while (");
1148 condition
->toCBuffer(buf
, hgs
);
1149 buf
->writebyte(')');
1152 /******************************** ForStatement ***************************/
1154 ForStatement::ForStatement(Loc loc
, Statement
*init
, Expression
*condition
, Expression
*increment
, Statement
*body
)
1158 this->condition
= condition
;
1159 this->increment
= increment
;
1163 Statement
*ForStatement::syntaxCopy()
1165 Statement
*i
= NULL
;
1167 i
= init
->syntaxCopy();
1168 Expression
*c
= NULL
;
1170 c
= condition
->syntaxCopy();
1171 Expression
*inc
= NULL
;
1173 inc
= increment
->syntaxCopy();
1174 ForStatement
*s
= new ForStatement(loc
, i
, c
, inc
, body
->syntaxCopy());
1178 Statement
*ForStatement::semantic(Scope
*sc
)
1180 ScopeDsymbol
*sym
= new ScopeDsymbol();
1181 sym
->parent
= sc
->scopesym
;
1184 init
= init
->semantic(sc
);
1188 condition
= condition
->semantic(sc
);
1189 condition
= resolveProperties(sc
, condition
);
1190 condition
= condition
->optimize(WANTvalue
);
1191 condition
= condition
->checkToBoolean();
1194 increment
= increment
->semantic(sc
);
1197 sc
->scontinue
= this;
1198 body
= body
->semantic(sc
);
1205 void ForStatement::scopeCode(Scope
*sc
, Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
1207 //printf("ForStatement::scopeCode()\n");
1210 init
->scopeCode(sc
, sentry
, sexception
, sfinally
);
1212 Statement::scopeCode(sc
, sentry
, sexception
, sfinally
);
1215 int ForStatement::hasBreak()
1217 //printf("ForStatement::hasBreak()\n");
1221 int ForStatement::hasContinue()
1226 int ForStatement::usesEH()
1228 return (init
&& init
->usesEH()) || body
->usesEH();
1231 int ForStatement::blockExit()
1232 { int result
= BEfallthru
;
1235 { result
= init
->blockExit();
1236 if (!(result
& BEfallthru
))
1240 { if (condition
->canThrow())
1244 result
&= ~BEfallthru
; // the body must do the exiting
1246 { int r
= body
->blockExit();
1248 result
|= BEfallthru
;
1249 result
|= r
& ~(BEbreak
| BEcontinue
);
1251 if (increment
&& increment
->canThrow())
1256 int ForStatement::fallOffEnd()
1263 int ForStatement::comeFrom()
1265 //printf("ForStatement::comeFrom()\n");
1267 { int result
= body
->comeFrom();
1268 //printf("result = %d\n", result);
1274 void ForStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1276 buf
->writestring("for (");
1280 hgs
->FLinit
.decl
= 0;
1281 init
->toCBuffer(buf
, hgs
);
1282 if (hgs
->FLinit
.decl
> 0)
1283 buf
->writebyte(';');
1284 hgs
->FLinit
.decl
= 0;
1288 buf
->writebyte(';');
1290 { buf
->writebyte(' ');
1291 condition
->toCBuffer(buf
, hgs
);
1293 buf
->writebyte(';');
1295 { buf
->writebyte(' ');
1296 increment
->toCBuffer(buf
, hgs
);
1298 buf
->writebyte(')');
1300 buf
->writebyte('{');
1302 body
->toCBuffer(buf
, hgs
);
1303 buf
->writebyte('}');
1307 /******************************** ForeachStatement ***************************/
1309 ForeachStatement::ForeachStatement(Loc loc
, enum TOK op
, Arguments
*arguments
,
1310 Expression
*aggr
, Statement
*body
)
1314 this->arguments
= arguments
;
1324 Statement
*ForeachStatement::syntaxCopy()
1326 Arguments
*args
= Argument::arraySyntaxCopy(arguments
);
1327 Expression
*exp
= aggr
->syntaxCopy();
1328 ForeachStatement
*s
= new ForeachStatement(loc
, op
, args
, exp
,
1329 body
? body
->syntaxCopy() : NULL
);
1333 Statement
*ForeachStatement::semantic(Scope
*sc
)
1335 //printf("ForeachStatement::semantic() %p\n", this);
1337 Statement
*s
= this;
1338 int dim
= arguments
->dim
;
1340 TypeAArray
*taa
= NULL
;
1347 func
= func
->fes
->func
;
1349 aggr
= aggr
->semantic(sc
);
1350 aggr
= resolveProperties(sc
, aggr
);
1351 aggr
= aggr
->optimize(WANTvalue
);
1354 error("invalid foreach aggregate %s", aggr
->toChars());
1358 inferApplyArgTypes(op
, arguments
, aggr
);
1360 /* Check for inference errors
1362 if (dim
!= arguments
->dim
)
1364 //printf("dim = %d, arguments->dim = %d\n", dim, arguments->dim);
1365 error("cannot uniquely infer foreach argument types");
1369 Type
*tab
= aggr
->type
->toBasetype();
1371 if (tab
->ty
== Ttuple
) // don't generate new scope for tuple loops
1373 if (dim
< 1 || dim
> 2)
1375 error("only one (value) or two (key,value) arguments for tuple foreach");
1379 TypeTuple
*tuple
= (TypeTuple
*)tab
;
1380 Statements
*statements
= new Statements();
1381 //printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars());
1383 TupleExp
*te
= NULL
;
1384 if (aggr
->op
== TOKtuple
) // expression tuple
1385 { te
= (TupleExp
*)aggr
;
1388 else if (aggr
->op
== TOKtype
) // type tuple
1390 n
= Argument::dim(tuple
->arguments
);
1394 for (size_t j
= 0; j
< n
; j
++)
1395 { size_t k
= (op
== TOKforeach
) ? j
: n
- 1 - j
;
1399 e
= (Expression
*)te
->exps
->data
[k
];
1401 t
= Argument::getNth(tuple
->arguments
, k
)->type
;
1402 Argument
*arg
= (Argument
*)arguments
->data
[0];
1403 Statements
*st
= new Statements();
1407 if (arg
->storageClass
& (STCout
| STCref
| STClazy
))
1408 error("no storage class for key %s", arg
->ident
->toChars());
1409 TY keyty
= arg
->type
->ty
;
1410 if ((keyty
!= Tint32
&& keyty
!= Tuns32
) &&
1411 (! global
.params
.isX86_64
||
1412 (keyty
!= Tint64
&& keyty
!= Tuns64
))
1415 error("foreach: key type must be int or uint, not %s", arg
->type
->toChars());
1417 Initializer
*ie
= new ExpInitializer(0, new IntegerExp(k
));
1418 VarDeclaration
*var
= new VarDeclaration(loc
, arg
->type
, arg
->ident
, ie
);
1419 var
->storage_class
|= STCmanifest
;
1420 DeclarationExp
*de
= new DeclarationExp(loc
, var
);
1421 st
->push(new ExpStatement(loc
, de
));
1422 arg
= (Argument
*)arguments
->data
[1]; // value
1425 if (arg
->storageClass
& (STCout
| STCref
| STClazy
))
1426 error("no storage class for value %s", arg
->ident
->toChars());
1429 { Type
*tb
= e
->type
->toBasetype();
1430 if ((tb
->ty
== Tfunction
|| tb
->ty
== Tsarray
) && e
->op
== TOKvar
)
1431 { VarExp
*ve
= (VarExp
*)e
;
1432 var
= new AliasDeclaration(loc
, arg
->ident
, ve
->var
);
1436 arg
->type
= e
->type
;
1437 Initializer
*ie
= new ExpInitializer(0, e
);
1438 VarDeclaration
*v
= new VarDeclaration(loc
, arg
->type
, arg
->ident
, ie
);
1440 v
->storage_class
|= STCconst
;
1446 var
= new AliasDeclaration(loc
, arg
->ident
, t
);
1448 DeclarationExp
*de
= new DeclarationExp(loc
, var
);
1449 st
->push(new ExpStatement(loc
, de
));
1451 st
->push(body
->syntaxCopy());
1452 s
= new CompoundStatement(loc
, st
);
1453 s
= new ScopeStatement(loc
, s
);
1454 statements
->push(s
);
1457 s
= new UnrolledLoopStatement(loc
, statements
);
1458 s
= s
->semantic(sc
);
1462 for (i
= 0; i
< dim
; i
++)
1463 { Argument
*arg
= (Argument
*)arguments
->data
[i
];
1466 error("cannot infer type for %s", arg
->ident
->toChars());
1471 sym
= new ScopeDsymbol();
1472 sym
->parent
= sc
->scopesym
;
1481 if (dim
< 1 || dim
> 2)
1483 error("only one or two arguments for array foreach");
1487 /* Look for special case of parsing char types out of char type
1490 tn
= tab
->nextOf()->toBasetype();
1491 if (tn
->ty
== Tchar
|| tn
->ty
== Twchar
|| tn
->ty
== Tdchar
)
1494 i
= (dim
== 1) ? 0 : 1; // index of value
1495 arg
= (Argument
*)arguments
->data
[i
];
1496 arg
->type
= arg
->type
->semantic(loc
, sc
);
1497 tnv
= arg
->type
->toBasetype();
1498 if (tnv
->ty
!= tn
->ty
&&
1499 (tnv
->ty
== Tchar
|| tnv
->ty
== Twchar
|| tnv
->ty
== Tdchar
))
1501 if (arg
->storageClass
& STCref
)
1502 error("foreach: value of UTF conversion cannot be ref");
1504 { arg
= (Argument
*)arguments
->data
[0];
1505 if (arg
->storageClass
& STCref
)
1506 error("foreach: key cannot be ref");
1512 for (i
= 0; i
< dim
; i
++)
1514 Argument
*arg
= (Argument
*)arguments
->data
[i
];
1515 VarDeclaration
*var
;
1517 var
= new VarDeclaration(loc
, arg
->type
, arg
->ident
, NULL
);
1518 var
->storage_class
|= STCforeach
;
1519 var
->storage_class
|= arg
->storageClass
& (STCin
| STCout
| STCref
| STCconst
| STCinvariant
);
1520 if (dim
== 2 && i
== 0)
1522 //var->storage_class |= STCfinal;
1525 { //if (!(arg->storageClass & STCref))
1526 //var->storage_class |= STCfinal;
1530 DeclarationExp
*de
= new DeclarationExp(loc
, var
);
1534 if (!sc
->insert(var
))
1535 error("%s already defined", var
->ident
->toChars());
1540 sc
->scontinue
= this;
1541 body
= body
->semantic(sc
);
1543 if (tab
->nextOf()->implicitConvTo(value
->type
) < MATCHconst
)
1545 if (aggr
->op
== TOKstring
)
1546 aggr
= aggr
->implicitCastTo(sc
, value
->type
->arrayOf());
1548 error("foreach: %s is not an array of %s",
1549 tab
->toChars(), value
->type
->toChars());
1553 ((key
->type
->ty
!= Tint32
&& key
->type
->ty
!= Tuns32
) &&
1554 (! global
.params
.isX86_64
||
1555 (key
->type
->ty
!= Tint64
&& key
->type
->ty
!= Tuns64
))
1559 error("foreach: key type must be int or uint, not %s", key
->type
->toChars());
1562 if (key
&& key
->storage_class
& (STCout
| STCref
))
1563 error("foreach: key cannot be out or ref");
1567 taa
= (TypeAArray
*)tab
;
1568 if (dim
< 1 || dim
> 2)
1570 error("only one or two arguments for associative array foreach");
1573 if (op
== TOKforeach_reverse
)
1575 error("no reverse iteration on associative arrays");
1583 { FuncDeclaration
*fdapply
;
1587 FuncLiteralDeclaration
*fld
;
1594 tret
= func
->type
->nextOf();
1596 // Need a variable to hold value from any return statements in body.
1597 if (!sc
->func
->vresult
&& tret
&& tret
!= Type::tvoid
)
1598 { VarDeclaration
*v
;
1600 v
= new VarDeclaration(loc
, tret
, Id::result
, NULL
);
1605 v
->parent
= sc
->func
;
1606 sc
->func
->vresult
= v
;
1609 /* Turn body into the function literal:
1610 * int delegate(ref T arg) { body }
1612 args
= new Arguments();
1613 for (i
= 0; i
< dim
; i
++)
1614 { Argument
*arg
= (Argument
*)arguments
->data
[i
];
1616 arg
->type
= arg
->type
->semantic(loc
, sc
);
1617 if (arg
->storageClass
& STCref
)
1620 { // Make a copy of the ref argument so it isn't
1625 id
= Lexer::uniqueId("__applyArg", i
);
1627 ie
= new ExpInitializer(0, new IdentifierExp(0, id
));
1628 v
= new VarDeclaration(0, arg
->type
, arg
->ident
, ie
);
1629 s
= new DeclarationStatement(0, v
);
1630 body
= new CompoundStatement(loc
, s
, body
);
1632 a
= new Argument(STCref
, arg
->type
, id
, NULL
);
1635 t
= new TypeFunction(args
, Type::tint32
, 0, LINKd
);
1636 fld
= new FuncLiteralDeclaration(loc
, 0, t
, TOKdelegate
, this);
1638 flde
= new FuncExp(loc
, fld
);
1639 flde
= flde
->semantic(sc
);
1640 fld
->tookAddressOf
= 0;
1642 // Resolve any forward referenced goto's
1643 for (int i
= 0; i
< gotos
.dim
; i
++)
1644 { CompoundStatement
*cs
= (CompoundStatement
*)gotos
.data
[i
];
1645 GotoStatement
*gs
= (GotoStatement
*)cs
->statements
->data
[0];
1647 if (!gs
->label
->statement
)
1648 { // 'Promote' it to this scope, and replace with a return
1650 s
= new ReturnStatement(0, new IntegerExp(cases
.dim
+ 1));
1651 cs
->statements
->data
[0] = (void *)s
;
1655 if (tab
->ty
== Taarray
)
1658 Argument
*arg
= (Argument
*)arguments
->data
[0];
1661 if (arg
->storageClass
& STCref
)
1662 error("foreach: index cannot be ref");
1663 if (!arg
->type
->equals(taa
->index
))
1664 error("foreach: index must be type %s, not %s", taa
->index
->toChars(), arg
->type
->toChars());
1665 arg
= (Argument
*)arguments
->data
[1];
1667 if (!arg
->type
->equals(taa
->nextOf()))
1668 error("foreach: value must be type %s, not %s", taa
->nextOf()->toChars(), arg
->type
->toChars());
1671 * _aaApply(aggr, keysize, flde)
1674 fdapply
= FuncDeclaration::genCfunc(Type::tint32
, "_aaApply2",
1675 Type::tvoid
->arrayOf(), Type::tsize_t
, flde
->type
); // flde->type is not generic
1677 fdapply
= FuncDeclaration::genCfunc(Type::tint32
, "_aaApply",
1678 Type::tvoid
->arrayOf(), Type::tsize_t
, flde
->type
); // flde->type is not generic);
1679 ec
= new VarExp(0, fdapply
);
1680 Expressions
*exps
= new Expressions();
1682 size_t keysize
= taa
->index
->size();
1683 keysize
= (keysize
+ (PTRSIZE
-1)) & ~(PTRSIZE
-1);
1684 exps
->push(new IntegerExp(0, keysize
, Type::tsize_t
));
1686 e
= new CallExp(loc
, ec
, exps
);
1687 e
->type
= Type::tint32
; // don't run semantic() on e
1689 else if (tab
->ty
== Tarray
|| tab
->ty
== Tsarray
)
1692 * _aApply(aggr, flde)
1694 static char fntab
[9][3] =
1699 char fdname
[7+1+2+ sizeof(dim
)*3 + 1];
1704 case Tchar
: flag
= 0; break;
1705 case Twchar
: flag
= 3; break;
1706 case Tdchar
: flag
= 6; break;
1711 case Tchar
: flag
+= 0; break;
1712 case Twchar
: flag
+= 1; break;
1713 case Tdchar
: flag
+= 2; break;
1716 const char *r
= (op
== TOKforeach_reverse
) ? "R" : "";
1717 int j
= sprintf(fdname
, "_aApply%s%.*s%d", r
, 2, fntab
[flag
], dim
);
1718 assert(j
< sizeof(fdname
));
1719 fdapply
= FuncDeclaration::genCfunc(Type::tint32
, fdname
,
1720 Type::tvoid
->arrayOf(), flde
->type
); // flde->type is not generic
1722 ec
= new VarExp(0, fdapply
);
1723 Expressions
*exps
= new Expressions();
1724 if (tab
->ty
== Tsarray
)
1725 aggr
= aggr
->castTo(sc
, tn
->arrayOf());
1728 e
= new CallExp(loc
, ec
, exps
);
1729 e
->type
= Type::tint32
; // don't run semantic() on e
1731 else if (tab
->ty
== Tdelegate
)
1736 Expressions
*exps
= new Expressions();
1738 e
= new CallExp(loc
, aggr
, exps
);
1739 e
= e
->semantic(sc
);
1740 if (e
->type
!= Type::tint32
)
1741 error("opApply() function for %s must return an int", tab
->toChars());
1748 ec
= new DotIdExp(loc
, aggr
,
1749 (op
== TOKforeach_reverse
) ? Id::applyReverse
1751 Expressions
*exps
= new Expressions();
1753 e
= new CallExp(loc
, ec
, exps
);
1754 e
= e
->semantic(sc
);
1755 if (e
->type
!= Type::tint32
)
1756 error("opApply() function for %s must return an int", tab
->toChars());
1760 // Easy case, a clean exit from the loop
1761 s
= new ExpStatement(loc
, e
);
1763 { // Construct a switch statement around the return value
1764 // of the apply function.
1765 Statements
*a
= new Statements();
1767 // default: break; takes care of cases 0 and 1
1768 s
= new BreakStatement(0, NULL
);
1769 s
= new DefaultStatement(0, s
);
1773 for (int i
= 0; i
< cases
.dim
; i
++)
1775 s
= (Statement
*)cases
.data
[i
];
1776 s
= new CaseStatement(0, new IntegerExp(i
+ 2), s
);
1780 s
= new CompoundStatement(loc
, a
);
1781 s
= new SwitchStatement(loc
, e
, s
);
1782 s
= s
->semantic(sc
);
1788 error("foreach: %s is not an aggregate type", aggr
->type
->toChars());
1796 int ForeachStatement::hasBreak()
1801 int ForeachStatement::hasContinue()
1806 int ForeachStatement::usesEH()
1808 return body
->usesEH();
1811 int ForeachStatement::blockExit()
1812 { int result
= BEfallthru
;
1814 if (aggr
->canThrow())
1819 result
|= body
->blockExit() & ~(BEbreak
| BEcontinue
);
1824 int ForeachStatement::fallOffEnd()
1831 int ForeachStatement::comeFrom()
1834 return body
->comeFrom();
1838 void ForeachStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1840 buf
->writestring(Token::toChars(op
));
1841 buf
->writestring(" (");
1842 for (int i
= 0; i
< arguments
->dim
; i
++)
1844 Argument
*a
= (Argument
*)arguments
->data
[i
];
1846 buf
->writestring(", ");
1847 if (a
->storageClass
& STCref
)
1848 buf
->writestring((global
.params
.Dversion
== 1)
1849 ? (char*)"inout " : (char*)"ref ");
1851 a
->type
->toCBuffer(buf
, a
->ident
, hgs
);
1853 buf
->writestring(a
->ident
->toChars());
1855 buf
->writestring("; ");
1856 aggr
->toCBuffer(buf
, hgs
);
1857 buf
->writebyte(')');
1859 buf
->writebyte('{');
1862 body
->toCBuffer(buf
, hgs
);
1863 buf
->writebyte('}');
1867 /**************************** ForeachRangeStatement ***************************/
1869 ForeachRangeStatement::ForeachRangeStatement(Loc loc
, enum TOK op
, Argument
*arg
,
1870 Expression
*lwr
, Expression
*upr
, Statement
*body
)
1882 Statement
*ForeachRangeStatement::syntaxCopy()
1884 ForeachRangeStatement
*s
= new ForeachRangeStatement(loc
, op
,
1888 body
? body
->syntaxCopy() : NULL
);
1892 Statement
*ForeachRangeStatement::semantic(Scope
*sc
)
1894 //printf("ForeachRangeStatement::semantic() %p\n", this);
1896 Statement
*s
= this;
1898 lwr
= lwr
->semantic(sc
);
1899 lwr
= resolveProperties(sc
, lwr
);
1900 lwr
= lwr
->optimize(WANTvalue
);
1903 error("invalid range lower bound %s", lwr
->toChars());
1907 upr
= upr
->semantic(sc
);
1908 upr
= resolveProperties(sc
, upr
);
1909 upr
= upr
->optimize(WANTvalue
);
1912 error("invalid range upper bound %s", upr
->toChars());
1918 lwr
= lwr
->implicitCastTo(sc
, arg
->type
);
1919 upr
= upr
->implicitCastTo(sc
, arg
->type
);
1923 /* Must infer types from lwr and upr
1925 AddExp
ea(loc
, lwr
, upr
);
1927 arg
->type
= ea
.type
;
1931 if (!arg
->type
->isscalar())
1932 error("%s is not a scalar type", arg
->type
->toChars());
1934 sym
= new ScopeDsymbol();
1935 sym
->parent
= sc
->scopesym
;
1940 key
= new VarDeclaration(loc
, arg
->type
, arg
->ident
, NULL
);
1941 DeclarationExp
*de
= new DeclarationExp(loc
, key
);
1944 if (key
->storage_class
)
1945 error("foreach range: key cannot have storage class");
1948 sc
->scontinue
= this;
1949 body
= body
->semantic(sc
);
1956 int ForeachRangeStatement::hasBreak()
1961 int ForeachRangeStatement::hasContinue()
1966 int ForeachRangeStatement::usesEH()
1968 return body
->usesEH();
1971 int ForeachRangeStatement::blockExit()
1972 { int result
= BEfallthru
;
1974 if (lwr
&& lwr
->canThrow())
1976 else if (upr
&& upr
->canThrow())
1981 result
|= body
->blockExit() & ~(BEbreak
| BEcontinue
);
1986 int ForeachRangeStatement::fallOffEnd()
1993 int ForeachRangeStatement::comeFrom()
1996 return body
->comeFrom();
2000 void ForeachRangeStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2002 buf
->writestring(Token::toChars(op
));
2003 buf
->writestring(" (");
2006 arg
->type
->toCBuffer(buf
, arg
->ident
, hgs
);
2008 buf
->writestring(arg
->ident
->toChars());
2010 buf
->writestring("; ");
2011 lwr
->toCBuffer(buf
, hgs
);
2012 buf
->writestring(" .. ");
2013 upr
->toCBuffer(buf
, hgs
);
2014 buf
->writebyte(')');
2016 buf
->writebyte('{');
2019 body
->toCBuffer(buf
, hgs
);
2020 buf
->writebyte('}');
2024 /******************************** IfStatement ***************************/
2026 IfStatement::IfStatement(Loc loc
, Argument
*arg
, Expression
*condition
, Statement
*ifbody
, Statement
*elsebody
)
2030 this->condition
= condition
;
2031 this->ifbody
= ifbody
;
2032 this->elsebody
= elsebody
;
2036 Statement
*IfStatement::syntaxCopy()
2038 Statement
*i
= NULL
;
2040 i
= ifbody
->syntaxCopy();
2042 Statement
*e
= NULL
;
2044 e
= elsebody
->syntaxCopy();
2046 Argument
*a
= arg
? arg
->syntaxCopy() : NULL
;
2047 IfStatement
*s
= new IfStatement(loc
, a
, condition
->syntaxCopy(), i
, e
);
2051 Statement
*IfStatement::semantic(Scope
*sc
)
2053 condition
= condition
->semantic(sc
);
2054 condition
= resolveProperties(sc
, condition
);
2055 condition
= condition
->checkToBoolean();
2057 // If we can short-circuit evaluate the if statement, don't do the
2058 // semantic analysis of the skipped code.
2059 // This feature allows a limited form of conditional compilation.
2060 condition
= condition
->optimize(WANTflags
);
2062 // Evaluate at runtime
2063 unsigned cs0
= sc
->callSuper
;
2068 { /* Declare arg, which we will set to be the
2069 * result of condition.
2071 ScopeDsymbol
*sym
= new ScopeDsymbol();
2072 sym
->parent
= sc
->scopesym
;
2073 scd
= sc
->push(sym
);
2075 Type
*t
= arg
->type
? arg
->type
: condition
->type
;
2076 match
= new VarDeclaration(loc
, t
->maybe(true), arg
->ident
, NULL
);
2078 match
->semantic(scd
);
2079 if (!scd
->insert(match
))
2081 match
->parent
= sc
->func
;
2086 VarExp
*v
= new VarExp(0, match
);
2087 condition
= new AssignExp(loc
, v
, condition
);
2088 condition
= condition
->semantic(scd
);
2090 if (match
&& match
->type
->ty
== Tmaybe
)
2092 // Matched object cannot be null in the then block
2093 // (and isn't in scope in the else)
2094 match
->type
= match
->type
->nextOf();
2099 ifbody
= ifbody
->semantic(scd
);
2102 cs1
= sc
->callSuper
;
2103 sc
->callSuper
= cs0
;
2105 elsebody
= elsebody
->semanticScope(sc
, NULL
, NULL
);
2106 sc
->mergeCallSuper(loc
, cs1
);
2111 int IfStatement::usesEH()
2113 return (ifbody
&& ifbody
->usesEH()) || (elsebody
&& elsebody
->usesEH());
2116 int IfStatement::blockExit()
2118 //printf("IfStatement::blockExit(%p)\n", this);
2120 int result
= BEnone
;
2121 if (condition
->canThrow())
2124 result
|= ifbody
->blockExit();
2126 result
|= BEfallthru
;
2128 result
|= elsebody
->blockExit();
2130 result
|= BEfallthru
;
2131 //printf("IfStatement::blockExit(%p) = x%x\n", this, result);
2135 int IfStatement::fallOffEnd()
2137 if (!ifbody
|| ifbody
->fallOffEnd() ||
2138 !elsebody
|| elsebody
->fallOffEnd())
2144 void IfStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2146 buf
->writestring("if (");
2150 arg
->type
->toCBuffer(buf
, arg
->ident
, hgs
);
2152 buf
->writestring(arg
->ident
->toChars());
2153 buf
->writebyte(';');
2155 condition
->toCBuffer(buf
, hgs
);
2156 buf
->writebyte(')');
2158 ifbody
->toCBuffer(buf
, hgs
);
2160 { buf
->writestring("else");
2162 elsebody
->toCBuffer(buf
, hgs
);
2166 /******************************** ConditionalStatement ***************************/
2168 ConditionalStatement::ConditionalStatement(Loc loc
, Condition
*condition
, Statement
*ifbody
, Statement
*elsebody
)
2171 this->condition
= condition
;
2172 this->ifbody
= ifbody
;
2173 this->elsebody
= elsebody
;
2176 Statement
*ConditionalStatement::syntaxCopy()
2178 Statement
*e
= NULL
;
2180 e
= elsebody
->syntaxCopy();
2181 ConditionalStatement
*s
= new ConditionalStatement(loc
,
2182 condition
->syntaxCopy(), ifbody
->syntaxCopy(), e
);
2186 Statement
*ConditionalStatement::semantic(Scope
*sc
)
2188 //printf("ConditionalStatement::semantic()\n");
2190 // If we can short-circuit evaluate the if statement, don't do the
2191 // semantic analysis of the skipped code.
2192 // This feature allows a limited form of conditional compilation.
2193 if (condition
->include(sc
, NULL
))
2195 ifbody
= ifbody
->semantic(sc
);
2201 elsebody
= elsebody
->semantic(sc
);
2206 Statements
*ConditionalStatement::flatten(Scope
*sc
)
2210 if (condition
->include(sc
, NULL
))
2215 Statements
*a
= new Statements();
2220 int ConditionalStatement::usesEH()
2222 return (ifbody
&& ifbody
->usesEH()) || (elsebody
&& elsebody
->usesEH());
2225 void ConditionalStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2227 condition
->toCBuffer(buf
, hgs
);
2230 ifbody
->toCBuffer(buf
, hgs
);
2233 buf
->writestring("else");
2235 elsebody
->toCBuffer(buf
, hgs
);
2241 /******************************** PragmaStatement ***************************/
2243 PragmaStatement::PragmaStatement(Loc loc
, Identifier
*ident
, Expressions
*args
, Statement
*body
)
2246 this->ident
= ident
;
2251 Statement
*PragmaStatement::syntaxCopy()
2253 Statement
*b
= NULL
;
2255 b
= body
->syntaxCopy();
2256 PragmaStatement
*s
= new PragmaStatement(loc
,
2257 ident
, Expression::arraySyntaxCopy(args
), b
);
2261 Statement
*PragmaStatement::semantic(Scope
*sc
)
2262 { // Should be merged with PragmaDeclaration
2263 //printf("PragmaStatement::semantic() %s\n", toChars());
2264 //printf("body = %p\n", body);
2265 if (ident
== Id::msg
)
2269 for (size_t i
= 0; i
< args
->dim
; i
++)
2271 Expression
*e
= (Expression
*)args
->data
[i
];
2273 e
= e
->semantic(sc
);
2274 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2275 if (e
->op
== TOKstring
)
2277 StringExp
*se
= (StringExp
*)e
;
2278 fprintf(stdmsg
, "%.*s", (int)se
->len
, se
->string
);
2281 error("string expected for message, not '%s'", e
->toChars());
2283 fprintf(stdmsg
, "\n");
2286 else if (ident
== Id::lib
)
2288 if (!args
|| args
->dim
!= 1)
2289 error("string expected for library name");
2292 Expression
*e
= (Expression
*)args
->data
[0];
2294 e
= e
->semantic(sc
);
2295 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2296 args
->data
[0] = (void *)e
;
2297 if (e
->op
!= TOKstring
)
2298 error("string expected for library name, not '%s'", e
->toChars());
2299 else if (global
.params
.verbose
)
2301 StringExp
*se
= (StringExp
*)e
;
2302 char *name
= (char *)mem
.malloc(se
->len
+ 1);
2303 memcpy(name
, se
->string
, se
->len
);
2305 printf("library %s\n", name
);
2310 else if (ident
== Id::startaddress
)
2312 if (!args
|| args
->dim
!= 1)
2313 error("function name expected for start address");
2316 Expression
*e
= (Expression
*)args
->data
[0];
2317 e
= e
->semantic(sc
);
2318 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2319 args
->data
[0] = (void *)e
;
2320 Dsymbol
*sa
= getDsymbol(e
);
2321 if (!sa
|| !sa
->isFuncDeclaration())
2322 error("function name expected for start address, not '%s'", e
->toChars());
2325 body
= body
->semantic(sc
);
2331 error("unrecognized pragma(%s)", ident
->toChars());
2335 body
= body
->semantic(sc
);
2340 int PragmaStatement::usesEH()
2342 return body
&& body
->usesEH();
2345 int PragmaStatement::blockExit()
2347 int result
= BEfallthru
;
2348 #if 0 // currently, no code is generated for Pragma's, so it's just fallthru
2349 if (arrayExpressionCanThrow(args
))
2352 result
|= body
->blockExit();
2357 int PragmaStatement::fallOffEnd()
2360 return body
->fallOffEnd();
2364 void PragmaStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2366 buf
->writestring("pragma (");
2367 buf
->writestring(ident
->toChars());
2368 if (args
&& args
->dim
)
2370 buf
->writestring(", ");
2371 argsToCBuffer(buf
, args
, hgs
);
2373 buf
->writeByte(')');
2377 buf
->writeByte('{');
2380 body
->toCBuffer(buf
, hgs
);
2382 buf
->writeByte('}');
2387 buf
->writeByte(';');
2393 /******************************** LogStatement ***************************/
2395 LogStatement::LogStatement(Loc loc
, int level
, Expressions
*args
)
2398 this->level
= level
;
2402 Statement
*LogStatement::syntaxCopy()
2404 Expressions
*copied_args
= Expression::arraySyntaxCopy(args
);
2405 LogStatement
*s
= new LogStatement(loc
, level
, copied_args
);
2409 Statement
*LogStatement::semantic(Scope
*sc
)
2411 Expression
*logger
= new GetLoggerExp(loc
);
2414 for (Dsymbol
*s
= sc
->parent
; s
; s
= s
->parent
)
2416 ClassDeclaration
*cd
;
2417 StructDeclaration
*sd
;
2419 cd
= s
->isClassDeclaration();
2428 // We're a top-level function. Generate log messages from the module
2429 args
->shift(new StringExp(loc
, strdup(sc
->module
->ident
->string
)));
2431 args
->shift(new StringExp(loc
, type
->toChars()));
2434 args
->shift(new IntegerExp(loc
, level
, Type::tint32
));
2435 Expression
*callLogger
= new CallExp(loc
, logger
, args
);
2437 Statement
*s
= new ExpStatement(loc
, callLogger
);
2439 return s
->semantic(sc
);
2442 void LogStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2446 case 10: l
= "log_debug"; break;
2447 case 20: l
= "log_info"; break;
2448 case 30: l
= "log_warning"; break;
2449 case 40: l
= "log_error"; break;
2451 error("Unknown log level %d", level
);
2454 buf
->writestring(l
);
2455 buf
->writeByte('(');
2456 argsToCBuffer(buf
, args
, hgs
);
2457 buf
->writeByte(')');
2461 /******************************** StaticAssertStatement ***************************/
2463 StaticAssertStatement::StaticAssertStatement(StaticAssert
*sa
)
2464 : Statement(sa
->loc
)
2469 Statement
*StaticAssertStatement::syntaxCopy()
2471 StaticAssertStatement
*s
= new StaticAssertStatement((StaticAssert
*)sa
->syntaxCopy(NULL
));
2475 Statement
*StaticAssertStatement::semantic(Scope
*sc
)
2481 void StaticAssertStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2483 sa
->toCBuffer(buf
, hgs
);
2487 /******************************** SwitchStatement ***************************/
2489 SwitchStatement::SwitchStatement(Loc loc
, Expression
*c
, Statement
*b
)
2501 Statement
*SwitchStatement::syntaxCopy()
2503 SwitchStatement
*s
= new SwitchStatement(loc
,
2504 condition
->syntaxCopy(), body
->syntaxCopy());
2508 Statement
*SwitchStatement::semantic(Scope
*sc
)
2510 //printf("SwitchStatement::semantic(%p)\n", this);
2512 assert(!cases
); // ensure semantic() is only run once
2513 condition
= condition
->semantic(sc
);
2514 condition
= resolveProperties(sc
, condition
);
2515 if (condition
->type
->isString())
2517 // If it's not an array, cast it to one
2518 if (condition
->type
->ty
!= Tarray
)
2520 condition
= condition
->implicitCastTo(sc
, condition
->type
->nextOf()->arrayOf());
2522 condition
->type
= condition
->type
->constOf();
2525 { condition
= condition
->integralPromotions(sc
);
2526 condition
->checkIntegral();
2528 condition
= condition
->optimize(WANTvalue
);
2534 cases
= new Array();
2535 sc
->noctor
++; // BUG: should use Scope::mergeCallSuper() for each case instead
2536 body
= body
->semantic(sc
);
2539 // Resolve any goto case's with exp
2540 for (int i
= 0; i
< gotoCases
.dim
; i
++)
2542 GotoCaseStatement
*gcs
= (GotoCaseStatement
*)gotoCases
.data
[i
];
2546 gcs
->error("no case statement following goto case;");
2550 for (Scope
*scx
= sc
; scx
; scx
= scx
->enclosing
)
2554 for (int j
= 0; j
< scx
->sw
->cases
->dim
; j
++)
2556 CaseStatement
*cs
= (CaseStatement
*)scx
->sw
->cases
->data
[j
];
2558 if (cs
->exp
->equals(gcs
->exp
))
2565 gcs
->error("case %s not found", gcs
->exp
->toChars());
2571 if (!sc
->sw
->sdefault
)
2574 if (global
.params
.warnings
)
2575 { fprintf(stdmsg
, "warning - ");
2576 error("switch statement has no default");
2579 // Generate runtime error if the default is hit
2580 Statements
*a
= new Statements();
2581 CompoundStatement
*cs
;
2584 if (global
.params
.useSwitchError
)
2585 s
= new SwitchErrorStatement(loc
);
2587 { Expression
*e
= new HaltExp(loc
);
2588 s
= new ExpStatement(loc
, e
);
2593 a
->push(new BreakStatement(loc
, NULL
));
2594 sc
->sw
->sdefault
= new DefaultStatement(loc
, s
);
2595 a
->push(sc
->sw
->sdefault
);
2596 cs
= new CompoundStatement(loc
, a
);
2604 int SwitchStatement::hasBreak()
2609 int SwitchStatement::usesEH()
2611 return body
? body
->usesEH() : 0;
2614 int SwitchStatement::blockExit()
2615 { int result
= BEnone
;
2616 if (condition
->canThrow())
2620 { result
|= body
->blockExit();
2621 if (result
& BEbreak
)
2622 { result
|= BEfallthru
;
2627 result
|= BEfallthru
;
2632 int SwitchStatement::fallOffEnd()
2636 return TRUE
; // need to do this better
2639 void SwitchStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2641 buf
->writestring("switch (");
2642 condition
->toCBuffer(buf
, hgs
);
2643 buf
->writebyte(')');
2647 if (!body
->isScopeStatement())
2648 { buf
->writebyte('{');
2650 body
->toCBuffer(buf
, hgs
);
2651 buf
->writebyte('}');
2656 body
->toCBuffer(buf
, hgs
);
2661 /******************************** CaseStatement ***************************/
2663 CaseStatement::CaseStatement(Loc loc
, Expression
*exp
, Statement
*s
)
2667 this->statement
= s
;
2672 Statement
*CaseStatement::syntaxCopy()
2674 CaseStatement
*s
= new CaseStatement(loc
, exp
->syntaxCopy(), statement
->syntaxCopy());
2678 Statement
*CaseStatement::semantic(Scope
*sc
)
2679 { SwitchStatement
*sw
= sc
->sw
;
2681 //printf("CaseStatement::semantic() %s\n", toChars());
2682 exp
= exp
->semantic(sc
);
2685 exp
= exp
->implicitCastTo(sc
, sw
->condition
->type
);
2686 exp
= exp
->optimize(WANTvalue
| WANTinterpret
);
2688 /* This is where variables are allowed as case expressions.
2690 if (exp
->op
== TOKvar
)
2691 { VarExp
*ve
= (VarExp
*)exp
;
2692 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
2693 Type
*t
= exp
->type
->toBasetype();
2694 if (v
&& (t
->isintegral() || t
->ty
== Tclass
))
2695 { /* Flag that we need to do special code generation
2696 * for this, i.e. generate a sequence of if-then-else
2703 if (exp
->op
!= TOKstring
&& exp
->op
!= TOKint64
)
2705 error("case must be a string or an integral constant, not %s", exp
->toChars());
2706 exp
= new IntegerExp(0);
2710 for (int i
= 0; i
< sw
->cases
->dim
; i
++)
2712 CaseStatement
*cs
= (CaseStatement
*)sw
->cases
->data
[i
];
2714 //printf("comparing '%s' with '%s'\n", exp->toChars(), cs->exp->toChars());
2715 if (cs
->exp
->equals(exp
))
2716 { error("duplicate case %s in switch statement", exp
->toChars());
2721 sw
->cases
->push(this);
2723 // Resolve any goto case's with no exp to this case statement
2724 for (int i
= 0; i
< sw
->gotoCases
.dim
; i
++)
2726 GotoCaseStatement
*gcs
= (GotoCaseStatement
*)sw
->gotoCases
.data
[i
];
2731 sw
->gotoCases
.remove(i
); // remove from array
2735 if (sc
->sw
->tf
!= sc
->tf
)
2736 error("switch and case are in different finally blocks");
2739 error("case not in switch statement");
2740 statement
= statement
->semantic(sc
);
2744 int CaseStatement::compare(Object
*obj
)
2746 // Sort cases so we can do an efficient lookup
2747 CaseStatement
*cs2
= (CaseStatement
*)(obj
);
2749 return exp
->compare(cs2
->exp
);
2752 int CaseStatement::usesEH()
2754 return statement
->usesEH();
2757 int CaseStatement::blockExit()
2763 int CaseStatement::fallOffEnd()
2765 return statement
->fallOffEnd();
2768 int CaseStatement::comeFrom()
2773 void CaseStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2775 buf
->writestring("case ");
2776 exp
->toCBuffer(buf
, hgs
);
2777 buf
->writebyte(':');
2779 statement
->toCBuffer(buf
, hgs
);
2782 /******************************** DefaultStatement ***************************/
2784 DefaultStatement::DefaultStatement(Loc loc
, Statement
*s
)
2787 this->statement
= s
;
2793 Statement
*DefaultStatement::syntaxCopy()
2795 DefaultStatement
*s
= new DefaultStatement(loc
, statement
->syntaxCopy());
2799 Statement
*DefaultStatement::semantic(Scope
*sc
)
2801 //printf("DefaultStatement::semantic()\n");
2804 if (sc
->sw
->sdefault
)
2806 error("switch statement already has a default");
2808 sc
->sw
->sdefault
= this;
2810 if (sc
->sw
->tf
!= sc
->tf
)
2811 error("switch and default are in different finally blocks");
2814 error("default not in switch statement");
2815 statement
= statement
->semantic(sc
);
2819 int DefaultStatement::usesEH()
2821 return statement
->usesEH();
2824 int DefaultStatement::blockExit()
2830 int DefaultStatement::fallOffEnd()
2832 return statement
->fallOffEnd();
2835 int DefaultStatement::comeFrom()
2840 void DefaultStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2842 buf
->writestring("default:\n");
2843 statement
->toCBuffer(buf
, hgs
);
2846 /******************************** GotoDefaultStatement ***************************/
2848 GotoDefaultStatement::GotoDefaultStatement(Loc loc
)
2854 Statement
*GotoDefaultStatement::syntaxCopy()
2856 GotoDefaultStatement
*s
= new GotoDefaultStatement(loc
);
2860 Statement
*GotoDefaultStatement::semantic(Scope
*sc
)
2864 error("goto default not in switch statement");
2868 int GotoDefaultStatement::blockExit()
2873 int GotoDefaultStatement::fallOffEnd()
2878 void GotoDefaultStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2880 buf
->writestring("goto default;\n");
2883 /******************************** GotoCaseStatement ***************************/
2885 GotoCaseStatement::GotoCaseStatement(Loc loc
, Expression
*exp
)
2892 Statement
*GotoCaseStatement::syntaxCopy()
2894 Expression
*e
= exp
? exp
->syntaxCopy() : NULL
;
2895 GotoCaseStatement
*s
= new GotoCaseStatement(loc
, e
);
2899 Statement
*GotoCaseStatement::semantic(Scope
*sc
)
2902 exp
= exp
->semantic(sc
);
2905 error("goto case not in switch statement");
2908 sc
->sw
->gotoCases
.push(this);
2911 exp
= exp
->implicitCastTo(sc
, sc
->sw
->condition
->type
);
2912 exp
= exp
->optimize(WANTvalue
);
2918 int GotoCaseStatement::blockExit()
2923 int GotoCaseStatement::fallOffEnd()
2928 void GotoCaseStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2930 buf
->writestring("goto case");
2932 { buf
->writebyte(' ');
2933 exp
->toCBuffer(buf
, hgs
);
2935 buf
->writebyte(';');
2939 /******************************** SwitchErrorStatement ***************************/
2941 SwitchErrorStatement::SwitchErrorStatement(Loc loc
)
2946 int SwitchErrorStatement::blockExit()
2951 int SwitchErrorStatement::fallOffEnd()
2956 void SwitchErrorStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2958 buf
->writestring("SwitchErrorStatement::toCBuffer()");
2962 /******************************** ReturnStatement ***************************/
2964 ReturnStatement::ReturnStatement(Loc loc
, Expression
*exp
)
2970 Statement
*ReturnStatement::syntaxCopy()
2972 Expression
*e
= NULL
;
2974 e
= exp
->syntaxCopy();
2975 ReturnStatement
*s
= new ReturnStatement(loc
, e
);
2979 Statement
*ReturnStatement::semantic(Scope
*sc
)
2981 //printf("ReturnStatement::semantic() %s\n", toChars());
2983 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
2989 // Find scope of function foreach is in
2990 for (; 1; scx
= scx
->enclosing
)
2993 if (scx
->func
!= fd
)
2994 { fd
= scx
->func
; // fd is now function enclosing foreach
3000 Type
*tret
= fd
->type
->nextOf();
3002 tret
= fd
->tintro
->nextOf();
3006 tbret
= tret
->toBasetype();
3008 // main() returns 0, even if it returns void
3009 if (!exp
&& (!tbret
|| tbret
->ty
== Tvoid
) && fd
->isMain())
3011 exp
= new IntegerExp(0);
3014 if (sc
->incontract
|| scx
->incontract
)
3015 error("return statements cannot be in contracts");
3016 if (sc
->tf
|| scx
->tf
)
3017 error("return statements cannot be in finally, scope(exit) or scope(success) bodies");
3019 if (fd
->isCtorDeclaration())
3021 // Constructors implicitly do:
3023 if (exp
&& exp
->op
!= TOKthis
)
3024 error("cannot return expression from constructor");
3025 exp
= new ThisExp(0);
3033 fd
->hasReturnExp
|= 1;
3035 exp
= exp
->semantic(sc
);
3036 exp
= resolveProperties(sc
, exp
);
3037 exp
= exp
->optimize(WANTvalue
);
3039 if (fd
->nrvo_can
&& exp
->op
== TOKvar
)
3040 { VarExp
*ve
= (VarExp
*)exp
;
3041 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
3043 if (!v
|| v
->isOut() || v
->isRef())
3045 else if (tbret
->ty
== Tstruct
&& ((TypeStruct
*)tbret
)->sym
->dtor
)
3046 // Struct being returned has destructors
3048 else if (fd
->nrvo_var
== NULL
)
3049 { if (!v
->isDataseg() && !v
->isParameter() && v
->toParent2() == fd
)
3050 { //printf("Setting nrvo to %s\n", v->toChars());
3056 else if (fd
->nrvo_var
!= v
)
3062 if (fd
->returnLabel
&& tbret
->ty
!= Tvoid
)
3065 else if (fd
->inferRetType
)
3067 if (fd
->type
->nextOf())
3069 if (!exp
->type
->equals(fd
->type
->nextOf()))
3070 error("mismatched function return type inference of %s and %s",
3071 exp
->type
->toChars(), fd
->type
->nextOf()->toChars());
3075 ((TypeFunction
*)fd
->type
)->next
= exp
->type
;
3076 fd
->type
= fd
->type
->semantic(loc
, sc
);
3078 { tret
= fd
->type
->nextOf();
3079 tbret
= tret
->toBasetype();
3083 else if (tbret
->ty
!= Tvoid
)
3085 exp
= exp
->implicitCastTo(sc
, tret
);
3088 else if (fd
->inferRetType
)
3090 if (fd
->type
->nextOf())
3092 if (fd
->type
->nextOf()->ty
!= Tvoid
)
3093 error("mismatched function return type inference of void and %s",
3094 fd
->type
->nextOf()->toChars());
3098 ((TypeFunction
*)fd
->type
)->next
= Type::tvoid
;
3099 fd
->type
= fd
->type
->semantic(loc
, sc
);
3101 { tret
= Type::tvoid
;
3106 else if (tbret
->ty
!= Tvoid
) // if non-void return
3107 error("return expression expected");
3113 if (exp
&& !implicit0
)
3115 exp
= exp
->implicitCastTo(sc
, tret
);
3117 if (!exp
|| exp
->op
== TOKint64
|| exp
->op
== TOKfloat64
||
3118 exp
->op
== TOKimaginary80
|| exp
->op
== TOKcomplex80
||
3119 exp
->op
== TOKthis
|| exp
->op
== TOKsuper
|| exp
->op
== TOKnull
||
3120 exp
->op
== TOKstring
)
3122 sc
->fes
->cases
.push(this);
3123 s
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
3125 else if (fd
->type
->nextOf()->toBasetype() == Type::tvoid
)
3130 s
= new ReturnStatement(0, NULL
);
3131 sc
->fes
->cases
.push(s
);
3133 // Construct: { exp; return cases.dim + 1; }
3134 s1
= new ExpStatement(loc
, exp
);
3135 s2
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
3136 s
= new CompoundStatement(loc
, s1
, s2
);
3144 // Construct: return vresult;
3146 { VarDeclaration
*v
;
3148 v
= new VarDeclaration(loc
, tret
, Id::result
, NULL
);
3151 if (!scx
->insert(v
))
3157 v
= new VarExp(0, fd
->vresult
);
3158 s
= new ReturnStatement(0, v
);
3159 sc
->fes
->cases
.push(s
);
3161 // Construct: { vresult = exp; return cases.dim + 1; }
3162 v
= new VarExp(0, fd
->vresult
);
3163 exp
= new AssignExp(loc
, v
, exp
);
3164 exp
= exp
->semantic(sc
);
3165 s1
= new ExpStatement(loc
, exp
);
3166 s2
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
3167 s
= new CompoundStatement(loc
, s1
, s2
);
3174 if (fd
->returnLabel
&& tbret
->ty
!= Tvoid
)
3176 assert(fd
->vresult
);
3177 VarExp
*v
= new VarExp(0, fd
->vresult
);
3179 exp
= new AssignExp(loc
, v
, exp
);
3180 exp
= exp
->semantic(sc
);
3187 /* BUG: need to issue an error on:
3194 if (sc
->callSuper
& CSXany_ctor
&&
3195 !(sc
->callSuper
& (CSXthis_ctor
| CSXsuper_ctor
)))
3196 error("return without calling constructor");
3198 sc
->callSuper
|= CSXreturn
;
3200 // See if all returns are instead to be replaced with a goto returnLabel;
3201 if (fd
->returnLabel
)
3203 GotoStatement
*gs
= new GotoStatement(loc
, Id::returnLabel
);
3205 gs
->label
= fd
->returnLabel
;
3209 s
= new ExpStatement(0, exp
);
3210 return new CompoundStatement(loc
, s
, gs
);
3215 if (exp
&& tbret
->ty
== Tvoid
&& !fd
->isMain())
3218 s
= new ExpStatement(loc
, exp
);
3221 return new CompoundStatement(loc
, s
, this);
3227 int ReturnStatement::blockExit()
3228 { int result
= BEreturn
;
3230 if (exp
&& exp
->canThrow())
3235 int ReturnStatement::fallOffEnd()
3240 void ReturnStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3242 buf
->printf("return ");
3244 exp
->toCBuffer(buf
, hgs
);
3245 buf
->writeByte(';');
3249 /******************************** BreakStatement ***************************/
3251 BreakStatement::BreakStatement(Loc loc
, Identifier
*ident
)
3254 this->ident
= ident
;
3257 Statement
*BreakStatement::syntaxCopy()
3259 BreakStatement
*s
= new BreakStatement(loc
, ident
);
3263 Statement
*BreakStatement::semantic(Scope
*sc
)
3265 //printf("BreakStatement::semantic()\n");
3267 // break Identifier;
3271 FuncDeclaration
*thisfunc
= sc
->func
;
3273 for (scx
= sc
; scx
; scx
= scx
->enclosing
)
3277 if (scx
->func
!= thisfunc
) // if in enclosing function
3279 if (sc
->fes
) // if this is the body of a foreach
3281 /* Post this statement to the fes, and replace
3282 * it with a return value that caller will put into
3283 * a switch. Caller will figure out where the break
3284 * label actually is.
3285 * Case numbers start with 2, not 0, as 0 is continue
3289 sc
->fes
->cases
.push(this);
3290 s
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
3293 break; // can't break to it
3297 if (ls
&& ls
->ident
== ident
)
3299 Statement
*s
= ls
->statement
;
3302 error("label '%s' has no break", ident
->toChars());
3303 if (ls
->tf
!= sc
->tf
)
3304 error("cannot break out of finally block");
3308 error("enclosing label '%s' for break not found", ident
->toChars());
3310 else if (!sc
->sbreak
)
3315 // Replace break; with return 1;
3316 s
= new ReturnStatement(0, new IntegerExp(1));
3319 error("break is not inside a loop or switch");
3324 int BreakStatement::blockExit()
3326 //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak);
3327 return ident
? BEgoto
: BEbreak
;
3330 int BreakStatement::fallOffEnd()
3335 void BreakStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3337 buf
->writestring("break");
3339 { buf
->writebyte(' ');
3340 buf
->writestring(ident
->toChars());
3342 buf
->writebyte(';');
3346 /******************************** ContinueStatement ***************************/
3348 ContinueStatement::ContinueStatement(Loc loc
, Identifier
*ident
)
3351 this->ident
= ident
;
3354 Statement
*ContinueStatement::syntaxCopy()
3356 ContinueStatement
*s
= new ContinueStatement(loc
, ident
);
3360 Statement
*ContinueStatement::semantic(Scope
*sc
)
3362 //printf("ContinueStatement::semantic() %p\n", this);
3366 FuncDeclaration
*thisfunc
= sc
->func
;
3368 for (scx
= sc
; scx
; scx
= scx
->enclosing
)
3372 if (scx
->func
!= thisfunc
) // if in enclosing function
3374 if (sc
->fes
) // if this is the body of a foreach
3376 for (; scx
; scx
= scx
->enclosing
)
3379 if (ls
&& ls
->ident
== ident
&& ls
->statement
== sc
->fes
)
3381 // Replace continue ident; with return 0;
3382 return new ReturnStatement(0, new IntegerExp(0));
3386 /* Post this statement to the fes, and replace
3387 * it with a return value that caller will put into
3388 * a switch. Caller will figure out where the break
3389 * label actually is.
3390 * Case numbers start with 2, not 0, as 0 is continue
3394 sc
->fes
->cases
.push(this);
3395 s
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
3398 break; // can't continue to it
3402 if (ls
&& ls
->ident
== ident
)
3404 Statement
*s
= ls
->statement
;
3406 if (!s
->hasContinue())
3407 error("label '%s' has no continue", ident
->toChars());
3408 if (ls
->tf
!= sc
->tf
)
3409 error("cannot continue out of finally block");
3413 error("enclosing label '%s' for continue not found", ident
->toChars());
3415 else if (!sc
->scontinue
)
3420 // Replace continue; with return 0;
3421 s
= new ReturnStatement(0, new IntegerExp(0));
3424 error("continue is not inside a loop");
3429 int ContinueStatement::blockExit()
3431 return ident
? BEgoto
: BEcontinue
;
3434 int ContinueStatement::fallOffEnd()
3439 void ContinueStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3441 buf
->writestring("continue");
3443 { buf
->writebyte(' ');
3444 buf
->writestring(ident
->toChars());
3446 buf
->writebyte(';');
3450 /******************************** SynchronizedStatement ***************************/
3452 SynchronizedStatement::SynchronizedStatement(Loc loc
, Expression
*exp
, Statement
*body
)
3460 SynchronizedStatement::SynchronizedStatement(Loc loc
, elem
*esync
, Statement
*body
)
3465 this->esync
= esync
;
3468 Statement
*SynchronizedStatement::syntaxCopy()
3470 Expression
*e
= exp
? exp
->syntaxCopy() : NULL
;
3471 SynchronizedStatement
*s
= new SynchronizedStatement(loc
, e
, body
? body
->syntaxCopy() : NULL
);
3475 Statement
*SynchronizedStatement::semantic(Scope
*sc
)
3478 { ClassDeclaration
*cd
;
3480 exp
= exp
->semantic(sc
);
3481 exp
= resolveProperties(sc
, exp
);
3482 cd
= exp
->type
->isClassHandle();
3484 error("can only synchronize on class objects, not '%s'", exp
->type
->toChars());
3485 else if (cd
->isInterfaceDeclaration())
3486 { Type
*t
= new TypeIdentifier(0, Id::Object
);
3488 t
= t
->semantic(0, sc
);
3489 exp
= new CastExp(loc
, exp
, t
);
3490 exp
= exp
->semantic(sc
);
3494 body
= body
->semantic(sc
);
3498 int SynchronizedStatement::hasBreak()
3500 return FALSE
; //TRUE;
3503 int SynchronizedStatement::hasContinue()
3505 return FALSE
; //TRUE;
3508 int SynchronizedStatement::usesEH()
3513 int SynchronizedStatement::blockExit()
3515 return body
? body
->blockExit() : BEfallthru
;
3518 int SynchronizedStatement::fallOffEnd()
3520 return body
? body
->fallOffEnd() : TRUE
;
3523 void SynchronizedStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3525 buf
->writestring("synchronized");
3527 { buf
->writebyte('(');
3528 exp
->toCBuffer(buf
, hgs
);
3529 buf
->writebyte(')');
3533 buf
->writebyte(' ');
3534 body
->toCBuffer(buf
, hgs
);
3538 /******************************** WithStatement ***************************/
3540 WithStatement::WithStatement(Loc loc
, Expression
*exp
, Statement
*body
)
3548 Statement
*WithStatement::syntaxCopy()
3550 WithStatement
*s
= new WithStatement(loc
, exp
->syntaxCopy(), body
? body
->syntaxCopy() : NULL
);
3554 Statement
*WithStatement::semantic(Scope
*sc
)
3555 { ScopeDsymbol
*sym
;
3558 //printf("WithStatement::semantic()\n");
3559 exp
= exp
->semantic(sc
);
3560 exp
= resolveProperties(sc
, exp
);
3561 if (exp
->op
== TOKimport
)
3562 { ScopeExp
*es
= (ScopeExp
*)exp
;
3566 else if (exp
->op
== TOKtype
)
3567 { TypeExp
*es
= (TypeExp
*)exp
;
3569 sym
= es
->type
->toDsymbol(sc
)->isScopeDsymbol();
3571 { error("%s has no members", es
->toChars());
3572 body
= body
->semantic(sc
);
3577 { Type
*t
= exp
->type
;
3580 t
= t
->toBasetype();
3581 if (t
->isClassHandle())
3583 init
= new ExpInitializer(loc
, exp
);
3584 wthis
= new VarDeclaration(loc
, exp
->type
, Id::withSym
, init
);
3585 wthis
->semantic(sc
);
3587 sym
= new WithScopeSymbol(this);
3588 sym
->parent
= sc
->scopesym
;
3590 else if (t
->ty
== Tstruct
)
3592 Expression
*e
= exp
->addressOf(sc
);
3593 init
= new ExpInitializer(loc
, e
);
3594 wthis
= new VarDeclaration(loc
, e
->type
, Id::withSym
, init
);
3595 wthis
->semantic(sc
);
3596 sym
= new WithScopeSymbol(this);
3597 sym
->parent
= sc
->scopesym
;
3600 { error("with expressions must be class objects, not '%s'", exp
->type
->toChars());
3607 body
= body
->semantic(sc
);
3614 void WithStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3616 buf
->writestring("with (");
3617 exp
->toCBuffer(buf
, hgs
);
3618 buf
->writestring(")\n");
3620 body
->toCBuffer(buf
, hgs
);
3623 int WithStatement::usesEH()
3625 return body
? body
->usesEH() : 0;
3628 int WithStatement::blockExit()
3630 int result
= BEnone
;
3631 if (exp
->canThrow())
3634 result
|= body
->blockExit();
3636 result
|= BEfallthru
;
3640 int WithStatement::fallOffEnd()
3642 return body
? body
->fallOffEnd() : TRUE
;
3645 /******************************** TryCatchStatement ***************************/
3647 TryCatchStatement::TryCatchStatement(Loc loc
, Statement
*body
, Array
*catches
)
3651 this->catches
= catches
;
3654 Statement
*TryCatchStatement::syntaxCopy()
3656 Array
*a
= new Array();
3657 a
->setDim(catches
->dim
);
3658 for (int i
= 0; i
< a
->dim
; i
++)
3661 c
= (Catch
*)catches
->data
[i
];
3662 c
= c
->syntaxCopy();
3665 TryCatchStatement
*s
= new TryCatchStatement(loc
, body
->syntaxCopy(), a
);
3669 Statement
*TryCatchStatement::semantic(Scope
*sc
)
3671 body
= body
->semanticScope(sc
, NULL
/*this*/, NULL
);
3673 /* Even if body is NULL, still do semantic analysis on catches
3675 for (size_t i
= 0; i
< catches
->dim
; i
++)
3676 { Catch
*c
= (Catch
*)catches
->data
[i
];
3679 // Determine if current catch 'hides' any previous catches
3680 for (size_t j
= 0; j
< i
; j
++)
3681 { Catch
*cj
= (Catch
*)catches
->data
[j
];
3682 char *si
= c
->loc
.toChars();
3683 char *sj
= cj
->loc
.toChars();
3685 if (c
->type
->toBasetype()->implicitConvTo(cj
->type
->toBasetype()))
3686 error("catch at %s hides catch at %s", sj
, si
);
3696 int TryCatchStatement::hasBreak()
3698 return FALSE
; //TRUE;
3701 int TryCatchStatement::usesEH()
3706 int TryCatchStatement::blockExit()
3710 result
= body
->blockExit();
3712 for (size_t i
= 0; i
< catches
->dim
; i
++)
3714 Catch
*c
= (Catch
*)catches
->data
[i
];
3715 result
|= c
->blockExit();
3720 int TryCatchStatement::fallOffEnd()
3725 result
= body
->fallOffEnd();
3726 for (int i
= 0; i
< catches
->dim
; i
++)
3729 c
= (Catch
*)catches
->data
[i
];
3731 result
|= c
->handler
->fallOffEnd();
3736 void TryCatchStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3738 buf
->writestring("try");
3741 body
->toCBuffer(buf
, hgs
);
3742 for (size_t i
= 0; i
< catches
->dim
; i
++)
3744 Catch
*c
= (Catch
*)catches
->data
[i
];
3745 c
->toCBuffer(buf
, hgs
);
3749 /******************************** Catch ***************************/
3751 Catch::Catch(Loc loc
, Type
*t
, Identifier
*id
, Statement
*handler
)
3753 //printf("Catch(%s, loc = %s)\n", id->toChars(), loc.toChars());
3757 this->handler
= handler
;
3761 Catch
*Catch::syntaxCopy()
3763 Catch
*c
= new Catch(loc
,
3764 (type
? type
->syntaxCopy() : NULL
),
3766 (handler
? handler
->syntaxCopy() : NULL
));
3770 void Catch::semantic(Scope
*sc
)
3771 { ScopeDsymbol
*sym
;
3773 //printf("Catch::semantic(%s)\n", ident->toChars());
3778 /* This is because the _d_local_unwind() gets the stack munged
3779 * up on this. The workaround is to place any try-catches into
3780 * a separate function, and call that.
3781 * To fix, have the compiler automatically convert the finally
3782 * body into a nested function.
3784 error(loc
, "cannot put catch statement inside finally block");
3788 sym
= new ScopeDsymbol();
3789 sym
->parent
= sc
->scopesym
;
3793 type
= new TypeIdentifier(0, Id::Object
);
3794 type
= type
->semantic(loc
, sc
);
3795 if (!type
->toBasetype()->isClassHandle())
3796 error("can only catch class objects, not '%s'", type
->toChars());
3799 var
= new VarDeclaration(loc
, type
, ident
, NULL
);
3800 var
->parent
= sc
->parent
;
3803 handler
= handler
->semantic(sc
);
3808 int Catch::blockExit()
3810 return handler
? handler
->blockExit() : BEfallthru
;
3813 void Catch::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3815 buf
->writestring("catch");
3817 { buf
->writebyte('(');
3818 type
->toCBuffer(buf
, ident
, hgs
);
3819 buf
->writebyte(')');
3822 buf
->writebyte('{');
3825 handler
->toCBuffer(buf
, hgs
);
3826 buf
->writebyte('}');
3830 /****************************** TryFinallyStatement ***************************/
3832 TryFinallyStatement::TryFinallyStatement(Loc loc
, Statement
*body
, Statement
*finalbody
)
3836 this->finalbody
= finalbody
;
3839 Statement
*TryFinallyStatement::syntaxCopy()
3841 TryFinallyStatement
*s
= new TryFinallyStatement(loc
,
3842 body
->syntaxCopy(), finalbody
->syntaxCopy());
3846 Statement
*TryFinallyStatement::semantic(Scope
*sc
)
3848 //printf("TryFinallyStatement::semantic()\n");
3849 body
= body
->semantic(sc
);
3853 sc
->scontinue
= NULL
; // no break or continue out of finally block
3854 finalbody
= finalbody
->semantic(sc
);
3860 if (body
->blockExit() == BEfallthru
)
3861 { Statement
*s
= new CompoundStatement(loc
, body
, finalbody
);
3867 void TryFinallyStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3869 buf
->printf("try\n{\n");
3870 body
->toCBuffer(buf
, hgs
);
3871 buf
->printf("}\nfinally\n{\n");
3872 finalbody
->toCBuffer(buf
, hgs
);
3873 buf
->writeByte('}');
3877 int TryFinallyStatement::hasBreak()
3879 return FALSE
; //TRUE;
3882 int TryFinallyStatement::hasContinue()
3884 return FALSE
; //TRUE;
3887 int TryFinallyStatement::usesEH()
3892 int TryFinallyStatement::blockExit()
3894 int result
= body
->blockExit();
3898 int TryFinallyStatement::fallOffEnd()
3901 result
= body
->fallOffEnd();
3903 // result = finalbody->fallOffEnd();
3907 /****************************** OnScopeStatement ***************************/
3909 OnScopeStatement::OnScopeStatement(Loc loc
, TOK tok
, Statement
*statement
)
3913 this->statement
= statement
;
3916 Statement
*OnScopeStatement::syntaxCopy()
3918 OnScopeStatement
*s
= new OnScopeStatement(loc
,
3919 tok
, statement
->syntaxCopy());
3923 Statement
*OnScopeStatement::semantic(Scope
*sc
)
3925 /* semantic is called on results of scopeCode() */
3929 int OnScopeStatement::blockExit()
3930 { // At this point, this statement is just an empty placeholder
3934 void OnScopeStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3936 buf
->writestring(Token::toChars(tok
));
3937 buf
->writebyte(' ');
3938 statement
->toCBuffer(buf
, hgs
);
3941 int OnScopeStatement::usesEH()
3946 void OnScopeStatement::scopeCode(Scope
*sc
, Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
3948 //printf("OnScopeStatement::scopeCode()\n");
3955 case TOKon_scope_exit
:
3956 *sfinally
= statement
;
3959 case TOKon_scope_failure
:
3960 *sexception
= statement
;
3963 case TOKon_scope_success
:
3966 * sentry: int x = 0;
3967 * sexception: x = 1;
3968 * sfinally: if (!x) statement;
3970 Identifier
*id
= Lexer::uniqueId("__os");
3972 ExpInitializer
*ie
= new ExpInitializer(loc
, new IntegerExp(0));
3973 VarDeclaration
*v
= new VarDeclaration(loc
, Type::tint32
, id
, ie
);
3974 *sentry
= new DeclarationStatement(loc
, v
);
3976 Expression
*e
= new IntegerExp(1);
3977 e
= new AssignExp(0, new VarExp(0, v
), e
);
3978 *sexception
= new ExpStatement(0, e
);
3980 e
= new VarExp(0, v
);
3981 e
= new NotExp(0, e
);
3982 *sfinally
= new IfStatement(0, NULL
, e
, statement
, NULL
);
3992 /******************************** ThrowStatement ***************************/
3994 ThrowStatement::ThrowStatement(Loc loc
, Expression
*exp
)
4000 Statement
*ThrowStatement::syntaxCopy()
4002 ThrowStatement
*s
= new ThrowStatement(loc
, exp
->syntaxCopy());
4006 Statement
*ThrowStatement::semantic(Scope
*sc
)
4008 //printf("ThrowStatement::semantic()\n");
4010 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
4011 fd
->hasReturnExp
|= 2;
4014 error("Throw statements cannot be in contracts");
4015 exp
= exp
->semantic(sc
);
4016 exp
= resolveProperties(sc
, exp
);
4017 if (!exp
->type
->toBasetype()->isClassHandle())
4018 error("can only throw class objects, not type %s", exp
->type
->toChars());
4022 int ThrowStatement::blockExit()
4024 return BEthrow
; // obviously
4027 int ThrowStatement::fallOffEnd()
4032 void ThrowStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4034 buf
->printf("throw ");
4035 exp
->toCBuffer(buf
, hgs
);
4036 buf
->writeByte(';');
4040 /******************************** VolatileStatement **************************/
4042 VolatileStatement::VolatileStatement(Loc loc
, Statement
*statement
)
4045 this->statement
= statement
;
4048 Statement
*VolatileStatement::syntaxCopy()
4050 VolatileStatement
*s
= new VolatileStatement(loc
,
4051 statement
? statement
->syntaxCopy() : NULL
);
4055 Statement
*VolatileStatement::semantic(Scope
*sc
)
4058 statement
= statement
->semantic(sc
);
4062 Statements
*VolatileStatement::flatten(Scope
*sc
)
4066 a
= statement
? statement
->flatten(sc
) : NULL
;
4068 { for (int i
= 0; i
< a
->dim
; i
++)
4069 { Statement
*s
= (Statement
*)a
->data
[i
];
4071 s
= new VolatileStatement(loc
, s
);
4079 int VolatileStatement::blockExit()
4081 return statement
? statement
->blockExit() : BEfallthru
;
4084 int VolatileStatement::fallOffEnd()
4086 return statement
? statement
->fallOffEnd() : TRUE
;
4089 void VolatileStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4091 buf
->writestring("volatile");
4093 { if (statement
->isScopeStatement())
4096 buf
->writebyte(' ');
4097 statement
->toCBuffer(buf
, hgs
);
4102 /******************************** GotoStatement ***************************/
4104 GotoStatement::GotoStatement(Loc loc
, Identifier
*ident
)
4107 this->ident
= ident
;
4112 Statement
*GotoStatement::syntaxCopy()
4114 GotoStatement
*s
= new GotoStatement(loc
, ident
);
4118 Statement
*GotoStatement::semantic(Scope
*sc
)
4119 { FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
4121 //printf("GotoStatement::semantic()\n");
4123 label
= fd
->searchLabel(ident
);
4124 if (!label
->statement
&& sc
->fes
)
4126 /* Either the goto label is forward referenced or it
4127 * is in the function that the enclosing foreach is in.
4128 * Can't know yet, so wrap the goto in a compound statement
4129 * so we can patch it later, and add it to a 'look at this later'
4132 Statements
*a
= new Statements();
4136 s
= new CompoundStatement(loc
, a
);
4137 sc
->fes
->gotos
.push(s
); // 'look at this later' list
4140 if (label
->statement
&& label
->statement
->tf
!= sc
->tf
)
4141 error("cannot goto in or out of finally block");
4145 int GotoStatement::blockExit()
4147 //printf("GotoStatement::blockExit(%p)\n", this);
4151 int GotoStatement::fallOffEnd()
4156 void GotoStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4158 buf
->writestring("goto ");
4159 buf
->writestring(ident
->toChars());
4160 buf
->writebyte(';');
4164 /******************************** LabelStatement ***************************/
4166 LabelStatement::LabelStatement(Loc loc
, Identifier
*ident
, Statement
*statement
)
4169 this->ident
= ident
;
4170 this->statement
= statement
;
4172 this->lblock
= NULL
;
4173 this->isReturnLabel
= 0;
4176 Statement
*LabelStatement::syntaxCopy()
4178 LabelStatement
*s
= new LabelStatement(loc
, ident
, statement
->syntaxCopy());
4182 Statement
*LabelStatement::semantic(Scope
*sc
)
4184 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
4186 //printf("LabelStatement::semantic()\n");
4187 ls
= fd
->searchLabel(ident
);
4189 error("Label '%s' already defined", ls
->toChars());
4191 ls
->statement
= this;
4194 sc
->scopesym
= sc
->enclosing
->scopesym
;
4195 sc
->callSuper
|= CSXlabel
;
4198 statement
= statement
->semantic(sc
);
4203 Statements
*LabelStatement::flatten(Scope
*sc
)
4205 Statements
*a
= NULL
;
4209 a
= statement
->flatten(sc
);
4214 a
->push(new ExpStatement(loc
, NULL
));
4216 Statement
*s
= (Statement
*)a
->data
[0];
4218 s
= new LabelStatement(loc
, ident
, s
);
4227 int LabelStatement::usesEH()
4229 return statement
? statement
->usesEH() : FALSE
;
4232 int LabelStatement::blockExit()
4234 //printf("LabelStatement::blockExit(%p)\n", this);
4235 return statement
? statement
->blockExit() : BEfallthru
;
4238 int LabelStatement::fallOffEnd()
4240 return statement
? statement
->fallOffEnd() : TRUE
;
4243 int LabelStatement::comeFrom()
4245 //printf("LabelStatement::comeFrom()\n");
4249 void LabelStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4251 buf
->writestring(ident
->toChars());
4252 buf
->writebyte(':');
4255 statement
->toCBuffer(buf
, hgs
);
4259 /******************************** LabelDsymbol ***************************/
4261 LabelDsymbol::LabelDsymbol(Identifier
*ident
)
4270 LabelDsymbol
*LabelDsymbol::isLabel() // is this a LabelDsymbol()?