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
, Scope
*sc
) {
360 Expressions
*args
= new Expressions();
362 // Collect all the objects we need for the constructor's arguments
363 for (int i
= 0; i
< arguments
->dim
; i
++) {
364 Argument
*arg
= (Argument
*) arguments
->data
[i
];
365 if (arg
->ident
== Id::args
) {
366 // For 'args', just pass through the string[] passed to main()
367 args
->push(new IdentifierExp(loc
, arg
->ident
));
369 // For everything else, call a getter in a dlt._externals.type module
370 Type
*type
= arg
->type
->semantic(loc
, sc
);
371 char* typeStr
= strdup(type
->toChars());
373 char* typeName
= strrchr(typeStr
, '.');
374 if (typeName
== NULL
) {
375 error("Expected '.' in main-injected type %s", typeName
);
381 Array
*dlt_package
= new Array();
382 dlt_package
->push(Id::_externals
);
384 Expression
*getter
= new IdentifierExp(loc
, Id::_externals
);
385 while (char *p
= strchr(typeStr
, '.')) {
387 Identifier
* component
= new Identifier(typeStr
, TOKidentifier
);
388 dlt_package
->push(component
);
389 getter
= new DotIdExp(loc
, getter
, component
);
392 Identifier
* component
= new Identifier(typeStr
, TOKidentifier
);
393 getter
= new DotIdExp(loc
, getter
, component
);
394 getter
= new DotIdExp(loc
, getter
, arg
->ident
);
396 Import
*im
= new Import(loc
, dlt_package
, component
, NULL
, true);
397 sc
->module
->members
->shift(im
);
398 im
->addMember(NULL
, sc
->scopesym
, 1);
403 OutBuffer *buf = new OutBuffer();
404 im->toCBuffer(buf, &hgs);
405 fprintf(stderr, "i: %s\n", buf->toChars());
408 getter
= new CallExp(loc
, getter
);
410 //fprintf(stderr, "e: %s\n", getter->toChars());
411 //fprintf(stderr, "type: %s\n", getter->type->toChars());
420 InjectorMainBody::InjectorMainBody(Loc loc
, ClassDeclaration
*mainClass
)
421 : Statement(loc
), mainClass(mainClass
)
425 Statement
*InjectorMainBody::semantic(Scope
*sc
)
427 // Find the constructor and the main method
428 CtorDeclaration
*ctor
= NULL
;
429 FuncDeclaration
*mainDecl
= NULL
;
430 for (int i
= 0; i
< mainClass
->members
->dim
; i
++) {
433 s
= (Dsymbol
*)mainClass
->members
->data
[i
];
435 CtorDeclaration
*thisCtor
= s
->isCtorDeclaration();
438 error("Multiple constructors for Main class!");
445 FuncDeclaration
*thisMethod
= s
->isFuncDeclaration();
446 if (thisMethod
&& thisMethod
->ident
== Id::main
) {
448 error("Multiple main methods for Main class!");
451 mainDecl
= thisMethod
;
456 if (mainDecl
== NULL
) {
457 error("No main method in Main class!");
461 Expression
*newMain
= new NewExp(loc
, NULL
, NULL
, mainClass
->getType(),
462 ctor
? getAutoArgs(ctor
->loc
, ctor
->arguments
, sc
) : NULL
);
464 // Then invoke the main() method inside it
465 // mainObject.main(...)
466 Expression
*mainMethod
= new DotIdExp(mainDecl
->loc
, newMain
, Id::main
);
467 Expression
*mainCall
= new CallExp(mainMethod
->loc
, mainMethod
,
468 getAutoArgs(mainDecl
->loc
,
469 ((TypeFunction
*) mainDecl
->type
)->parameters
,
472 Statement
*body
= new ExpStatement(loc
, mainCall
);
474 return body
->semantic(sc
);
477 /******************************** CompoundStatement ***************************/
479 CompoundStatement::CompoundStatement(Loc loc
, Statements
*s
)
485 CompoundStatement::CompoundStatement(Loc loc
, Statement
*s1
, Statement
*s2
)
488 statements
= new Statements();
489 statements
->reserve(2);
490 statements
->push(s1
);
491 statements
->push(s2
);
494 Statement
*CompoundStatement::syntaxCopy()
496 Statements
*a
= new Statements();
497 a
->setDim(statements
->dim
);
498 for (size_t i
= 0; i
< statements
->dim
; i
++)
499 { Statement
*s
= (Statement
*)statements
->data
[i
];
504 CompoundStatement
*cs
= new CompoundStatement(loc
, a
);
509 Statement
*CompoundStatement::semantic(Scope
*sc
)
512 //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", this, sc);
514 for (size_t i
= 0; i
< statements
->dim
; )
516 s
= (Statement
*) statements
->data
[i
];
518 { Statements
*a
= s
->flatten(sc
);
522 statements
->remove(i
);
523 statements
->insert(i
, a
);
527 statements
->data
[i
] = s
;
531 Statement
*sexception
;
534 s
->scopeCode(sc
, &sentry
, &sexception
, &sfinally
);
537 sentry
= sentry
->semantic(sc
);
538 statements
->data
[i
] = sentry
;
542 if (i
+ 1 == statements
->dim
&& !sfinally
)
545 sexception
= sexception
->semantic(sc
);
547 statements
->push(sexception
);
549 // Assume sexception does not throw
550 statements
->push(sfinally
);
561 * { sexception; throw __o; }
564 Statements
*a
= new Statements();
566 for (int j
= i
+ 1; j
< statements
->dim
; j
++)
568 a
->push(statements
->data
[j
]);
570 body
= new CompoundStatement(0, a
);
571 body
= new ScopeStatement(0, body
);
573 Identifier
*id
= Lexer::uniqueId("__o");
575 Statement
*handler
= new ThrowStatement(0, new IdentifierExp(0, id
));
576 handler
= new CompoundStatement(0, sexception
, handler
);
578 Array
*catches
= new Array();
579 Catch
*ctch
= new Catch(0, NULL
, id
, handler
);
581 s
= new TryCatchStatement(0, body
, catches
);
584 s
= new TryFinallyStatement(0, s
, sfinally
);
586 statements
->setDim(i
+ 1);
593 if (0 && i
+ 1 == statements
->dim
)
595 statements
->push(sfinally
);
602 * s; try { s1; s2; } finally { sfinally; }
605 Statements
*a
= new Statements();
607 for (int j
= i
+ 1; j
< statements
->dim
; j
++)
609 a
->push(statements
->data
[j
]);
611 body
= new CompoundStatement(0, a
);
612 s
= new TryFinallyStatement(0, body
, sfinally
);
614 statements
->setDim(i
+ 1);
623 if (statements
->dim
== 1)
628 Statements
*CompoundStatement::flatten(Scope
*sc
)
633 ReturnStatement
*CompoundStatement::isReturnStatement()
635 ReturnStatement
*rs
= NULL
;
637 for (i
= 0; i
< statements
->dim
; i
++)
640 s
= (Statement
*) statements
->data
[i
];
643 rs
= s
->isReturnStatement();
651 void CompoundStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
654 for (i
= 0; i
< statements
->dim
; i
++)
657 s
= (Statement
*) statements
->data
[i
];
659 s
->toCBuffer(buf
, hgs
);
663 int CompoundStatement::usesEH()
665 for (int i
= 0; i
< statements
->dim
; i
++)
668 s
= (Statement
*) statements
->data
[i
];
669 if (s
&& s
->usesEH())
675 int CompoundStatement::blockExit()
677 //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim);
678 int result
= BEfallthru
;
679 for (size_t i
= 0; i
< statements
->dim
; i
++)
680 { Statement
*s
= (Statement
*) statements
->data
[i
];
683 //printf("result = x%x\n", result);
684 //printf("%s\n", s->toChars());
685 if (!(result
& BEfallthru
) && !s
->comeFrom())
687 if (global
.params
.warnings
)
688 { fprintf(stdmsg
, "warning - ");
689 s
->error("statement is not reachable");
693 result
&= ~BEfallthru
;
694 result
|= s
->blockExit();
700 int CompoundStatement::fallOffEnd()
701 { int falloff
= TRUE
;
703 //printf("CompoundStatement::fallOffEnd()\n");
704 for (int i
= 0; i
< statements
->dim
; i
++)
705 { Statement
*s
= (Statement
*)statements
->data
[i
];
711 if (!falloff
&& global
.params
.warnings
&& !s
->comeFrom())
713 fprintf(stdmsg
, "warning - ");
714 s
->error("statement is not reachable");
717 falloff
= s
->fallOffEnd();
722 int CompoundStatement::comeFrom()
723 { int comefrom
= FALSE
;
725 //printf("CompoundStatement::comeFrom()\n");
726 for (int i
= 0; i
< statements
->dim
; i
++)
727 { Statement
*s
= (Statement
*)statements
->data
[i
];
732 comefrom
|= s
->comeFrom();
738 /**************************** UnrolledLoopStatement ***************************/
740 UnrolledLoopStatement::UnrolledLoopStatement(Loc loc
, Statements
*s
)
746 Statement
*UnrolledLoopStatement::syntaxCopy()
748 Statements
*a
= new Statements();
749 a
->setDim(statements
->dim
);
750 for (size_t i
= 0; i
< statements
->dim
; i
++)
751 { Statement
*s
= (Statement
*)statements
->data
[i
];
756 UnrolledLoopStatement
*cs
= new UnrolledLoopStatement(loc
, a
);
761 Statement
*UnrolledLoopStatement::semantic(Scope
*sc
)
763 //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc);
766 Scope
*scd
= sc
->push();
768 scd
->scontinue
= this;
770 for (size_t i
= 0; i
< statements
->dim
; i
++)
772 Statement
*s
= (Statement
*) statements
->data
[i
];
775 s
= s
->semantic(scd
);
776 statements
->data
[i
] = s
;
785 void UnrolledLoopStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
787 buf
->writestring("unrolled {");
790 for (size_t i
= 0; i
< statements
->dim
; i
++)
793 s
= (Statement
*) statements
->data
[i
];
795 s
->toCBuffer(buf
, hgs
);
802 int UnrolledLoopStatement::hasBreak()
807 int UnrolledLoopStatement::hasContinue()
812 int UnrolledLoopStatement::usesEH()
814 for (size_t i
= 0; i
< statements
->dim
; i
++)
815 { Statement
*s
= (Statement
*) statements
->data
[i
];
816 if (s
&& s
->usesEH())
822 int UnrolledLoopStatement::blockExit()
824 int result
= BEfallthru
;
825 for (size_t i
= 0; i
< statements
->dim
; i
++)
826 { Statement
*s
= (Statement
*) statements
->data
[i
];
829 int r
= s
->blockExit();
830 result
|= r
& ~(BEbreak
| BEcontinue
);
836 int UnrolledLoopStatement::fallOffEnd()
838 //printf("UnrolledLoopStatement::fallOffEnd()\n");
839 for (size_t i
= 0; i
< statements
->dim
; i
++)
840 { Statement
*s
= (Statement
*)statements
->data
[i
];
848 int UnrolledLoopStatement::comeFrom()
849 { int comefrom
= FALSE
;
851 //printf("UnrolledLoopStatement::comeFrom()\n");
852 for (size_t i
= 0; i
< statements
->dim
; i
++)
853 { Statement
*s
= (Statement
*)statements
->data
[i
];
858 comefrom
|= s
->comeFrom();
864 /******************************** ScopeStatement ***************************/
866 ScopeStatement::ScopeStatement(Loc loc
, Statement
*s
)
872 Statement
*ScopeStatement::syntaxCopy()
876 s
= statement
? statement
->syntaxCopy() : NULL
;
877 s
= new ScopeStatement(loc
, s
);
882 Statement
*ScopeStatement::semantic(Scope
*sc
)
885 //printf("ScopeStatement::semantic(sc = %p)\n", sc);
889 sym
= new ScopeDsymbol();
890 sym
->parent
= sc
->scopesym
;
893 a
= statement
->flatten(sc
);
896 statement
= new CompoundStatement(loc
, a
);
899 statement
= statement
->semantic(sc
);
903 Statement
*sexception
;
906 statement
->scopeCode(sc
, &sentry
, &sexception
, &sfinally
);
909 //printf("adding sfinally\n");
910 statement
= new CompoundStatement(loc
, statement
, sfinally
);
919 int ScopeStatement::hasBreak()
921 //printf("ScopeStatement::hasBreak() %s\n", toChars());
922 return statement
? statement
->hasBreak() : FALSE
;
925 int ScopeStatement::hasContinue()
927 return statement
? statement
->hasContinue() : FALSE
;
930 int ScopeStatement::usesEH()
932 return statement
? statement
->usesEH() : FALSE
;
935 int ScopeStatement::blockExit()
937 //printf("ScopeStatement::blockExit(%p)\n", statement);
938 return statement
? statement
->blockExit() : BEfallthru
;
941 int ScopeStatement::fallOffEnd()
943 return statement
? statement
->fallOffEnd() : TRUE
;
946 int ScopeStatement::comeFrom()
948 //printf("ScopeStatement::comeFrom()\n");
949 return statement
? statement
->comeFrom() : FALSE
;
952 void ScopeStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
958 statement
->toCBuffer(buf
, hgs
);
964 /******************************** WhileStatement ***************************/
966 WhileStatement::WhileStatement(Loc loc
, Expression
*c
, Statement
*b
)
973 Statement
*WhileStatement::syntaxCopy()
975 WhileStatement
*s
= new WhileStatement(loc
, condition
->syntaxCopy(), body
? body
->syntaxCopy() : NULL
);
980 Statement
*WhileStatement::semantic(Scope
*sc
)
983 if (condition
->op
== TOKmatch
)
985 /* Rewrite while (condition) body as:
989 * while ((_match = _match.opNext), _match);
992 Expression
*ew
= new IdentifierExp(0, Id::_match
);
993 ew
= new DotIdExp(0, ew
, Id::next
);
994 ew
= new AssignExp(0, new IdentifierExp(0, Id::_match
), ew
);
995 ////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0));
996 Expression
*ev
= new IdentifierExp(0, Id::_match
);
997 //ev = new CastExp(0, ev, Type::tvoidptr);
998 ew
= new CommaExp(0, ew
, ev
);
999 Statement
*sw
= new DoStatement(loc
, body
, ew
);
1000 Statement
*si
= new IfStatement(loc
, condition
, sw
, NULL
);
1001 return si
->semantic(sc
);
1005 condition
= condition
->semantic(sc
);
1006 condition
= resolveProperties(sc
, condition
);
1007 condition
= condition
->optimize(WANTvalue
);
1008 condition
= condition
->checkToBoolean();
1012 Scope
*scd
= sc
->push();
1014 scd
->scontinue
= this;
1016 body
= body
->semantic(scd
);
1024 int WhileStatement::hasBreak()
1029 int WhileStatement::hasContinue()
1034 int WhileStatement::usesEH()
1036 return body
? body
->usesEH() : 0;
1039 int WhileStatement::blockExit()
1041 //printf("WhileStatement::blockExit(%p)\n", this);
1043 int result
= BEnone
;
1044 if (condition
->canThrow())
1047 { result
|= body
->blockExit();
1048 if (result
& BEbreak
)
1049 result
|= BEfallthru
;
1050 result
&= ~(BEbreak
| BEcontinue
);
1053 result
|= BEfallthru
;
1057 int WhileStatement::fallOffEnd()
1064 int WhileStatement::comeFrom()
1067 return body
->comeFrom();
1071 void WhileStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1073 buf
->writestring("while (");
1074 condition
->toCBuffer(buf
, hgs
);
1075 buf
->writebyte(')');
1078 body
->toCBuffer(buf
, hgs
);
1081 /******************************** DoStatement ***************************/
1083 DoStatement::DoStatement(Loc loc
, Statement
*b
, Expression
*c
)
1090 Statement
*DoStatement::syntaxCopy()
1092 DoStatement
*s
= new DoStatement(loc
, body
? body
->syntaxCopy() : NULL
, condition
->syntaxCopy());
1097 Statement
*DoStatement::semantic(Scope
*sc
)
1101 body
= body
->semanticScope(sc
, this, this);
1103 condition
= condition
->semantic(sc
);
1104 condition
= resolveProperties(sc
, condition
);
1105 condition
= condition
->optimize(WANTvalue
);
1107 condition
= condition
->checkToBoolean();
1112 int DoStatement::hasBreak()
1117 int DoStatement::hasContinue()
1122 int DoStatement::usesEH()
1124 return body
? body
->usesEH() : 0;
1127 int DoStatement::blockExit()
1131 { result
= body
->blockExit();
1132 if (result
& BEbreak
)
1134 if (result
== BEbreak
)
1136 result
|= BEfallthru
;
1138 if (result
& BEcontinue
)
1139 result
|= BEfallthru
;
1140 result
&= ~(BEbreak
| BEcontinue
);
1143 result
= BEfallthru
;
1144 if (result
& BEfallthru
&& condition
->canThrow())
1149 int DoStatement::fallOffEnd()
1156 int DoStatement::comeFrom()
1159 return body
->comeFrom();
1163 void DoStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1165 buf
->writestring("do");
1168 body
->toCBuffer(buf
, hgs
);
1169 buf
->writestring("while (");
1170 condition
->toCBuffer(buf
, hgs
);
1171 buf
->writebyte(')');
1174 /******************************** ForStatement ***************************/
1176 ForStatement::ForStatement(Loc loc
, Statement
*init
, Expression
*condition
, Expression
*increment
, Statement
*body
)
1180 this->condition
= condition
;
1181 this->increment
= increment
;
1185 Statement
*ForStatement::syntaxCopy()
1187 Statement
*i
= NULL
;
1189 i
= init
->syntaxCopy();
1190 Expression
*c
= NULL
;
1192 c
= condition
->syntaxCopy();
1193 Expression
*inc
= NULL
;
1195 inc
= increment
->syntaxCopy();
1196 ForStatement
*s
= new ForStatement(loc
, i
, c
, inc
, body
->syntaxCopy());
1200 Statement
*ForStatement::semantic(Scope
*sc
)
1202 ScopeDsymbol
*sym
= new ScopeDsymbol();
1203 sym
->parent
= sc
->scopesym
;
1206 init
= init
->semantic(sc
);
1210 condition
= condition
->semantic(sc
);
1211 condition
= resolveProperties(sc
, condition
);
1212 condition
= condition
->optimize(WANTvalue
);
1213 condition
= condition
->checkToBoolean();
1216 increment
= increment
->semantic(sc
);
1219 sc
->scontinue
= this;
1220 body
= body
->semantic(sc
);
1227 void ForStatement::scopeCode(Scope
*sc
, Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
1229 //printf("ForStatement::scopeCode()\n");
1232 init
->scopeCode(sc
, sentry
, sexception
, sfinally
);
1234 Statement::scopeCode(sc
, sentry
, sexception
, sfinally
);
1237 int ForStatement::hasBreak()
1239 //printf("ForStatement::hasBreak()\n");
1243 int ForStatement::hasContinue()
1248 int ForStatement::usesEH()
1250 return (init
&& init
->usesEH()) || body
->usesEH();
1253 int ForStatement::blockExit()
1254 { int result
= BEfallthru
;
1257 { result
= init
->blockExit();
1258 if (!(result
& BEfallthru
))
1262 { if (condition
->canThrow())
1266 result
&= ~BEfallthru
; // the body must do the exiting
1268 { int r
= body
->blockExit();
1270 result
|= BEfallthru
;
1271 result
|= r
& ~(BEbreak
| BEcontinue
);
1273 if (increment
&& increment
->canThrow())
1278 int ForStatement::fallOffEnd()
1285 int ForStatement::comeFrom()
1287 //printf("ForStatement::comeFrom()\n");
1289 { int result
= body
->comeFrom();
1290 //printf("result = %d\n", result);
1296 void ForStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1298 buf
->writestring("for (");
1302 hgs
->FLinit
.decl
= 0;
1303 init
->toCBuffer(buf
, hgs
);
1304 if (hgs
->FLinit
.decl
> 0)
1305 buf
->writebyte(';');
1306 hgs
->FLinit
.decl
= 0;
1310 buf
->writebyte(';');
1312 { buf
->writebyte(' ');
1313 condition
->toCBuffer(buf
, hgs
);
1315 buf
->writebyte(';');
1317 { buf
->writebyte(' ');
1318 increment
->toCBuffer(buf
, hgs
);
1320 buf
->writebyte(')');
1322 buf
->writebyte('{');
1324 body
->toCBuffer(buf
, hgs
);
1325 buf
->writebyte('}');
1329 /******************************** ForeachStatement ***************************/
1331 ForeachStatement::ForeachStatement(Loc loc
, enum TOK op
, Arguments
*arguments
,
1332 Expression
*aggr
, Statement
*body
)
1336 this->arguments
= arguments
;
1346 Statement
*ForeachStatement::syntaxCopy()
1348 Arguments
*args
= Argument::arraySyntaxCopy(arguments
);
1349 Expression
*exp
= aggr
->syntaxCopy();
1350 ForeachStatement
*s
= new ForeachStatement(loc
, op
, args
, exp
,
1351 body
? body
->syntaxCopy() : NULL
);
1355 Statement
*ForeachStatement::semantic(Scope
*sc
)
1357 //printf("ForeachStatement::semantic() %p\n", this);
1359 Statement
*s
= this;
1360 int dim
= arguments
->dim
;
1362 TypeAArray
*taa
= NULL
;
1369 func
= func
->fes
->func
;
1371 aggr
= aggr
->semantic(sc
);
1372 aggr
= resolveProperties(sc
, aggr
);
1373 aggr
= aggr
->optimize(WANTvalue
);
1376 error("invalid foreach aggregate %s", aggr
->toChars());
1380 inferApplyArgTypes(op
, arguments
, aggr
);
1382 /* Check for inference errors
1384 if (dim
!= arguments
->dim
)
1386 //printf("dim = %d, arguments->dim = %d\n", dim, arguments->dim);
1387 error("cannot uniquely infer foreach argument types");
1391 Type
*tab
= aggr
->type
->toBasetype();
1393 if (tab
->ty
== Ttuple
) // don't generate new scope for tuple loops
1395 if (dim
< 1 || dim
> 2)
1397 error("only one (value) or two (key,value) arguments for tuple foreach");
1401 TypeTuple
*tuple
= (TypeTuple
*)tab
;
1402 Statements
*statements
= new Statements();
1403 //printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars());
1405 TupleExp
*te
= NULL
;
1406 if (aggr
->op
== TOKtuple
) // expression tuple
1407 { te
= (TupleExp
*)aggr
;
1410 else if (aggr
->op
== TOKtype
) // type tuple
1412 n
= Argument::dim(tuple
->arguments
);
1416 for (size_t j
= 0; j
< n
; j
++)
1417 { size_t k
= (op
== TOKforeach
) ? j
: n
- 1 - j
;
1421 e
= (Expression
*)te
->exps
->data
[k
];
1423 t
= Argument::getNth(tuple
->arguments
, k
)->type
;
1424 Argument
*arg
= (Argument
*)arguments
->data
[0];
1425 Statements
*st
= new Statements();
1429 if (arg
->storageClass
& (STCout
| STCref
| STClazy
))
1430 error("no storage class for key %s", arg
->ident
->toChars());
1431 TY keyty
= arg
->type
->ty
;
1432 if ((keyty
!= Tint32
&& keyty
!= Tuns32
) &&
1433 (! global
.params
.isX86_64
||
1434 (keyty
!= Tint64
&& keyty
!= Tuns64
))
1437 error("foreach: key type must be int or uint, not %s", arg
->type
->toChars());
1439 Initializer
*ie
= new ExpInitializer(0, new IntegerExp(k
));
1440 VarDeclaration
*var
= new VarDeclaration(loc
, arg
->type
, arg
->ident
, ie
);
1441 var
->storage_class
|= STCmanifest
;
1442 DeclarationExp
*de
= new DeclarationExp(loc
, var
);
1443 st
->push(new ExpStatement(loc
, de
));
1444 arg
= (Argument
*)arguments
->data
[1]; // value
1447 if (arg
->storageClass
& (STCout
| STCref
| STClazy
))
1448 error("no storage class for value %s", arg
->ident
->toChars());
1451 { Type
*tb
= e
->type
->toBasetype();
1452 if ((tb
->ty
== Tfunction
|| tb
->ty
== Tsarray
) && e
->op
== TOKvar
)
1453 { VarExp
*ve
= (VarExp
*)e
;
1454 var
= new AliasDeclaration(loc
, arg
->ident
, ve
->var
);
1458 arg
->type
= e
->type
;
1459 Initializer
*ie
= new ExpInitializer(0, e
);
1460 VarDeclaration
*v
= new VarDeclaration(loc
, arg
->type
, arg
->ident
, ie
);
1462 v
->storage_class
|= STCconst
;
1468 var
= new AliasDeclaration(loc
, arg
->ident
, t
);
1470 DeclarationExp
*de
= new DeclarationExp(loc
, var
);
1471 st
->push(new ExpStatement(loc
, de
));
1473 st
->push(body
->syntaxCopy());
1474 s
= new CompoundStatement(loc
, st
);
1475 s
= new ScopeStatement(loc
, s
);
1476 statements
->push(s
);
1479 s
= new UnrolledLoopStatement(loc
, statements
);
1480 s
= s
->semantic(sc
);
1484 for (i
= 0; i
< dim
; i
++)
1485 { Argument
*arg
= (Argument
*)arguments
->data
[i
];
1488 error("cannot infer type for %s", arg
->ident
->toChars());
1493 sym
= new ScopeDsymbol();
1494 sym
->parent
= sc
->scopesym
;
1503 if (dim
< 1 || dim
> 2)
1505 error("only one or two arguments for array foreach");
1509 /* Look for special case of parsing char types out of char type
1512 tn
= tab
->nextOf()->toBasetype();
1513 if (tn
->ty
== Tchar
|| tn
->ty
== Twchar
|| tn
->ty
== Tdchar
)
1516 i
= (dim
== 1) ? 0 : 1; // index of value
1517 arg
= (Argument
*)arguments
->data
[i
];
1518 arg
->type
= arg
->type
->semantic(loc
, sc
);
1519 tnv
= arg
->type
->toBasetype();
1520 if (tnv
->ty
!= tn
->ty
&&
1521 (tnv
->ty
== Tchar
|| tnv
->ty
== Twchar
|| tnv
->ty
== Tdchar
))
1523 if (arg
->storageClass
& STCref
)
1524 error("foreach: value of UTF conversion cannot be ref");
1526 { arg
= (Argument
*)arguments
->data
[0];
1527 if (arg
->storageClass
& STCref
)
1528 error("foreach: key cannot be ref");
1534 for (i
= 0; i
< dim
; i
++)
1536 Argument
*arg
= (Argument
*)arguments
->data
[i
];
1537 VarDeclaration
*var
;
1539 var
= new VarDeclaration(loc
, arg
->type
, arg
->ident
, NULL
);
1540 var
->storage_class
|= STCforeach
;
1541 var
->storage_class
|= arg
->storageClass
& (STCin
| STCout
| STCref
| STCconst
| STCinvariant
);
1542 if (dim
== 2 && i
== 0)
1544 //var->storage_class |= STCfinal;
1547 { //if (!(arg->storageClass & STCref))
1548 //var->storage_class |= STCfinal;
1552 DeclarationExp
*de
= new DeclarationExp(loc
, var
);
1556 if (!sc
->insert(var
))
1557 error("%s already defined", var
->ident
->toChars());
1562 sc
->scontinue
= this;
1563 body
= body
->semantic(sc
);
1565 if (tab
->nextOf()->implicitConvTo(value
->type
) < MATCHconst
)
1567 if (aggr
->op
== TOKstring
)
1568 aggr
= aggr
->implicitCastTo(sc
, value
->type
->arrayOf());
1570 error("foreach: %s is not an array of %s",
1571 tab
->toChars(), value
->type
->toChars());
1575 ((key
->type
->ty
!= Tint32
&& key
->type
->ty
!= Tuns32
) &&
1576 (! global
.params
.isX86_64
||
1577 (key
->type
->ty
!= Tint64
&& key
->type
->ty
!= Tuns64
))
1581 error("foreach: key type must be int or uint, not %s", key
->type
->toChars());
1584 if (key
&& key
->storage_class
& (STCout
| STCref
))
1585 error("foreach: key cannot be out or ref");
1589 taa
= (TypeAArray
*)tab
;
1590 if (dim
< 1 || dim
> 2)
1592 error("only one or two arguments for associative array foreach");
1595 if (op
== TOKforeach_reverse
)
1597 error("no reverse iteration on associative arrays");
1605 { FuncDeclaration
*fdapply
;
1609 FuncLiteralDeclaration
*fld
;
1616 tret
= func
->type
->nextOf();
1618 // Need a variable to hold value from any return statements in body.
1619 if (!sc
->func
->vresult
&& tret
&& tret
!= Type::tvoid
)
1620 { VarDeclaration
*v
;
1622 v
= new VarDeclaration(loc
, tret
, Id::result
, NULL
);
1627 v
->parent
= sc
->func
;
1628 sc
->func
->vresult
= v
;
1631 /* Turn body into the function literal:
1632 * int delegate(ref T arg) { body }
1634 args
= new Arguments();
1635 for (i
= 0; i
< dim
; i
++)
1636 { Argument
*arg
= (Argument
*)arguments
->data
[i
];
1638 arg
->type
= arg
->type
->semantic(loc
, sc
);
1639 if (arg
->storageClass
& STCref
)
1642 { // Make a copy of the ref argument so it isn't
1647 id
= Lexer::uniqueId("__applyArg", i
);
1649 ie
= new ExpInitializer(0, new IdentifierExp(0, id
));
1650 v
= new VarDeclaration(0, arg
->type
, arg
->ident
, ie
);
1651 s
= new DeclarationStatement(0, v
);
1652 body
= new CompoundStatement(loc
, s
, body
);
1654 a
= new Argument(STCref
, arg
->type
, id
, NULL
);
1657 t
= new TypeFunction(args
, Type::tint32
, 0, LINKd
);
1658 fld
= new FuncLiteralDeclaration(loc
, 0, t
, TOKdelegate
, this);
1660 flde
= new FuncExp(loc
, fld
);
1661 flde
= flde
->semantic(sc
);
1662 fld
->tookAddressOf
= 0;
1664 // Resolve any forward referenced goto's
1665 for (int i
= 0; i
< gotos
.dim
; i
++)
1666 { CompoundStatement
*cs
= (CompoundStatement
*)gotos
.data
[i
];
1667 GotoStatement
*gs
= (GotoStatement
*)cs
->statements
->data
[0];
1669 if (!gs
->label
->statement
)
1670 { // 'Promote' it to this scope, and replace with a return
1672 s
= new ReturnStatement(0, new IntegerExp(cases
.dim
+ 1));
1673 cs
->statements
->data
[0] = (void *)s
;
1677 if (tab
->ty
== Taarray
)
1680 Argument
*arg
= (Argument
*)arguments
->data
[0];
1683 if (arg
->storageClass
& STCref
)
1684 error("foreach: index cannot be ref");
1685 if (!arg
->type
->equals(taa
->index
))
1686 error("foreach: index must be type %s, not %s", taa
->index
->toChars(), arg
->type
->toChars());
1687 arg
= (Argument
*)arguments
->data
[1];
1689 if (!arg
->type
->equals(taa
->nextOf()))
1690 error("foreach: value must be type %s, not %s", taa
->nextOf()->toChars(), arg
->type
->toChars());
1693 * _aaApply(aggr, keysize, flde)
1696 fdapply
= FuncDeclaration::genCfunc(Type::tint32
, "_aaApply2",
1697 Type::tvoid
->arrayOf(), Type::tsize_t
, flde
->type
); // flde->type is not generic
1699 fdapply
= FuncDeclaration::genCfunc(Type::tint32
, "_aaApply",
1700 Type::tvoid
->arrayOf(), Type::tsize_t
, flde
->type
); // flde->type is not generic);
1701 ec
= new VarExp(0, fdapply
);
1702 Expressions
*exps
= new Expressions();
1704 size_t keysize
= taa
->index
->size();
1705 keysize
= (keysize
+ (PTRSIZE
-1)) & ~(PTRSIZE
-1);
1706 exps
->push(new IntegerExp(0, keysize
, Type::tsize_t
));
1708 e
= new CallExp(loc
, ec
, exps
);
1709 e
->type
= Type::tint32
; // don't run semantic() on e
1711 else if (tab
->ty
== Tarray
|| tab
->ty
== Tsarray
)
1714 * _aApply(aggr, flde)
1716 static char fntab
[9][3] =
1721 char fdname
[7+1+2+ sizeof(dim
)*3 + 1];
1726 case Tchar
: flag
= 0; break;
1727 case Twchar
: flag
= 3; break;
1728 case Tdchar
: flag
= 6; break;
1733 case Tchar
: flag
+= 0; break;
1734 case Twchar
: flag
+= 1; break;
1735 case Tdchar
: flag
+= 2; break;
1738 const char *r
= (op
== TOKforeach_reverse
) ? "R" : "";
1739 int j
= sprintf(fdname
, "_aApply%s%.*s%d", r
, 2, fntab
[flag
], dim
);
1740 assert(j
< sizeof(fdname
));
1741 fdapply
= FuncDeclaration::genCfunc(Type::tint32
, fdname
,
1742 Type::tvoid
->arrayOf(), flde
->type
); // flde->type is not generic
1744 ec
= new VarExp(0, fdapply
);
1745 Expressions
*exps
= new Expressions();
1746 if (tab
->ty
== Tsarray
)
1747 aggr
= aggr
->castTo(sc
, tn
->arrayOf());
1750 e
= new CallExp(loc
, ec
, exps
);
1751 e
->type
= Type::tint32
; // don't run semantic() on e
1753 else if (tab
->ty
== Tdelegate
)
1758 Expressions
*exps
= new Expressions();
1760 e
= new CallExp(loc
, aggr
, exps
);
1761 e
= e
->semantic(sc
);
1762 if (e
->type
!= Type::tint32
)
1763 error("opApply() function for %s must return an int", tab
->toChars());
1770 ec
= new DotIdExp(loc
, aggr
,
1771 (op
== TOKforeach_reverse
) ? Id::applyReverse
1773 Expressions
*exps
= new Expressions();
1775 e
= new CallExp(loc
, ec
, exps
);
1776 e
= e
->semantic(sc
);
1777 if (e
->type
!= Type::tint32
)
1778 error("opApply() function for %s must return an int", tab
->toChars());
1782 // Easy case, a clean exit from the loop
1783 s
= new ExpStatement(loc
, e
);
1785 { // Construct a switch statement around the return value
1786 // of the apply function.
1787 Statements
*a
= new Statements();
1789 // default: break; takes care of cases 0 and 1
1790 s
= new BreakStatement(0, NULL
);
1791 s
= new DefaultStatement(0, s
);
1795 for (int i
= 0; i
< cases
.dim
; i
++)
1797 s
= (Statement
*)cases
.data
[i
];
1798 s
= new CaseStatement(0, new IntegerExp(i
+ 2), s
);
1802 s
= new CompoundStatement(loc
, a
);
1803 s
= new SwitchStatement(loc
, e
, s
);
1804 s
= s
->semantic(sc
);
1810 error("foreach: %s is not an aggregate type", aggr
->type
->toChars());
1818 int ForeachStatement::hasBreak()
1823 int ForeachStatement::hasContinue()
1828 int ForeachStatement::usesEH()
1830 return body
->usesEH();
1833 int ForeachStatement::blockExit()
1834 { int result
= BEfallthru
;
1836 if (aggr
->canThrow())
1841 result
|= body
->blockExit() & ~(BEbreak
| BEcontinue
);
1846 int ForeachStatement::fallOffEnd()
1853 int ForeachStatement::comeFrom()
1856 return body
->comeFrom();
1860 void ForeachStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1862 buf
->writestring(Token::toChars(op
));
1863 buf
->writestring(" (");
1864 for (int i
= 0; i
< arguments
->dim
; i
++)
1866 Argument
*a
= (Argument
*)arguments
->data
[i
];
1868 buf
->writestring(", ");
1869 if (a
->storageClass
& STCref
)
1870 buf
->writestring((global
.params
.Dversion
== 1)
1871 ? (char*)"inout " : (char*)"ref ");
1873 a
->type
->toCBuffer(buf
, a
->ident
, hgs
);
1875 buf
->writestring(a
->ident
->toChars());
1877 buf
->writestring("; ");
1878 aggr
->toCBuffer(buf
, hgs
);
1879 buf
->writebyte(')');
1881 buf
->writebyte('{');
1884 body
->toCBuffer(buf
, hgs
);
1885 buf
->writebyte('}');
1889 /**************************** ForeachRangeStatement ***************************/
1891 ForeachRangeStatement::ForeachRangeStatement(Loc loc
, enum TOK op
, Argument
*arg
,
1892 Expression
*lwr
, Expression
*upr
, Statement
*body
)
1904 Statement
*ForeachRangeStatement::syntaxCopy()
1906 ForeachRangeStatement
*s
= new ForeachRangeStatement(loc
, op
,
1910 body
? body
->syntaxCopy() : NULL
);
1914 Statement
*ForeachRangeStatement::semantic(Scope
*sc
)
1916 //printf("ForeachRangeStatement::semantic() %p\n", this);
1918 Statement
*s
= this;
1920 lwr
= lwr
->semantic(sc
);
1921 lwr
= resolveProperties(sc
, lwr
);
1922 lwr
= lwr
->optimize(WANTvalue
);
1925 error("invalid range lower bound %s", lwr
->toChars());
1929 upr
= upr
->semantic(sc
);
1930 upr
= resolveProperties(sc
, upr
);
1931 upr
= upr
->optimize(WANTvalue
);
1934 error("invalid range upper bound %s", upr
->toChars());
1940 lwr
= lwr
->implicitCastTo(sc
, arg
->type
);
1941 upr
= upr
->implicitCastTo(sc
, arg
->type
);
1945 /* Must infer types from lwr and upr
1947 AddExp
ea(loc
, lwr
, upr
);
1949 arg
->type
= ea
.type
;
1953 if (!arg
->type
->isscalar())
1954 error("%s is not a scalar type", arg
->type
->toChars());
1956 sym
= new ScopeDsymbol();
1957 sym
->parent
= sc
->scopesym
;
1962 key
= new VarDeclaration(loc
, arg
->type
, arg
->ident
, NULL
);
1963 DeclarationExp
*de
= new DeclarationExp(loc
, key
);
1966 if (key
->storage_class
)
1967 error("foreach range: key cannot have storage class");
1970 sc
->scontinue
= this;
1971 body
= body
->semantic(sc
);
1978 int ForeachRangeStatement::hasBreak()
1983 int ForeachRangeStatement::hasContinue()
1988 int ForeachRangeStatement::usesEH()
1990 return body
->usesEH();
1993 int ForeachRangeStatement::blockExit()
1994 { int result
= BEfallthru
;
1996 if (lwr
&& lwr
->canThrow())
1998 else if (upr
&& upr
->canThrow())
2003 result
|= body
->blockExit() & ~(BEbreak
| BEcontinue
);
2008 int ForeachRangeStatement::fallOffEnd()
2015 int ForeachRangeStatement::comeFrom()
2018 return body
->comeFrom();
2022 void ForeachRangeStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2024 buf
->writestring(Token::toChars(op
));
2025 buf
->writestring(" (");
2028 arg
->type
->toCBuffer(buf
, arg
->ident
, hgs
);
2030 buf
->writestring(arg
->ident
->toChars());
2032 buf
->writestring("; ");
2033 lwr
->toCBuffer(buf
, hgs
);
2034 buf
->writestring(" .. ");
2035 upr
->toCBuffer(buf
, hgs
);
2036 buf
->writebyte(')');
2038 buf
->writebyte('{');
2041 body
->toCBuffer(buf
, hgs
);
2042 buf
->writebyte('}');
2046 /******************************** IfStatement ***************************/
2048 IfStatement::IfStatement(Loc loc
, Argument
*arg
, Expression
*condition
, Statement
*ifbody
, Statement
*elsebody
)
2052 this->condition
= condition
;
2053 this->ifbody
= ifbody
;
2054 this->elsebody
= elsebody
;
2058 Statement
*IfStatement::syntaxCopy()
2060 Statement
*i
= NULL
;
2062 i
= ifbody
->syntaxCopy();
2064 Statement
*e
= NULL
;
2066 e
= elsebody
->syntaxCopy();
2068 Argument
*a
= arg
? arg
->syntaxCopy() : NULL
;
2069 IfStatement
*s
= new IfStatement(loc
, a
, condition
->syntaxCopy(), i
, e
);
2073 Statement
*IfStatement::semantic(Scope
*sc
)
2075 condition
= condition
->semantic(sc
);
2076 condition
= resolveProperties(sc
, condition
);
2077 condition
= condition
->checkToBoolean();
2079 // If we can short-circuit evaluate the if statement, don't do the
2080 // semantic analysis of the skipped code.
2081 // This feature allows a limited form of conditional compilation.
2082 condition
= condition
->optimize(WANTflags
);
2084 // Evaluate at runtime
2085 unsigned cs0
= sc
->callSuper
;
2090 { /* Declare arg, which we will set to be the
2091 * result of condition.
2093 ScopeDsymbol
*sym
= new ScopeDsymbol();
2094 sym
->parent
= sc
->scopesym
;
2095 scd
= sc
->push(sym
);
2097 Type
*t
= arg
->type
? arg
->type
: condition
->type
;
2098 match
= new VarDeclaration(loc
, t
->maybe(true), arg
->ident
, NULL
);
2100 match
->semantic(scd
);
2101 if (!scd
->insert(match
))
2103 match
->parent
= sc
->func
;
2108 VarExp
*v
= new VarExp(0, match
);
2109 condition
= new AssignExp(loc
, v
, condition
);
2110 condition
= condition
->semantic(scd
);
2112 if (match
&& match
->type
->ty
== Tmaybe
)
2114 // Matched object cannot be null in the then block
2115 // (and isn't in scope in the else)
2116 match
->type
= match
->type
->nextOf();
2121 ifbody
= ifbody
->semantic(scd
);
2124 cs1
= sc
->callSuper
;
2125 sc
->callSuper
= cs0
;
2127 elsebody
= elsebody
->semanticScope(sc
, NULL
, NULL
);
2128 sc
->mergeCallSuper(loc
, cs1
);
2133 int IfStatement::usesEH()
2135 return (ifbody
&& ifbody
->usesEH()) || (elsebody
&& elsebody
->usesEH());
2138 int IfStatement::blockExit()
2140 //printf("IfStatement::blockExit(%p)\n", this);
2142 int result
= BEnone
;
2143 if (condition
->canThrow())
2146 result
|= ifbody
->blockExit();
2148 result
|= BEfallthru
;
2150 result
|= elsebody
->blockExit();
2152 result
|= BEfallthru
;
2153 //printf("IfStatement::blockExit(%p) = x%x\n", this, result);
2157 int IfStatement::fallOffEnd()
2159 if (!ifbody
|| ifbody
->fallOffEnd() ||
2160 !elsebody
|| elsebody
->fallOffEnd())
2166 void IfStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2168 buf
->writestring("if (");
2172 arg
->type
->toCBuffer(buf
, arg
->ident
, hgs
);
2174 buf
->writestring(arg
->ident
->toChars());
2175 buf
->writebyte(';');
2177 condition
->toCBuffer(buf
, hgs
);
2178 buf
->writebyte(')');
2180 ifbody
->toCBuffer(buf
, hgs
);
2182 { buf
->writestring("else");
2184 elsebody
->toCBuffer(buf
, hgs
);
2188 /******************************** ConditionalStatement ***************************/
2190 ConditionalStatement::ConditionalStatement(Loc loc
, Condition
*condition
, Statement
*ifbody
, Statement
*elsebody
)
2193 this->condition
= condition
;
2194 this->ifbody
= ifbody
;
2195 this->elsebody
= elsebody
;
2198 Statement
*ConditionalStatement::syntaxCopy()
2200 Statement
*e
= NULL
;
2202 e
= elsebody
->syntaxCopy();
2203 ConditionalStatement
*s
= new ConditionalStatement(loc
,
2204 condition
->syntaxCopy(), ifbody
->syntaxCopy(), e
);
2208 Statement
*ConditionalStatement::semantic(Scope
*sc
)
2210 //printf("ConditionalStatement::semantic()\n");
2212 // If we can short-circuit evaluate the if statement, don't do the
2213 // semantic analysis of the skipped code.
2214 // This feature allows a limited form of conditional compilation.
2215 if (condition
->include(sc
, NULL
))
2217 ifbody
= ifbody
->semantic(sc
);
2223 elsebody
= elsebody
->semantic(sc
);
2228 Statements
*ConditionalStatement::flatten(Scope
*sc
)
2232 if (condition
->include(sc
, NULL
))
2237 Statements
*a
= new Statements();
2242 int ConditionalStatement::usesEH()
2244 return (ifbody
&& ifbody
->usesEH()) || (elsebody
&& elsebody
->usesEH());
2247 void ConditionalStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2249 condition
->toCBuffer(buf
, hgs
);
2252 ifbody
->toCBuffer(buf
, hgs
);
2255 buf
->writestring("else");
2257 elsebody
->toCBuffer(buf
, hgs
);
2263 /******************************** PragmaStatement ***************************/
2265 PragmaStatement::PragmaStatement(Loc loc
, Identifier
*ident
, Expressions
*args
, Statement
*body
)
2268 this->ident
= ident
;
2273 Statement
*PragmaStatement::syntaxCopy()
2275 Statement
*b
= NULL
;
2277 b
= body
->syntaxCopy();
2278 PragmaStatement
*s
= new PragmaStatement(loc
,
2279 ident
, Expression::arraySyntaxCopy(args
), b
);
2283 Statement
*PragmaStatement::semantic(Scope
*sc
)
2284 { // Should be merged with PragmaDeclaration
2285 //printf("PragmaStatement::semantic() %s\n", toChars());
2286 //printf("body = %p\n", body);
2287 if (ident
== Id::msg
)
2291 for (size_t i
= 0; i
< args
->dim
; i
++)
2293 Expression
*e
= (Expression
*)args
->data
[i
];
2295 e
= e
->semantic(sc
);
2296 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2297 if (e
->op
== TOKstring
)
2299 StringExp
*se
= (StringExp
*)e
;
2300 fprintf(stdmsg
, "%.*s", (int)se
->len
, se
->string
);
2303 error("string expected for message, not '%s'", e
->toChars());
2305 fprintf(stdmsg
, "\n");
2308 else if (ident
== Id::lib
)
2310 if (!args
|| args
->dim
!= 1)
2311 error("string expected for library name");
2314 Expression
*e
= (Expression
*)args
->data
[0];
2316 e
= e
->semantic(sc
);
2317 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2318 args
->data
[0] = (void *)e
;
2319 if (e
->op
!= TOKstring
)
2320 error("string expected for library name, not '%s'", e
->toChars());
2321 else if (global
.params
.verbose
)
2323 StringExp
*se
= (StringExp
*)e
;
2324 char *name
= (char *)mem
.malloc(se
->len
+ 1);
2325 memcpy(name
, se
->string
, se
->len
);
2327 printf("library %s\n", name
);
2332 else if (ident
== Id::startaddress
)
2334 if (!args
|| args
->dim
!= 1)
2335 error("function name expected for start address");
2338 Expression
*e
= (Expression
*)args
->data
[0];
2339 e
= e
->semantic(sc
);
2340 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2341 args
->data
[0] = (void *)e
;
2342 Dsymbol
*sa
= getDsymbol(e
);
2343 if (!sa
|| !sa
->isFuncDeclaration())
2344 error("function name expected for start address, not '%s'", e
->toChars());
2347 body
= body
->semantic(sc
);
2353 error("unrecognized pragma(%s)", ident
->toChars());
2357 body
= body
->semantic(sc
);
2362 int PragmaStatement::usesEH()
2364 return body
&& body
->usesEH();
2367 int PragmaStatement::blockExit()
2369 int result
= BEfallthru
;
2370 #if 0 // currently, no code is generated for Pragma's, so it's just fallthru
2371 if (arrayExpressionCanThrow(args
))
2374 result
|= body
->blockExit();
2379 int PragmaStatement::fallOffEnd()
2382 return body
->fallOffEnd();
2386 void PragmaStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2388 buf
->writestring("pragma (");
2389 buf
->writestring(ident
->toChars());
2390 if (args
&& args
->dim
)
2392 buf
->writestring(", ");
2393 argsToCBuffer(buf
, args
, hgs
);
2395 buf
->writeByte(')');
2399 buf
->writeByte('{');
2402 body
->toCBuffer(buf
, hgs
);
2404 buf
->writeByte('}');
2409 buf
->writeByte(';');
2415 /******************************** LogStatement ***************************/
2417 LogStatement::LogStatement(Loc loc
, int level
, Expressions
*args
)
2420 this->level
= level
;
2424 Statement
*LogStatement::syntaxCopy()
2426 Expressions
*copied_args
= Expression::arraySyntaxCopy(args
);
2427 LogStatement
*s
= new LogStatement(loc
, level
, copied_args
);
2431 Statement
*LogStatement::semantic(Scope
*sc
)
2433 Expression
*logger
= new GetLoggerExp(loc
);
2436 for (Dsymbol
*s
= sc
->parent
; s
; s
= s
->parent
)
2438 ClassDeclaration
*cd
;
2439 StructDeclaration
*sd
;
2441 cd
= s
->isClassDeclaration();
2450 // We're a top-level function. Generate log messages from the module
2451 args
->shift(new StringExp(loc
, strdup(sc
->module
->ident
->string
)));
2453 args
->shift(new StringExp(loc
, type
->toChars()));
2456 args
->shift(new IntegerExp(loc
, level
, Type::tint32
));
2457 Expression
*callLogger
= new CallExp(loc
, logger
, args
);
2459 Statement
*s
= new ExpStatement(loc
, callLogger
);
2461 return s
->semantic(sc
);
2464 void LogStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2468 case 0: l
= "log_debug"; break;
2469 case 1: l
= "log_info"; break;
2470 case 2: l
= "log_warning"; break;
2471 case 3: l
= "log_error"; break;
2473 error("Unknown log level %d", level
);
2476 buf
->writestring(l
);
2477 buf
->writeByte('(');
2478 argsToCBuffer(buf
, args
, hgs
);
2479 buf
->writeByte(')');
2483 /******************************** StaticAssertStatement ***************************/
2485 StaticAssertStatement::StaticAssertStatement(StaticAssert
*sa
)
2486 : Statement(sa
->loc
)
2491 Statement
*StaticAssertStatement::syntaxCopy()
2493 StaticAssertStatement
*s
= new StaticAssertStatement((StaticAssert
*)sa
->syntaxCopy(NULL
));
2497 Statement
*StaticAssertStatement::semantic(Scope
*sc
)
2503 void StaticAssertStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2505 sa
->toCBuffer(buf
, hgs
);
2509 /******************************** SwitchStatement ***************************/
2511 SwitchStatement::SwitchStatement(Loc loc
, Expression
*c
, Statement
*b
)
2523 Statement
*SwitchStatement::syntaxCopy()
2525 SwitchStatement
*s
= new SwitchStatement(loc
,
2526 condition
->syntaxCopy(), body
->syntaxCopy());
2530 Statement
*SwitchStatement::semantic(Scope
*sc
)
2532 //printf("SwitchStatement::semantic(%p)\n", this);
2534 assert(!cases
); // ensure semantic() is only run once
2535 condition
= condition
->semantic(sc
);
2536 condition
= resolveProperties(sc
, condition
);
2537 if (condition
->type
->isString())
2539 // If it's not an array, cast it to one
2540 if (condition
->type
->ty
!= Tarray
)
2542 condition
= condition
->implicitCastTo(sc
, condition
->type
->nextOf()->arrayOf());
2544 condition
->type
= condition
->type
->constOf();
2547 { condition
= condition
->integralPromotions(sc
);
2548 condition
->checkIntegral();
2550 condition
= condition
->optimize(WANTvalue
);
2556 cases
= new Array();
2557 sc
->noctor
++; // BUG: should use Scope::mergeCallSuper() for each case instead
2558 body
= body
->semantic(sc
);
2561 // Resolve any goto case's with exp
2562 for (int i
= 0; i
< gotoCases
.dim
; i
++)
2564 GotoCaseStatement
*gcs
= (GotoCaseStatement
*)gotoCases
.data
[i
];
2568 gcs
->error("no case statement following goto case;");
2572 for (Scope
*scx
= sc
; scx
; scx
= scx
->enclosing
)
2576 for (int j
= 0; j
< scx
->sw
->cases
->dim
; j
++)
2578 CaseStatement
*cs
= (CaseStatement
*)scx
->sw
->cases
->data
[j
];
2580 if (cs
->exp
->equals(gcs
->exp
))
2587 gcs
->error("case %s not found", gcs
->exp
->toChars());
2593 if (!sc
->sw
->sdefault
)
2596 if (global
.params
.warnings
)
2597 { fprintf(stdmsg
, "warning - ");
2598 error("switch statement has no default");
2601 // Generate runtime error if the default is hit
2602 Statements
*a
= new Statements();
2603 CompoundStatement
*cs
;
2606 if (global
.params
.useSwitchError
)
2607 s
= new SwitchErrorStatement(loc
);
2609 { Expression
*e
= new HaltExp(loc
);
2610 s
= new ExpStatement(loc
, e
);
2615 a
->push(new BreakStatement(loc
, NULL
));
2616 sc
->sw
->sdefault
= new DefaultStatement(loc
, s
);
2617 a
->push(sc
->sw
->sdefault
);
2618 cs
= new CompoundStatement(loc
, a
);
2626 int SwitchStatement::hasBreak()
2631 int SwitchStatement::usesEH()
2633 return body
? body
->usesEH() : 0;
2636 int SwitchStatement::blockExit()
2637 { int result
= BEnone
;
2638 if (condition
->canThrow())
2642 { result
|= body
->blockExit();
2643 if (result
& BEbreak
)
2644 { result
|= BEfallthru
;
2649 result
|= BEfallthru
;
2654 int SwitchStatement::fallOffEnd()
2658 return TRUE
; // need to do this better
2661 void SwitchStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2663 buf
->writestring("switch (");
2664 condition
->toCBuffer(buf
, hgs
);
2665 buf
->writebyte(')');
2669 if (!body
->isScopeStatement())
2670 { buf
->writebyte('{');
2672 body
->toCBuffer(buf
, hgs
);
2673 buf
->writebyte('}');
2678 body
->toCBuffer(buf
, hgs
);
2683 /******************************** CaseStatement ***************************/
2685 CaseStatement::CaseStatement(Loc loc
, Expression
*exp
, Statement
*s
)
2689 this->statement
= s
;
2694 Statement
*CaseStatement::syntaxCopy()
2696 CaseStatement
*s
= new CaseStatement(loc
, exp
->syntaxCopy(), statement
->syntaxCopy());
2700 Statement
*CaseStatement::semantic(Scope
*sc
)
2701 { SwitchStatement
*sw
= sc
->sw
;
2703 //printf("CaseStatement::semantic() %s\n", toChars());
2704 exp
= exp
->semantic(sc
);
2707 exp
= exp
->implicitCastTo(sc
, sw
->condition
->type
);
2708 exp
= exp
->optimize(WANTvalue
| WANTinterpret
);
2710 /* This is where variables are allowed as case expressions.
2712 if (exp
->op
== TOKvar
)
2713 { VarExp
*ve
= (VarExp
*)exp
;
2714 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
2715 Type
*t
= exp
->type
->toBasetype();
2716 if (v
&& (t
->isintegral() || t
->ty
== Tclass
))
2717 { /* Flag that we need to do special code generation
2718 * for this, i.e. generate a sequence of if-then-else
2725 if (exp
->op
!= TOKstring
&& exp
->op
!= TOKint64
)
2727 error("case must be a string or an integral constant, not %s", exp
->toChars());
2728 exp
= new IntegerExp(0);
2732 for (int i
= 0; i
< sw
->cases
->dim
; i
++)
2734 CaseStatement
*cs
= (CaseStatement
*)sw
->cases
->data
[i
];
2736 //printf("comparing '%s' with '%s'\n", exp->toChars(), cs->exp->toChars());
2737 if (cs
->exp
->equals(exp
))
2738 { error("duplicate case %s in switch statement", exp
->toChars());
2743 sw
->cases
->push(this);
2745 // Resolve any goto case's with no exp to this case statement
2746 for (int i
= 0; i
< sw
->gotoCases
.dim
; i
++)
2748 GotoCaseStatement
*gcs
= (GotoCaseStatement
*)sw
->gotoCases
.data
[i
];
2753 sw
->gotoCases
.remove(i
); // remove from array
2757 if (sc
->sw
->tf
!= sc
->tf
)
2758 error("switch and case are in different finally blocks");
2761 error("case not in switch statement");
2762 statement
= statement
->semantic(sc
);
2766 int CaseStatement::compare(Object
*obj
)
2768 // Sort cases so we can do an efficient lookup
2769 CaseStatement
*cs2
= (CaseStatement
*)(obj
);
2771 return exp
->compare(cs2
->exp
);
2774 int CaseStatement::usesEH()
2776 return statement
->usesEH();
2779 int CaseStatement::blockExit()
2785 int CaseStatement::fallOffEnd()
2787 return statement
->fallOffEnd();
2790 int CaseStatement::comeFrom()
2795 void CaseStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2797 buf
->writestring("case ");
2798 exp
->toCBuffer(buf
, hgs
);
2799 buf
->writebyte(':');
2801 statement
->toCBuffer(buf
, hgs
);
2804 /******************************** DefaultStatement ***************************/
2806 DefaultStatement::DefaultStatement(Loc loc
, Statement
*s
)
2809 this->statement
= s
;
2815 Statement
*DefaultStatement::syntaxCopy()
2817 DefaultStatement
*s
= new DefaultStatement(loc
, statement
->syntaxCopy());
2821 Statement
*DefaultStatement::semantic(Scope
*sc
)
2823 //printf("DefaultStatement::semantic()\n");
2826 if (sc
->sw
->sdefault
)
2828 error("switch statement already has a default");
2830 sc
->sw
->sdefault
= this;
2832 if (sc
->sw
->tf
!= sc
->tf
)
2833 error("switch and default are in different finally blocks");
2836 error("default not in switch statement");
2837 statement
= statement
->semantic(sc
);
2841 int DefaultStatement::usesEH()
2843 return statement
->usesEH();
2846 int DefaultStatement::blockExit()
2852 int DefaultStatement::fallOffEnd()
2854 return statement
->fallOffEnd();
2857 int DefaultStatement::comeFrom()
2862 void DefaultStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2864 buf
->writestring("default:\n");
2865 statement
->toCBuffer(buf
, hgs
);
2868 /******************************** GotoDefaultStatement ***************************/
2870 GotoDefaultStatement::GotoDefaultStatement(Loc loc
)
2876 Statement
*GotoDefaultStatement::syntaxCopy()
2878 GotoDefaultStatement
*s
= new GotoDefaultStatement(loc
);
2882 Statement
*GotoDefaultStatement::semantic(Scope
*sc
)
2886 error("goto default not in switch statement");
2890 int GotoDefaultStatement::blockExit()
2895 int GotoDefaultStatement::fallOffEnd()
2900 void GotoDefaultStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2902 buf
->writestring("goto default;\n");
2905 /******************************** GotoCaseStatement ***************************/
2907 GotoCaseStatement::GotoCaseStatement(Loc loc
, Expression
*exp
)
2914 Statement
*GotoCaseStatement::syntaxCopy()
2916 Expression
*e
= exp
? exp
->syntaxCopy() : NULL
;
2917 GotoCaseStatement
*s
= new GotoCaseStatement(loc
, e
);
2921 Statement
*GotoCaseStatement::semantic(Scope
*sc
)
2924 exp
= exp
->semantic(sc
);
2927 error("goto case not in switch statement");
2930 sc
->sw
->gotoCases
.push(this);
2933 exp
= exp
->implicitCastTo(sc
, sc
->sw
->condition
->type
);
2934 exp
= exp
->optimize(WANTvalue
);
2940 int GotoCaseStatement::blockExit()
2945 int GotoCaseStatement::fallOffEnd()
2950 void GotoCaseStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2952 buf
->writestring("goto case");
2954 { buf
->writebyte(' ');
2955 exp
->toCBuffer(buf
, hgs
);
2957 buf
->writebyte(';');
2961 /******************************** SwitchErrorStatement ***************************/
2963 SwitchErrorStatement::SwitchErrorStatement(Loc loc
)
2968 int SwitchErrorStatement::blockExit()
2973 int SwitchErrorStatement::fallOffEnd()
2978 void SwitchErrorStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2980 buf
->writestring("SwitchErrorStatement::toCBuffer()");
2984 /******************************** ReturnStatement ***************************/
2986 ReturnStatement::ReturnStatement(Loc loc
, Expression
*exp
)
2992 Statement
*ReturnStatement::syntaxCopy()
2994 Expression
*e
= NULL
;
2996 e
= exp
->syntaxCopy();
2997 ReturnStatement
*s
= new ReturnStatement(loc
, e
);
3001 Statement
*ReturnStatement::semantic(Scope
*sc
)
3003 //printf("ReturnStatement::semantic() %s\n", toChars());
3005 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
3011 // Find scope of function foreach is in
3012 for (; 1; scx
= scx
->enclosing
)
3015 if (scx
->func
!= fd
)
3016 { fd
= scx
->func
; // fd is now function enclosing foreach
3022 Type
*tret
= fd
->type
->nextOf();
3024 tret
= fd
->tintro
->nextOf();
3028 tbret
= tret
->toBasetype();
3030 // main() returns 0, even if it returns void
3031 if (!exp
&& (!tbret
|| tbret
->ty
== Tvoid
) && fd
->isMain())
3033 exp
= new IntegerExp(0);
3036 if (sc
->incontract
|| scx
->incontract
)
3037 error("return statements cannot be in contracts");
3038 if (sc
->tf
|| scx
->tf
)
3039 error("return statements cannot be in finally, scope(exit) or scope(success) bodies");
3041 if (fd
->isCtorDeclaration())
3043 // Constructors implicitly do:
3045 if (exp
&& exp
->op
!= TOKthis
)
3046 error("cannot return expression from constructor");
3047 exp
= new ThisExp(0);
3055 fd
->hasReturnExp
|= 1;
3057 exp
= exp
->semantic(sc
);
3058 exp
= resolveProperties(sc
, exp
);
3059 exp
= exp
->optimize(WANTvalue
);
3061 if (fd
->nrvo_can
&& exp
->op
== TOKvar
)
3062 { VarExp
*ve
= (VarExp
*)exp
;
3063 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
3065 if (!v
|| v
->isOut() || v
->isRef())
3067 else if (tbret
->ty
== Tstruct
&& ((TypeStruct
*)tbret
)->sym
->dtor
)
3068 // Struct being returned has destructors
3070 else if (fd
->nrvo_var
== NULL
)
3071 { if (!v
->isDataseg() && !v
->isParameter() && v
->toParent2() == fd
)
3072 { //printf("Setting nrvo to %s\n", v->toChars());
3078 else if (fd
->nrvo_var
!= v
)
3084 if (fd
->returnLabel
&& tbret
->ty
!= Tvoid
)
3087 else if (fd
->inferRetType
)
3089 if (fd
->type
->nextOf())
3091 if (!exp
->type
->equals(fd
->type
->nextOf()))
3092 error("mismatched function return type inference of %s and %s",
3093 exp
->type
->toChars(), fd
->type
->nextOf()->toChars());
3097 ((TypeFunction
*)fd
->type
)->next
= exp
->type
;
3098 fd
->type
= fd
->type
->semantic(loc
, sc
);
3100 { tret
= fd
->type
->nextOf();
3101 tbret
= tret
->toBasetype();
3105 else if (tbret
->ty
!= Tvoid
)
3107 exp
= exp
->implicitCastTo(sc
, tret
);
3110 else if (fd
->inferRetType
)
3112 if (fd
->type
->nextOf())
3114 if (fd
->type
->nextOf()->ty
!= Tvoid
)
3115 error("mismatched function return type inference of void and %s",
3116 fd
->type
->nextOf()->toChars());
3120 ((TypeFunction
*)fd
->type
)->next
= Type::tvoid
;
3121 fd
->type
= fd
->type
->semantic(loc
, sc
);
3123 { tret
= Type::tvoid
;
3128 else if (tbret
->ty
!= Tvoid
) // if non-void return
3129 error("return expression expected");
3135 if (exp
&& !implicit0
)
3137 exp
= exp
->implicitCastTo(sc
, tret
);
3139 if (!exp
|| exp
->op
== TOKint64
|| exp
->op
== TOKfloat64
||
3140 exp
->op
== TOKimaginary80
|| exp
->op
== TOKcomplex80
||
3141 exp
->op
== TOKthis
|| exp
->op
== TOKsuper
|| exp
->op
== TOKnull
||
3142 exp
->op
== TOKstring
)
3144 sc
->fes
->cases
.push(this);
3145 s
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
3147 else if (fd
->type
->nextOf()->toBasetype() == Type::tvoid
)
3152 s
= new ReturnStatement(0, NULL
);
3153 sc
->fes
->cases
.push(s
);
3155 // Construct: { exp; return cases.dim + 1; }
3156 s1
= new ExpStatement(loc
, exp
);
3157 s2
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
3158 s
= new CompoundStatement(loc
, s1
, s2
);
3166 // Construct: return vresult;
3168 { VarDeclaration
*v
;
3170 v
= new VarDeclaration(loc
, tret
, Id::result
, NULL
);
3173 if (!scx
->insert(v
))
3179 v
= new VarExp(0, fd
->vresult
);
3180 s
= new ReturnStatement(0, v
);
3181 sc
->fes
->cases
.push(s
);
3183 // Construct: { vresult = exp; return cases.dim + 1; }
3184 v
= new VarExp(0, fd
->vresult
);
3185 exp
= new AssignExp(loc
, v
, exp
);
3186 exp
= exp
->semantic(sc
);
3187 s1
= new ExpStatement(loc
, exp
);
3188 s2
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
3189 s
= new CompoundStatement(loc
, s1
, s2
);
3196 if (fd
->returnLabel
&& tbret
->ty
!= Tvoid
)
3198 assert(fd
->vresult
);
3199 VarExp
*v
= new VarExp(0, fd
->vresult
);
3201 exp
= new AssignExp(loc
, v
, exp
);
3202 exp
= exp
->semantic(sc
);
3209 /* BUG: need to issue an error on:
3216 if (sc
->callSuper
& CSXany_ctor
&&
3217 !(sc
->callSuper
& (CSXthis_ctor
| CSXsuper_ctor
)))
3218 error("return without calling constructor");
3220 sc
->callSuper
|= CSXreturn
;
3222 // See if all returns are instead to be replaced with a goto returnLabel;
3223 if (fd
->returnLabel
)
3225 GotoStatement
*gs
= new GotoStatement(loc
, Id::returnLabel
);
3227 gs
->label
= fd
->returnLabel
;
3231 s
= new ExpStatement(0, exp
);
3232 return new CompoundStatement(loc
, s
, gs
);
3237 if (exp
&& tbret
->ty
== Tvoid
&& !fd
->isMain())
3240 s
= new ExpStatement(loc
, exp
);
3243 return new CompoundStatement(loc
, s
, this);
3249 int ReturnStatement::blockExit()
3250 { int result
= BEreturn
;
3252 if (exp
&& exp
->canThrow())
3257 int ReturnStatement::fallOffEnd()
3262 void ReturnStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3264 buf
->printf("return ");
3266 exp
->toCBuffer(buf
, hgs
);
3267 buf
->writeByte(';');
3271 /******************************** BreakStatement ***************************/
3273 BreakStatement::BreakStatement(Loc loc
, Identifier
*ident
)
3276 this->ident
= ident
;
3279 Statement
*BreakStatement::syntaxCopy()
3281 BreakStatement
*s
= new BreakStatement(loc
, ident
);
3285 Statement
*BreakStatement::semantic(Scope
*sc
)
3287 //printf("BreakStatement::semantic()\n");
3289 // break Identifier;
3293 FuncDeclaration
*thisfunc
= sc
->func
;
3295 for (scx
= sc
; scx
; scx
= scx
->enclosing
)
3299 if (scx
->func
!= thisfunc
) // if in enclosing function
3301 if (sc
->fes
) // if this is the body of a foreach
3303 /* Post this statement to the fes, and replace
3304 * it with a return value that caller will put into
3305 * a switch. Caller will figure out where the break
3306 * label actually is.
3307 * Case numbers start with 2, not 0, as 0 is continue
3311 sc
->fes
->cases
.push(this);
3312 s
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
3315 break; // can't break to it
3319 if (ls
&& ls
->ident
== ident
)
3321 Statement
*s
= ls
->statement
;
3324 error("label '%s' has no break", ident
->toChars());
3325 if (ls
->tf
!= sc
->tf
)
3326 error("cannot break out of finally block");
3330 error("enclosing label '%s' for break not found", ident
->toChars());
3332 else if (!sc
->sbreak
)
3337 // Replace break; with return 1;
3338 s
= new ReturnStatement(0, new IntegerExp(1));
3341 error("break is not inside a loop or switch");
3346 int BreakStatement::blockExit()
3348 //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak);
3349 return ident
? BEgoto
: BEbreak
;
3352 int BreakStatement::fallOffEnd()
3357 void BreakStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3359 buf
->writestring("break");
3361 { buf
->writebyte(' ');
3362 buf
->writestring(ident
->toChars());
3364 buf
->writebyte(';');
3368 /******************************** ContinueStatement ***************************/
3370 ContinueStatement::ContinueStatement(Loc loc
, Identifier
*ident
)
3373 this->ident
= ident
;
3376 Statement
*ContinueStatement::syntaxCopy()
3378 ContinueStatement
*s
= new ContinueStatement(loc
, ident
);
3382 Statement
*ContinueStatement::semantic(Scope
*sc
)
3384 //printf("ContinueStatement::semantic() %p\n", this);
3388 FuncDeclaration
*thisfunc
= sc
->func
;
3390 for (scx
= sc
; scx
; scx
= scx
->enclosing
)
3394 if (scx
->func
!= thisfunc
) // if in enclosing function
3396 if (sc
->fes
) // if this is the body of a foreach
3398 for (; scx
; scx
= scx
->enclosing
)
3401 if (ls
&& ls
->ident
== ident
&& ls
->statement
== sc
->fes
)
3403 // Replace continue ident; with return 0;
3404 return new ReturnStatement(0, new IntegerExp(0));
3408 /* Post this statement to the fes, and replace
3409 * it with a return value that caller will put into
3410 * a switch. Caller will figure out where the break
3411 * label actually is.
3412 * Case numbers start with 2, not 0, as 0 is continue
3416 sc
->fes
->cases
.push(this);
3417 s
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
3420 break; // can't continue to it
3424 if (ls
&& ls
->ident
== ident
)
3426 Statement
*s
= ls
->statement
;
3428 if (!s
->hasContinue())
3429 error("label '%s' has no continue", ident
->toChars());
3430 if (ls
->tf
!= sc
->tf
)
3431 error("cannot continue out of finally block");
3435 error("enclosing label '%s' for continue not found", ident
->toChars());
3437 else if (!sc
->scontinue
)
3442 // Replace continue; with return 0;
3443 s
= new ReturnStatement(0, new IntegerExp(0));
3446 error("continue is not inside a loop");
3451 int ContinueStatement::blockExit()
3453 return ident
? BEgoto
: BEcontinue
;
3456 int ContinueStatement::fallOffEnd()
3461 void ContinueStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3463 buf
->writestring("continue");
3465 { buf
->writebyte(' ');
3466 buf
->writestring(ident
->toChars());
3468 buf
->writebyte(';');
3472 /******************************** SynchronizedStatement ***************************/
3474 SynchronizedStatement::SynchronizedStatement(Loc loc
, Expression
*exp
, Statement
*body
)
3482 SynchronizedStatement::SynchronizedStatement(Loc loc
, elem
*esync
, Statement
*body
)
3487 this->esync
= esync
;
3490 Statement
*SynchronizedStatement::syntaxCopy()
3492 Expression
*e
= exp
? exp
->syntaxCopy() : NULL
;
3493 SynchronizedStatement
*s
= new SynchronizedStatement(loc
, e
, body
? body
->syntaxCopy() : NULL
);
3497 Statement
*SynchronizedStatement::semantic(Scope
*sc
)
3500 { ClassDeclaration
*cd
;
3502 exp
= exp
->semantic(sc
);
3503 exp
= resolveProperties(sc
, exp
);
3504 cd
= exp
->type
->isClassHandle();
3506 error("can only synchronize on class objects, not '%s'", exp
->type
->toChars());
3507 else if (cd
->isInterfaceDeclaration())
3508 { Type
*t
= new TypeIdentifier(0, Id::Object
);
3510 t
= t
->semantic(0, sc
);
3511 exp
= new CastExp(loc
, exp
, t
);
3512 exp
= exp
->semantic(sc
);
3516 body
= body
->semantic(sc
);
3520 int SynchronizedStatement::hasBreak()
3522 return FALSE
; //TRUE;
3525 int SynchronizedStatement::hasContinue()
3527 return FALSE
; //TRUE;
3530 int SynchronizedStatement::usesEH()
3535 int SynchronizedStatement::blockExit()
3537 return body
? body
->blockExit() : BEfallthru
;
3540 int SynchronizedStatement::fallOffEnd()
3542 return body
? body
->fallOffEnd() : TRUE
;
3545 void SynchronizedStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3547 buf
->writestring("synchronized");
3549 { buf
->writebyte('(');
3550 exp
->toCBuffer(buf
, hgs
);
3551 buf
->writebyte(')');
3555 buf
->writebyte(' ');
3556 body
->toCBuffer(buf
, hgs
);
3560 /******************************** WithStatement ***************************/
3562 WithStatement::WithStatement(Loc loc
, Expression
*exp
, Statement
*body
)
3570 Statement
*WithStatement::syntaxCopy()
3572 WithStatement
*s
= new WithStatement(loc
, exp
->syntaxCopy(), body
? body
->syntaxCopy() : NULL
);
3576 Statement
*WithStatement::semantic(Scope
*sc
)
3577 { ScopeDsymbol
*sym
;
3580 //printf("WithStatement::semantic()\n");
3581 exp
= exp
->semantic(sc
);
3582 exp
= resolveProperties(sc
, exp
);
3583 if (exp
->op
== TOKimport
)
3584 { ScopeExp
*es
= (ScopeExp
*)exp
;
3588 else if (exp
->op
== TOKtype
)
3589 { TypeExp
*es
= (TypeExp
*)exp
;
3591 sym
= es
->type
->toDsymbol(sc
)->isScopeDsymbol();
3593 { error("%s has no members", es
->toChars());
3594 body
= body
->semantic(sc
);
3599 { Type
*t
= exp
->type
;
3602 t
= t
->toBasetype();
3603 if (t
->isClassHandle())
3605 init
= new ExpInitializer(loc
, exp
);
3606 wthis
= new VarDeclaration(loc
, exp
->type
, Id::withSym
, init
);
3607 wthis
->semantic(sc
);
3609 sym
= new WithScopeSymbol(this);
3610 sym
->parent
= sc
->scopesym
;
3612 else if (t
->ty
== Tstruct
)
3614 Expression
*e
= exp
->addressOf(sc
);
3615 init
= new ExpInitializer(loc
, e
);
3616 wthis
= new VarDeclaration(loc
, e
->type
, Id::withSym
, init
);
3617 wthis
->semantic(sc
);
3618 sym
= new WithScopeSymbol(this);
3619 sym
->parent
= sc
->scopesym
;
3622 { error("with expressions must be class objects, not '%s'", exp
->type
->toChars());
3629 body
= body
->semantic(sc
);
3636 void WithStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3638 buf
->writestring("with (");
3639 exp
->toCBuffer(buf
, hgs
);
3640 buf
->writestring(")\n");
3642 body
->toCBuffer(buf
, hgs
);
3645 int WithStatement::usesEH()
3647 return body
? body
->usesEH() : 0;
3650 int WithStatement::blockExit()
3652 int result
= BEnone
;
3653 if (exp
->canThrow())
3656 result
|= body
->blockExit();
3658 result
|= BEfallthru
;
3662 int WithStatement::fallOffEnd()
3664 return body
? body
->fallOffEnd() : TRUE
;
3667 /******************************** TryCatchStatement ***************************/
3669 TryCatchStatement::TryCatchStatement(Loc loc
, Statement
*body
, Array
*catches
)
3673 this->catches
= catches
;
3676 Statement
*TryCatchStatement::syntaxCopy()
3678 Array
*a
= new Array();
3679 a
->setDim(catches
->dim
);
3680 for (int i
= 0; i
< a
->dim
; i
++)
3683 c
= (Catch
*)catches
->data
[i
];
3684 c
= c
->syntaxCopy();
3687 TryCatchStatement
*s
= new TryCatchStatement(loc
, body
->syntaxCopy(), a
);
3691 Statement
*TryCatchStatement::semantic(Scope
*sc
)
3693 body
= body
->semanticScope(sc
, NULL
/*this*/, NULL
);
3695 /* Even if body is NULL, still do semantic analysis on catches
3697 for (size_t i
= 0; i
< catches
->dim
; i
++)
3698 { Catch
*c
= (Catch
*)catches
->data
[i
];
3701 // Determine if current catch 'hides' any previous catches
3702 for (size_t j
= 0; j
< i
; j
++)
3703 { Catch
*cj
= (Catch
*)catches
->data
[j
];
3704 char *si
= c
->loc
.toChars();
3705 char *sj
= cj
->loc
.toChars();
3707 if (c
->type
->toBasetype()->implicitConvTo(cj
->type
->toBasetype()))
3708 error("catch at %s hides catch at %s", sj
, si
);
3718 int TryCatchStatement::hasBreak()
3720 return FALSE
; //TRUE;
3723 int TryCatchStatement::usesEH()
3728 int TryCatchStatement::blockExit()
3732 result
= body
->blockExit();
3734 for (size_t i
= 0; i
< catches
->dim
; i
++)
3736 Catch
*c
= (Catch
*)catches
->data
[i
];
3737 result
|= c
->blockExit();
3742 int TryCatchStatement::fallOffEnd()
3747 result
= body
->fallOffEnd();
3748 for (int i
= 0; i
< catches
->dim
; i
++)
3751 c
= (Catch
*)catches
->data
[i
];
3753 result
|= c
->handler
->fallOffEnd();
3758 void TryCatchStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3760 buf
->writestring("try");
3763 body
->toCBuffer(buf
, hgs
);
3764 for (size_t i
= 0; i
< catches
->dim
; i
++)
3766 Catch
*c
= (Catch
*)catches
->data
[i
];
3767 c
->toCBuffer(buf
, hgs
);
3771 /******************************** Catch ***************************/
3773 Catch::Catch(Loc loc
, Type
*t
, Identifier
*id
, Statement
*handler
)
3775 //printf("Catch(%s, loc = %s)\n", id->toChars(), loc.toChars());
3779 this->handler
= handler
;
3783 Catch
*Catch::syntaxCopy()
3785 Catch
*c
= new Catch(loc
,
3786 (type
? type
->syntaxCopy() : NULL
),
3788 (handler
? handler
->syntaxCopy() : NULL
));
3792 void Catch::semantic(Scope
*sc
)
3793 { ScopeDsymbol
*sym
;
3795 //printf("Catch::semantic(%s)\n", ident->toChars());
3800 /* This is because the _d_local_unwind() gets the stack munged
3801 * up on this. The workaround is to place any try-catches into
3802 * a separate function, and call that.
3803 * To fix, have the compiler automatically convert the finally
3804 * body into a nested function.
3806 error(loc
, "cannot put catch statement inside finally block");
3810 sym
= new ScopeDsymbol();
3811 sym
->parent
= sc
->scopesym
;
3815 type
= new TypeIdentifier(0, Id::Object
);
3816 type
= type
->semantic(loc
, sc
);
3817 if (!type
->toBasetype()->isClassHandle())
3818 error("can only catch class objects, not '%s'", type
->toChars());
3821 var
= new VarDeclaration(loc
, type
, ident
, NULL
);
3822 var
->parent
= sc
->parent
;
3825 handler
= handler
->semantic(sc
);
3830 int Catch::blockExit()
3832 return handler
? handler
->blockExit() : BEfallthru
;
3835 void Catch::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3837 buf
->writestring("catch");
3839 { buf
->writebyte('(');
3840 type
->toCBuffer(buf
, ident
, hgs
);
3841 buf
->writebyte(')');
3844 buf
->writebyte('{');
3847 handler
->toCBuffer(buf
, hgs
);
3848 buf
->writebyte('}');
3852 /****************************** TryFinallyStatement ***************************/
3854 TryFinallyStatement::TryFinallyStatement(Loc loc
, Statement
*body
, Statement
*finalbody
)
3858 this->finalbody
= finalbody
;
3861 Statement
*TryFinallyStatement::syntaxCopy()
3863 TryFinallyStatement
*s
= new TryFinallyStatement(loc
,
3864 body
->syntaxCopy(), finalbody
->syntaxCopy());
3868 Statement
*TryFinallyStatement::semantic(Scope
*sc
)
3870 //printf("TryFinallyStatement::semantic()\n");
3871 body
= body
->semantic(sc
);
3875 sc
->scontinue
= NULL
; // no break or continue out of finally block
3876 finalbody
= finalbody
->semantic(sc
);
3882 if (body
->blockExit() == BEfallthru
)
3883 { Statement
*s
= new CompoundStatement(loc
, body
, finalbody
);
3889 void TryFinallyStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3891 buf
->printf("try\n{\n");
3892 body
->toCBuffer(buf
, hgs
);
3893 buf
->printf("}\nfinally\n{\n");
3894 finalbody
->toCBuffer(buf
, hgs
);
3895 buf
->writeByte('}');
3899 int TryFinallyStatement::hasBreak()
3901 return FALSE
; //TRUE;
3904 int TryFinallyStatement::hasContinue()
3906 return FALSE
; //TRUE;
3909 int TryFinallyStatement::usesEH()
3914 int TryFinallyStatement::blockExit()
3916 int result
= body
->blockExit();
3920 int TryFinallyStatement::fallOffEnd()
3923 result
= body
->fallOffEnd();
3925 // result = finalbody->fallOffEnd();
3929 /****************************** OnScopeStatement ***************************/
3931 OnScopeStatement::OnScopeStatement(Loc loc
, TOK tok
, Statement
*statement
)
3935 this->statement
= statement
;
3938 Statement
*OnScopeStatement::syntaxCopy()
3940 OnScopeStatement
*s
= new OnScopeStatement(loc
,
3941 tok
, statement
->syntaxCopy());
3945 Statement
*OnScopeStatement::semantic(Scope
*sc
)
3947 /* semantic is called on results of scopeCode() */
3951 int OnScopeStatement::blockExit()
3952 { // At this point, this statement is just an empty placeholder
3956 void OnScopeStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3958 buf
->writestring(Token::toChars(tok
));
3959 buf
->writebyte(' ');
3960 statement
->toCBuffer(buf
, hgs
);
3963 int OnScopeStatement::usesEH()
3968 void OnScopeStatement::scopeCode(Scope
*sc
, Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
3970 //printf("OnScopeStatement::scopeCode()\n");
3977 case TOKon_scope_exit
:
3978 *sfinally
= statement
;
3981 case TOKon_scope_failure
:
3982 *sexception
= statement
;
3985 case TOKon_scope_success
:
3988 * sentry: int x = 0;
3989 * sexception: x = 1;
3990 * sfinally: if (!x) statement;
3992 Identifier
*id
= Lexer::uniqueId("__os");
3994 ExpInitializer
*ie
= new ExpInitializer(loc
, new IntegerExp(0));
3995 VarDeclaration
*v
= new VarDeclaration(loc
, Type::tint32
, id
, ie
);
3996 *sentry
= new DeclarationStatement(loc
, v
);
3998 Expression
*e
= new IntegerExp(1);
3999 e
= new AssignExp(0, new VarExp(0, v
), e
);
4000 *sexception
= new ExpStatement(0, e
);
4002 e
= new VarExp(0, v
);
4003 e
= new NotExp(0, e
);
4004 *sfinally
= new IfStatement(0, NULL
, e
, statement
, NULL
);
4014 /******************************** ThrowStatement ***************************/
4016 ThrowStatement::ThrowStatement(Loc loc
, Expression
*exp
)
4022 Statement
*ThrowStatement::syntaxCopy()
4024 ThrowStatement
*s
= new ThrowStatement(loc
, exp
->syntaxCopy());
4028 Statement
*ThrowStatement::semantic(Scope
*sc
)
4030 //printf("ThrowStatement::semantic()\n");
4032 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
4033 fd
->hasReturnExp
|= 2;
4036 error("Throw statements cannot be in contracts");
4037 exp
= exp
->semantic(sc
);
4038 exp
= resolveProperties(sc
, exp
);
4039 if (!exp
->type
->toBasetype()->isClassHandle())
4040 error("can only throw class objects, not type %s", exp
->type
->toChars());
4044 int ThrowStatement::blockExit()
4046 return BEthrow
; // obviously
4049 int ThrowStatement::fallOffEnd()
4054 void ThrowStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4056 buf
->printf("throw ");
4057 exp
->toCBuffer(buf
, hgs
);
4058 buf
->writeByte(';');
4062 /******************************** VolatileStatement **************************/
4064 VolatileStatement::VolatileStatement(Loc loc
, Statement
*statement
)
4067 this->statement
= statement
;
4070 Statement
*VolatileStatement::syntaxCopy()
4072 VolatileStatement
*s
= new VolatileStatement(loc
,
4073 statement
? statement
->syntaxCopy() : NULL
);
4077 Statement
*VolatileStatement::semantic(Scope
*sc
)
4080 statement
= statement
->semantic(sc
);
4084 Statements
*VolatileStatement::flatten(Scope
*sc
)
4088 a
= statement
? statement
->flatten(sc
) : NULL
;
4090 { for (int i
= 0; i
< a
->dim
; i
++)
4091 { Statement
*s
= (Statement
*)a
->data
[i
];
4093 s
= new VolatileStatement(loc
, s
);
4101 int VolatileStatement::blockExit()
4103 return statement
? statement
->blockExit() : BEfallthru
;
4106 int VolatileStatement::fallOffEnd()
4108 return statement
? statement
->fallOffEnd() : TRUE
;
4111 void VolatileStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4113 buf
->writestring("volatile");
4115 { if (statement
->isScopeStatement())
4118 buf
->writebyte(' ');
4119 statement
->toCBuffer(buf
, hgs
);
4124 /******************************** GotoStatement ***************************/
4126 GotoStatement::GotoStatement(Loc loc
, Identifier
*ident
)
4129 this->ident
= ident
;
4134 Statement
*GotoStatement::syntaxCopy()
4136 GotoStatement
*s
= new GotoStatement(loc
, ident
);
4140 Statement
*GotoStatement::semantic(Scope
*sc
)
4141 { FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
4143 //printf("GotoStatement::semantic()\n");
4145 label
= fd
->searchLabel(ident
);
4146 if (!label
->statement
&& sc
->fes
)
4148 /* Either the goto label is forward referenced or it
4149 * is in the function that the enclosing foreach is in.
4150 * Can't know yet, so wrap the goto in a compound statement
4151 * so we can patch it later, and add it to a 'look at this later'
4154 Statements
*a
= new Statements();
4158 s
= new CompoundStatement(loc
, a
);
4159 sc
->fes
->gotos
.push(s
); // 'look at this later' list
4162 if (label
->statement
&& label
->statement
->tf
!= sc
->tf
)
4163 error("cannot goto in or out of finally block");
4167 int GotoStatement::blockExit()
4169 //printf("GotoStatement::blockExit(%p)\n", this);
4173 int GotoStatement::fallOffEnd()
4178 void GotoStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4180 buf
->writestring("goto ");
4181 buf
->writestring(ident
->toChars());
4182 buf
->writebyte(';');
4186 /******************************** LabelStatement ***************************/
4188 LabelStatement::LabelStatement(Loc loc
, Identifier
*ident
, Statement
*statement
)
4191 this->ident
= ident
;
4192 this->statement
= statement
;
4194 this->lblock
= NULL
;
4195 this->isReturnLabel
= 0;
4198 Statement
*LabelStatement::syntaxCopy()
4200 LabelStatement
*s
= new LabelStatement(loc
, ident
, statement
->syntaxCopy());
4204 Statement
*LabelStatement::semantic(Scope
*sc
)
4206 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
4208 //printf("LabelStatement::semantic()\n");
4209 ls
= fd
->searchLabel(ident
);
4211 error("Label '%s' already defined", ls
->toChars());
4213 ls
->statement
= this;
4216 sc
->scopesym
= sc
->enclosing
->scopesym
;
4217 sc
->callSuper
|= CSXlabel
;
4220 statement
= statement
->semantic(sc
);
4225 Statements
*LabelStatement::flatten(Scope
*sc
)
4227 Statements
*a
= NULL
;
4231 a
= statement
->flatten(sc
);
4236 a
->push(new ExpStatement(loc
, NULL
));
4238 Statement
*s
= (Statement
*)a
->data
[0];
4240 s
= new LabelStatement(loc
, ident
, s
);
4249 int LabelStatement::usesEH()
4251 return statement
? statement
->usesEH() : FALSE
;
4254 int LabelStatement::blockExit()
4256 //printf("LabelStatement::blockExit(%p)\n", this);
4257 return statement
? statement
->blockExit() : BEfallthru
;
4260 int LabelStatement::fallOffEnd()
4262 return statement
? statement
->fallOffEnd() : TRUE
;
4265 int LabelStatement::comeFrom()
4267 //printf("LabelStatement::comeFrom()\n");
4271 void LabelStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4273 buf
->writestring(ident
->toChars());
4274 buf
->writebyte(':');
4277 statement
->toCBuffer(buf
, hgs
);
4281 /******************************** LabelDsymbol ***************************/
4283 LabelDsymbol::LabelDsymbol(Identifier
*ident
)
4292 LabelDsymbol
*LabelDsymbol::isLabel() // is this a LabelDsymbol()?