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 if (mainDecl
->type
->nextOf()->ty
!= Tvoid
) {
462 error("Main.main must return void (throw SystemExit to return a non-zero exit code)");
465 Expression
*newMain
= new NewExp(loc
, NULL
, NULL
, mainClass
->getType(),
466 ctor
? getAutoArgs(ctor
->loc
, ctor
->arguments
, sc
) : NULL
);
468 // Then invoke the main() method inside it
469 // mainObject.main(...)
470 Expression
*mainMethod
= new DotIdExp(mainDecl
->loc
, newMain
, Id::main
);
471 Expression
*mainCall
= new CallExp(mainMethod
->loc
, mainMethod
,
472 getAutoArgs(mainDecl
->loc
,
473 ((TypeFunction
*) mainDecl
->type
)->parameters
,
476 Statement
*body
= new ExpStatement(loc
, mainCall
);
478 return body
->semantic(sc
);
481 /******************************** CompoundStatement ***************************/
483 CompoundStatement::CompoundStatement(Loc loc
, Statements
*s
)
489 CompoundStatement::CompoundStatement(Loc loc
, Statement
*s1
, Statement
*s2
)
492 statements
= new Statements();
493 statements
->reserve(2);
494 statements
->push(s1
);
495 statements
->push(s2
);
498 Statement
*CompoundStatement::syntaxCopy()
500 Statements
*a
= new Statements();
501 a
->setDim(statements
->dim
);
502 for (size_t i
= 0; i
< statements
->dim
; i
++)
503 { Statement
*s
= (Statement
*)statements
->data
[i
];
508 CompoundStatement
*cs
= new CompoundStatement(loc
, a
);
513 Statement
*CompoundStatement::semantic(Scope
*sc
)
516 //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", this, sc);
518 for (size_t i
= 0; i
< statements
->dim
; )
520 s
= (Statement
*) statements
->data
[i
];
522 { Statements
*a
= s
->flatten(sc
);
526 statements
->remove(i
);
527 statements
->insert(i
, a
);
531 statements
->data
[i
] = s
;
535 Statement
*sexception
;
538 s
->scopeCode(sc
, &sentry
, &sexception
, &sfinally
);
541 sentry
= sentry
->semantic(sc
);
542 statements
->data
[i
] = sentry
;
546 if (i
+ 1 == statements
->dim
&& !sfinally
)
549 sexception
= sexception
->semantic(sc
);
551 statements
->push(sexception
);
553 // Assume sexception does not throw
554 statements
->push(sfinally
);
565 * { sexception; throw __o; }
568 Statements
*a
= new Statements();
570 for (int j
= i
+ 1; j
< statements
->dim
; j
++)
572 a
->push(statements
->data
[j
]);
574 body
= new CompoundStatement(0, a
);
575 body
= new ScopeStatement(0, body
);
577 Identifier
*id
= Lexer::uniqueId("__o");
579 Statement
*handler
= new ThrowStatement(0, new IdentifierExp(0, id
));
580 handler
= new CompoundStatement(0, sexception
, handler
);
582 Array
*catches
= new Array();
583 Catch
*ctch
= new Catch(0, NULL
, id
, handler
);
585 s
= new TryCatchStatement(0, body
, catches
);
588 s
= new TryFinallyStatement(0, s
, sfinally
);
590 statements
->setDim(i
+ 1);
597 if (0 && i
+ 1 == statements
->dim
)
599 statements
->push(sfinally
);
606 * s; try { s1; s2; } finally { sfinally; }
609 Statements
*a
= new Statements();
611 for (int j
= i
+ 1; j
< statements
->dim
; j
++)
613 a
->push(statements
->data
[j
]);
615 body
= new CompoundStatement(0, a
);
616 s
= new TryFinallyStatement(0, body
, sfinally
);
618 statements
->setDim(i
+ 1);
627 if (statements
->dim
== 1)
632 Statements
*CompoundStatement::flatten(Scope
*sc
)
637 ReturnStatement
*CompoundStatement::isReturnStatement()
639 ReturnStatement
*rs
= NULL
;
641 for (i
= 0; i
< statements
->dim
; i
++)
644 s
= (Statement
*) statements
->data
[i
];
647 rs
= s
->isReturnStatement();
655 void CompoundStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
658 for (i
= 0; i
< statements
->dim
; i
++)
661 s
= (Statement
*) statements
->data
[i
];
663 s
->toCBuffer(buf
, hgs
);
667 int CompoundStatement::usesEH()
669 for (int i
= 0; i
< statements
->dim
; i
++)
672 s
= (Statement
*) statements
->data
[i
];
673 if (s
&& s
->usesEH())
679 int CompoundStatement::blockExit()
681 //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim);
682 int result
= BEfallthru
;
683 for (size_t i
= 0; i
< statements
->dim
; i
++)
684 { Statement
*s
= (Statement
*) statements
->data
[i
];
687 //printf("result = x%x\n", result);
688 //printf("%s\n", s->toChars());
689 if (!(result
& BEfallthru
) && !s
->comeFrom())
691 if (global
.params
.warnings
)
692 { fprintf(stdmsg
, "warning - ");
693 s
->error("statement is not reachable");
697 result
&= ~BEfallthru
;
698 result
|= s
->blockExit();
704 int CompoundStatement::fallOffEnd()
705 { int falloff
= TRUE
;
707 //printf("CompoundStatement::fallOffEnd()\n");
708 for (int i
= 0; i
< statements
->dim
; i
++)
709 { Statement
*s
= (Statement
*)statements
->data
[i
];
715 if (!falloff
&& global
.params
.warnings
&& !s
->comeFrom())
717 fprintf(stdmsg
, "warning - ");
718 s
->error("statement is not reachable");
721 falloff
= s
->fallOffEnd();
726 int CompoundStatement::comeFrom()
727 { int comefrom
= FALSE
;
729 //printf("CompoundStatement::comeFrom()\n");
730 for (int i
= 0; i
< statements
->dim
; i
++)
731 { Statement
*s
= (Statement
*)statements
->data
[i
];
736 comefrom
|= s
->comeFrom();
742 /**************************** UnrolledLoopStatement ***************************/
744 UnrolledLoopStatement::UnrolledLoopStatement(Loc loc
, Statements
*s
)
750 Statement
*UnrolledLoopStatement::syntaxCopy()
752 Statements
*a
= new Statements();
753 a
->setDim(statements
->dim
);
754 for (size_t i
= 0; i
< statements
->dim
; i
++)
755 { Statement
*s
= (Statement
*)statements
->data
[i
];
760 UnrolledLoopStatement
*cs
= new UnrolledLoopStatement(loc
, a
);
765 Statement
*UnrolledLoopStatement::semantic(Scope
*sc
)
767 //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc);
770 Scope
*scd
= sc
->push();
772 scd
->scontinue
= this;
774 for (size_t i
= 0; i
< statements
->dim
; i
++)
776 Statement
*s
= (Statement
*) statements
->data
[i
];
779 s
= s
->semantic(scd
);
780 statements
->data
[i
] = s
;
789 void UnrolledLoopStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
791 buf
->writestring("unrolled {");
794 for (size_t i
= 0; i
< statements
->dim
; i
++)
797 s
= (Statement
*) statements
->data
[i
];
799 s
->toCBuffer(buf
, hgs
);
806 int UnrolledLoopStatement::hasBreak()
811 int UnrolledLoopStatement::hasContinue()
816 int UnrolledLoopStatement::usesEH()
818 for (size_t i
= 0; i
< statements
->dim
; i
++)
819 { Statement
*s
= (Statement
*) statements
->data
[i
];
820 if (s
&& s
->usesEH())
826 int UnrolledLoopStatement::blockExit()
828 int result
= BEfallthru
;
829 for (size_t i
= 0; i
< statements
->dim
; i
++)
830 { Statement
*s
= (Statement
*) statements
->data
[i
];
833 int r
= s
->blockExit();
834 result
|= r
& ~(BEbreak
| BEcontinue
);
840 int UnrolledLoopStatement::fallOffEnd()
842 //printf("UnrolledLoopStatement::fallOffEnd()\n");
843 for (size_t i
= 0; i
< statements
->dim
; i
++)
844 { Statement
*s
= (Statement
*)statements
->data
[i
];
852 int UnrolledLoopStatement::comeFrom()
853 { int comefrom
= FALSE
;
855 //printf("UnrolledLoopStatement::comeFrom()\n");
856 for (size_t i
= 0; i
< statements
->dim
; i
++)
857 { Statement
*s
= (Statement
*)statements
->data
[i
];
862 comefrom
|= s
->comeFrom();
868 /******************************** ScopeStatement ***************************/
870 ScopeStatement::ScopeStatement(Loc loc
, Statement
*s
)
876 Statement
*ScopeStatement::syntaxCopy()
880 s
= statement
? statement
->syntaxCopy() : NULL
;
881 s
= new ScopeStatement(loc
, s
);
886 Statement
*ScopeStatement::semantic(Scope
*sc
)
889 //printf("ScopeStatement::semantic(sc = %p)\n", sc);
893 sym
= new ScopeDsymbol();
894 sym
->parent
= sc
->scopesym
;
897 a
= statement
->flatten(sc
);
900 statement
= new CompoundStatement(loc
, a
);
903 statement
= statement
->semantic(sc
);
907 Statement
*sexception
;
910 statement
->scopeCode(sc
, &sentry
, &sexception
, &sfinally
);
913 //printf("adding sfinally\n");
914 statement
= new CompoundStatement(loc
, statement
, sfinally
);
923 int ScopeStatement::hasBreak()
925 //printf("ScopeStatement::hasBreak() %s\n", toChars());
926 return statement
? statement
->hasBreak() : FALSE
;
929 int ScopeStatement::hasContinue()
931 return statement
? statement
->hasContinue() : FALSE
;
934 int ScopeStatement::usesEH()
936 return statement
? statement
->usesEH() : FALSE
;
939 int ScopeStatement::blockExit()
941 //printf("ScopeStatement::blockExit(%p)\n", statement);
942 return statement
? statement
->blockExit() : BEfallthru
;
945 int ScopeStatement::fallOffEnd()
947 return statement
? statement
->fallOffEnd() : TRUE
;
950 int ScopeStatement::comeFrom()
952 //printf("ScopeStatement::comeFrom()\n");
953 return statement
? statement
->comeFrom() : FALSE
;
956 void ScopeStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
962 statement
->toCBuffer(buf
, hgs
);
968 /******************************** WhileStatement ***************************/
970 WhileStatement::WhileStatement(Loc loc
, Expression
*c
, Statement
*b
)
977 Statement
*WhileStatement::syntaxCopy()
979 WhileStatement
*s
= new WhileStatement(loc
, condition
->syntaxCopy(), body
? body
->syntaxCopy() : NULL
);
984 Statement
*WhileStatement::semantic(Scope
*sc
)
987 if (condition
->op
== TOKmatch
)
989 /* Rewrite while (condition) body as:
993 * while ((_match = _match.opNext), _match);
996 Expression
*ew
= new IdentifierExp(0, Id::_match
);
997 ew
= new DotIdExp(0, ew
, Id::next
);
998 ew
= new AssignExp(0, new IdentifierExp(0, Id::_match
), ew
);
999 ////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0));
1000 Expression
*ev
= new IdentifierExp(0, Id::_match
);
1001 //ev = new CastExp(0, ev, Type::tvoidptr);
1002 ew
= new CommaExp(0, ew
, ev
);
1003 Statement
*sw
= new DoStatement(loc
, body
, ew
);
1004 Statement
*si
= new IfStatement(loc
, condition
, sw
, NULL
);
1005 return si
->semantic(sc
);
1009 condition
= condition
->semantic(sc
);
1010 condition
= resolveProperties(sc
, condition
);
1011 condition
= condition
->optimize(WANTvalue
);
1012 condition
= condition
->checkToBoolean();
1016 Scope
*scd
= sc
->push();
1018 scd
->scontinue
= this;
1020 body
= body
->semantic(scd
);
1028 int WhileStatement::hasBreak()
1033 int WhileStatement::hasContinue()
1038 int WhileStatement::usesEH()
1040 return body
? body
->usesEH() : 0;
1043 int WhileStatement::blockExit()
1045 //printf("WhileStatement::blockExit(%p)\n", this);
1047 int result
= BEnone
;
1048 if (condition
->canThrow())
1051 { result
|= body
->blockExit();
1052 if (result
& BEbreak
)
1053 result
|= BEfallthru
;
1054 result
&= ~(BEbreak
| BEcontinue
);
1057 result
|= BEfallthru
;
1061 int WhileStatement::fallOffEnd()
1068 int WhileStatement::comeFrom()
1071 return body
->comeFrom();
1075 void WhileStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1077 buf
->writestring("while (");
1078 condition
->toCBuffer(buf
, hgs
);
1079 buf
->writebyte(')');
1082 body
->toCBuffer(buf
, hgs
);
1085 /******************************** DoStatement ***************************/
1087 DoStatement::DoStatement(Loc loc
, Statement
*b
, Expression
*c
)
1094 Statement
*DoStatement::syntaxCopy()
1096 DoStatement
*s
= new DoStatement(loc
, body
? body
->syntaxCopy() : NULL
, condition
->syntaxCopy());
1101 Statement
*DoStatement::semantic(Scope
*sc
)
1105 body
= body
->semanticScope(sc
, this, this);
1107 condition
= condition
->semantic(sc
);
1108 condition
= resolveProperties(sc
, condition
);
1109 condition
= condition
->optimize(WANTvalue
);
1111 condition
= condition
->checkToBoolean();
1116 int DoStatement::hasBreak()
1121 int DoStatement::hasContinue()
1126 int DoStatement::usesEH()
1128 return body
? body
->usesEH() : 0;
1131 int DoStatement::blockExit()
1135 { result
= body
->blockExit();
1136 if (result
& BEbreak
)
1138 if (result
== BEbreak
)
1140 result
|= BEfallthru
;
1142 if (result
& BEcontinue
)
1143 result
|= BEfallthru
;
1144 result
&= ~(BEbreak
| BEcontinue
);
1147 result
= BEfallthru
;
1148 if (result
& BEfallthru
&& condition
->canThrow())
1153 int DoStatement::fallOffEnd()
1160 int DoStatement::comeFrom()
1163 return body
->comeFrom();
1167 void DoStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1169 buf
->writestring("do");
1172 body
->toCBuffer(buf
, hgs
);
1173 buf
->writestring("while (");
1174 condition
->toCBuffer(buf
, hgs
);
1175 buf
->writebyte(')');
1178 /******************************** ForStatement ***************************/
1180 ForStatement::ForStatement(Loc loc
, Statement
*init
, Expression
*condition
, Expression
*increment
, Statement
*body
)
1184 this->condition
= condition
;
1185 this->increment
= increment
;
1189 Statement
*ForStatement::syntaxCopy()
1191 Statement
*i
= NULL
;
1193 i
= init
->syntaxCopy();
1194 Expression
*c
= NULL
;
1196 c
= condition
->syntaxCopy();
1197 Expression
*inc
= NULL
;
1199 inc
= increment
->syntaxCopy();
1200 ForStatement
*s
= new ForStatement(loc
, i
, c
, inc
, body
->syntaxCopy());
1204 Statement
*ForStatement::semantic(Scope
*sc
)
1206 ScopeDsymbol
*sym
= new ScopeDsymbol();
1207 sym
->parent
= sc
->scopesym
;
1210 init
= init
->semantic(sc
);
1214 condition
= condition
->semantic(sc
);
1215 condition
= resolveProperties(sc
, condition
);
1216 condition
= condition
->optimize(WANTvalue
);
1217 condition
= condition
->checkToBoolean();
1220 increment
= increment
->semantic(sc
);
1223 sc
->scontinue
= this;
1224 body
= body
->semantic(sc
);
1231 void ForStatement::scopeCode(Scope
*sc
, Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
1233 //printf("ForStatement::scopeCode()\n");
1236 init
->scopeCode(sc
, sentry
, sexception
, sfinally
);
1238 Statement::scopeCode(sc
, sentry
, sexception
, sfinally
);
1241 int ForStatement::hasBreak()
1243 //printf("ForStatement::hasBreak()\n");
1247 int ForStatement::hasContinue()
1252 int ForStatement::usesEH()
1254 return (init
&& init
->usesEH()) || body
->usesEH();
1257 int ForStatement::blockExit()
1258 { int result
= BEfallthru
;
1261 { result
= init
->blockExit();
1262 if (!(result
& BEfallthru
))
1266 { if (condition
->canThrow())
1270 result
&= ~BEfallthru
; // the body must do the exiting
1272 { int r
= body
->blockExit();
1274 result
|= BEfallthru
;
1275 result
|= r
& ~(BEbreak
| BEcontinue
);
1277 if (increment
&& increment
->canThrow())
1282 int ForStatement::fallOffEnd()
1289 int ForStatement::comeFrom()
1291 //printf("ForStatement::comeFrom()\n");
1293 { int result
= body
->comeFrom();
1294 //printf("result = %d\n", result);
1300 void ForStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1302 buf
->writestring("for (");
1306 hgs
->FLinit
.decl
= 0;
1307 init
->toCBuffer(buf
, hgs
);
1308 if (hgs
->FLinit
.decl
> 0)
1309 buf
->writebyte(';');
1310 hgs
->FLinit
.decl
= 0;
1314 buf
->writebyte(';');
1316 { buf
->writebyte(' ');
1317 condition
->toCBuffer(buf
, hgs
);
1319 buf
->writebyte(';');
1321 { buf
->writebyte(' ');
1322 increment
->toCBuffer(buf
, hgs
);
1324 buf
->writebyte(')');
1326 buf
->writebyte('{');
1328 body
->toCBuffer(buf
, hgs
);
1329 buf
->writebyte('}');
1333 /******************************** ForeachStatement ***************************/
1335 ForeachStatement::ForeachStatement(Loc loc
, enum TOK op
, Arguments
*arguments
,
1336 Expression
*aggr
, Statement
*body
)
1340 this->arguments
= arguments
;
1350 Statement
*ForeachStatement::syntaxCopy()
1352 Arguments
*args
= Argument::arraySyntaxCopy(arguments
);
1353 Expression
*exp
= aggr
->syntaxCopy();
1354 ForeachStatement
*s
= new ForeachStatement(loc
, op
, args
, exp
,
1355 body
? body
->syntaxCopy() : NULL
);
1359 Statement
*ForeachStatement::semantic(Scope
*sc
)
1361 //printf("ForeachStatement::semantic() %p\n", this);
1363 Statement
*s
= this;
1364 int dim
= arguments
->dim
;
1366 TypeAArray
*taa
= NULL
;
1373 func
= func
->fes
->func
;
1375 aggr
= aggr
->semantic(sc
);
1376 aggr
= resolveProperties(sc
, aggr
);
1377 aggr
= aggr
->optimize(WANTvalue
);
1380 error("invalid foreach aggregate %s", aggr
->toChars());
1384 inferApplyArgTypes(op
, arguments
, aggr
);
1386 /* Check for inference errors
1388 if (dim
!= arguments
->dim
)
1390 //printf("dim = %d, arguments->dim = %d\n", dim, arguments->dim);
1391 error("cannot uniquely infer foreach argument types");
1395 Type
*tab
= aggr
->type
->toBasetype();
1397 if (tab
->ty
== Ttuple
) // don't generate new scope for tuple loops
1399 if (dim
< 1 || dim
> 2)
1401 error("only one (value) or two (key,value) arguments for tuple foreach");
1405 TypeTuple
*tuple
= (TypeTuple
*)tab
;
1406 Statements
*statements
= new Statements();
1407 //printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars());
1409 TupleExp
*te
= NULL
;
1410 if (aggr
->op
== TOKtuple
) // expression tuple
1411 { te
= (TupleExp
*)aggr
;
1414 else if (aggr
->op
== TOKtype
) // type tuple
1416 n
= Argument::dim(tuple
->arguments
);
1420 for (size_t j
= 0; j
< n
; j
++)
1421 { size_t k
= (op
== TOKforeach
) ? j
: n
- 1 - j
;
1425 e
= (Expression
*)te
->exps
->data
[k
];
1427 t
= Argument::getNth(tuple
->arguments
, k
)->type
;
1428 Argument
*arg
= (Argument
*)arguments
->data
[0];
1429 Statements
*st
= new Statements();
1433 if (arg
->storageClass
& (STCout
| STCref
| STClazy
))
1434 error("no storage class for key %s", arg
->ident
->toChars());
1435 TY keyty
= arg
->type
->ty
;
1436 if ((keyty
!= Tint32
&& keyty
!= Tuns32
) &&
1437 (! global
.params
.isX86_64
||
1438 (keyty
!= Tint64
&& keyty
!= Tuns64
))
1441 error("foreach: key type must be int or uint, not %s", arg
->type
->toChars());
1443 Initializer
*ie
= new ExpInitializer(0, new IntegerExp(k
));
1444 VarDeclaration
*var
= new VarDeclaration(loc
, arg
->type
, arg
->ident
, ie
);
1445 var
->storage_class
|= STCmanifest
;
1446 DeclarationExp
*de
= new DeclarationExp(loc
, var
);
1447 st
->push(new ExpStatement(loc
, de
));
1448 arg
= (Argument
*)arguments
->data
[1]; // value
1451 if (arg
->storageClass
& (STCout
| STCref
| STClazy
))
1452 error("no storage class for value %s", arg
->ident
->toChars());
1455 { Type
*tb
= e
->type
->toBasetype();
1456 if ((tb
->ty
== Tfunction
|| tb
->ty
== Tsarray
) && e
->op
== TOKvar
)
1457 { VarExp
*ve
= (VarExp
*)e
;
1458 var
= new AliasDeclaration(loc
, arg
->ident
, ve
->var
);
1462 arg
->type
= e
->type
;
1463 Initializer
*ie
= new ExpInitializer(0, e
);
1464 VarDeclaration
*v
= new VarDeclaration(loc
, arg
->type
, arg
->ident
, ie
);
1466 v
->storage_class
|= STCconst
;
1472 var
= new AliasDeclaration(loc
, arg
->ident
, t
);
1474 DeclarationExp
*de
= new DeclarationExp(loc
, var
);
1475 st
->push(new ExpStatement(loc
, de
));
1477 st
->push(body
->syntaxCopy());
1478 s
= new CompoundStatement(loc
, st
);
1479 s
= new ScopeStatement(loc
, s
);
1480 statements
->push(s
);
1483 s
= new UnrolledLoopStatement(loc
, statements
);
1484 s
= s
->semantic(sc
);
1488 for (i
= 0; i
< dim
; i
++)
1489 { Argument
*arg
= (Argument
*)arguments
->data
[i
];
1492 error("cannot infer type for %s", arg
->ident
->toChars());
1497 sym
= new ScopeDsymbol();
1498 sym
->parent
= sc
->scopesym
;
1507 if (dim
< 1 || dim
> 2)
1509 error("only one or two arguments for array foreach");
1513 /* Look for special case of parsing char types out of char type
1516 tn
= tab
->nextOf()->toBasetype();
1517 if (tn
->ty
== Tchar
|| tn
->ty
== Twchar
|| tn
->ty
== Tdchar
)
1520 i
= (dim
== 1) ? 0 : 1; // index of value
1521 arg
= (Argument
*)arguments
->data
[i
];
1522 arg
->type
= arg
->type
->semantic(loc
, sc
);
1523 tnv
= arg
->type
->toBasetype();
1524 if (tnv
->ty
!= tn
->ty
&&
1525 (tnv
->ty
== Tchar
|| tnv
->ty
== Twchar
|| tnv
->ty
== Tdchar
))
1527 if (arg
->storageClass
& STCref
)
1528 error("foreach: value of UTF conversion cannot be ref");
1530 { arg
= (Argument
*)arguments
->data
[0];
1531 if (arg
->storageClass
& STCref
)
1532 error("foreach: key cannot be ref");
1538 for (i
= 0; i
< dim
; i
++)
1540 Argument
*arg
= (Argument
*)arguments
->data
[i
];
1541 VarDeclaration
*var
;
1543 var
= new VarDeclaration(loc
, arg
->type
, arg
->ident
, NULL
);
1544 var
->storage_class
|= STCforeach
;
1545 var
->storage_class
|= arg
->storageClass
& (STCin
| STCout
| STCref
| STCconst
| STCinvariant
);
1546 if (dim
== 2 && i
== 0)
1548 //var->storage_class |= STCfinal;
1551 { //if (!(arg->storageClass & STCref))
1552 //var->storage_class |= STCfinal;
1556 DeclarationExp
*de
= new DeclarationExp(loc
, var
);
1560 if (!sc
->insert(var
))
1561 error("%s already defined", var
->ident
->toChars());
1566 sc
->scontinue
= this;
1567 body
= body
->semantic(sc
);
1569 if (tab
->nextOf()->implicitConvTo(value
->type
) < MATCHconst
)
1571 if (aggr
->op
== TOKstring
)
1572 aggr
= aggr
->implicitCastTo(sc
, value
->type
->arrayOf());
1574 error("foreach: %s is not an array of %s",
1575 tab
->toChars(), value
->type
->toChars());
1579 ((key
->type
->ty
!= Tint32
&& key
->type
->ty
!= Tuns32
) &&
1580 (! global
.params
.isX86_64
||
1581 (key
->type
->ty
!= Tint64
&& key
->type
->ty
!= Tuns64
))
1585 error("foreach: key type must be int or uint, not %s", key
->type
->toChars());
1588 if (key
&& key
->storage_class
& (STCout
| STCref
))
1589 error("foreach: key cannot be out or ref");
1593 taa
= (TypeAArray
*)tab
;
1594 if (dim
< 1 || dim
> 2)
1596 error("only one or two arguments for associative array foreach");
1599 if (op
== TOKforeach_reverse
)
1601 error("no reverse iteration on associative arrays");
1609 { FuncDeclaration
*fdapply
;
1613 FuncLiteralDeclaration
*fld
;
1620 tret
= func
->type
->nextOf();
1622 // Need a variable to hold value from any return statements in body.
1623 if (!sc
->func
->vresult
&& tret
&& tret
!= Type::tvoid
)
1624 { VarDeclaration
*v
;
1626 v
= new VarDeclaration(loc
, tret
, Id::result
, NULL
);
1631 v
->parent
= sc
->func
;
1632 sc
->func
->vresult
= v
;
1635 /* Turn body into the function literal:
1636 * int delegate(ref T arg) { body }
1638 args
= new Arguments();
1639 for (i
= 0; i
< dim
; i
++)
1640 { Argument
*arg
= (Argument
*)arguments
->data
[i
];
1642 arg
->type
= arg
->type
->semantic(loc
, sc
);
1643 if (arg
->storageClass
& STCref
)
1646 { // Make a copy of the ref argument so it isn't
1651 id
= Lexer::uniqueId("__applyArg", i
);
1653 ie
= new ExpInitializer(0, new IdentifierExp(0, id
));
1654 v
= new VarDeclaration(0, arg
->type
, arg
->ident
, ie
);
1655 s
= new DeclarationStatement(0, v
);
1656 body
= new CompoundStatement(loc
, s
, body
);
1658 a
= new Argument(STCref
, arg
->type
, id
, NULL
);
1661 t
= new TypeFunction(args
, Type::tint32
, 0, LINKd
);
1662 fld
= new FuncLiteralDeclaration(loc
, 0, t
, TOKdelegate
, this);
1664 flde
= new FuncExp(loc
, fld
);
1665 flde
= flde
->semantic(sc
);
1666 fld
->tookAddressOf
= 0;
1668 // Resolve any forward referenced goto's
1669 for (int i
= 0; i
< gotos
.dim
; i
++)
1670 { CompoundStatement
*cs
= (CompoundStatement
*)gotos
.data
[i
];
1671 GotoStatement
*gs
= (GotoStatement
*)cs
->statements
->data
[0];
1673 if (!gs
->label
->statement
)
1674 { // 'Promote' it to this scope, and replace with a return
1676 s
= new ReturnStatement(0, new IntegerExp(cases
.dim
+ 1));
1677 cs
->statements
->data
[0] = (void *)s
;
1681 if (tab
->ty
== Taarray
)
1684 Argument
*arg
= (Argument
*)arguments
->data
[0];
1687 if (arg
->storageClass
& STCref
)
1688 error("foreach: index cannot be ref");
1689 if (!arg
->type
->equals(taa
->index
))
1690 error("foreach: index must be type %s, not %s", taa
->index
->toChars(), arg
->type
->toChars());
1691 arg
= (Argument
*)arguments
->data
[1];
1693 if (!arg
->type
->equals(taa
->nextOf()))
1694 error("foreach: value must be type %s, not %s", taa
->nextOf()->toChars(), arg
->type
->toChars());
1697 * _aaApply(aggr, keysize, flde)
1700 fdapply
= FuncDeclaration::genCfunc(Type::tint32
, "_aaApply2",
1701 Type::tvoid
->arrayOf(), Type::tsize_t
, flde
->type
); // flde->type is not generic
1703 fdapply
= FuncDeclaration::genCfunc(Type::tint32
, "_aaApply",
1704 Type::tvoid
->arrayOf(), Type::tsize_t
, flde
->type
); // flde->type is not generic);
1705 ec
= new VarExp(0, fdapply
);
1706 Expressions
*exps
= new Expressions();
1708 size_t keysize
= taa
->index
->size();
1709 keysize
= (keysize
+ (PTRSIZE
-1)) & ~(PTRSIZE
-1);
1710 exps
->push(new IntegerExp(0, keysize
, Type::tsize_t
));
1712 e
= new CallExp(loc
, ec
, exps
);
1713 e
->type
= Type::tint32
; // don't run semantic() on e
1715 else if (tab
->ty
== Tarray
|| tab
->ty
== Tsarray
)
1718 * _aApply(aggr, flde)
1720 static char fntab
[9][3] =
1725 char fdname
[7+1+2+ sizeof(dim
)*3 + 1];
1730 case Tchar
: flag
= 0; break;
1731 case Twchar
: flag
= 3; break;
1732 case Tdchar
: flag
= 6; break;
1737 case Tchar
: flag
+= 0; break;
1738 case Twchar
: flag
+= 1; break;
1739 case Tdchar
: flag
+= 2; break;
1742 const char *r
= (op
== TOKforeach_reverse
) ? "R" : "";
1743 int j
= sprintf(fdname
, "_aApply%s%.*s%d", r
, 2, fntab
[flag
], dim
);
1744 assert(j
< sizeof(fdname
));
1745 fdapply
= FuncDeclaration::genCfunc(Type::tint32
, fdname
,
1746 Type::tvoid
->arrayOf(), flde
->type
); // flde->type is not generic
1748 ec
= new VarExp(0, fdapply
);
1749 Expressions
*exps
= new Expressions();
1750 if (tab
->ty
== Tsarray
)
1751 aggr
= aggr
->castTo(sc
, tn
->arrayOf());
1754 e
= new CallExp(loc
, ec
, exps
);
1755 e
->type
= Type::tint32
; // don't run semantic() on e
1757 else if (tab
->ty
== Tdelegate
)
1762 Expressions
*exps
= new Expressions();
1764 e
= new CallExp(loc
, aggr
, exps
);
1765 e
= e
->semantic(sc
);
1766 if (e
->type
!= Type::tint32
)
1767 error("opApply() function for %s must return an int", tab
->toChars());
1774 ec
= new DotIdExp(loc
, aggr
,
1775 (op
== TOKforeach_reverse
) ? Id::applyReverse
1777 Expressions
*exps
= new Expressions();
1779 e
= new CallExp(loc
, ec
, exps
);
1780 e
= e
->semantic(sc
);
1781 if (e
->type
!= Type::tint32
)
1782 error("opApply() function for %s must return an int", tab
->toChars());
1786 // Easy case, a clean exit from the loop
1787 s
= new ExpStatement(loc
, e
);
1789 { // Construct a switch statement around the return value
1790 // of the apply function.
1791 Statements
*a
= new Statements();
1793 // default: break; takes care of cases 0 and 1
1794 s
= new BreakStatement(0, NULL
);
1795 s
= new DefaultStatement(0, s
);
1799 for (int i
= 0; i
< cases
.dim
; i
++)
1801 s
= (Statement
*)cases
.data
[i
];
1802 s
= new CaseStatement(0, new IntegerExp(i
+ 2), s
);
1806 s
= new CompoundStatement(loc
, a
);
1807 s
= new SwitchStatement(loc
, e
, s
);
1808 s
= s
->semantic(sc
);
1814 error("foreach: %s is not an aggregate type", aggr
->type
->toChars());
1822 int ForeachStatement::hasBreak()
1827 int ForeachStatement::hasContinue()
1832 int ForeachStatement::usesEH()
1834 return body
->usesEH();
1837 int ForeachStatement::blockExit()
1838 { int result
= BEfallthru
;
1840 if (aggr
->canThrow())
1845 result
|= body
->blockExit() & ~(BEbreak
| BEcontinue
);
1850 int ForeachStatement::fallOffEnd()
1857 int ForeachStatement::comeFrom()
1860 return body
->comeFrom();
1864 void ForeachStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1866 buf
->writestring(Token::toChars(op
));
1867 buf
->writestring(" (");
1868 for (int i
= 0; i
< arguments
->dim
; i
++)
1870 Argument
*a
= (Argument
*)arguments
->data
[i
];
1872 buf
->writestring(", ");
1873 if (a
->storageClass
& STCref
)
1874 buf
->writestring((global
.params
.Dversion
== 1)
1875 ? (char*)"inout " : (char*)"ref ");
1877 a
->type
->toCBuffer(buf
, a
->ident
, hgs
);
1879 buf
->writestring(a
->ident
->toChars());
1881 buf
->writestring("; ");
1882 aggr
->toCBuffer(buf
, hgs
);
1883 buf
->writebyte(')');
1885 buf
->writebyte('{');
1888 body
->toCBuffer(buf
, hgs
);
1889 buf
->writebyte('}');
1893 /**************************** ForeachRangeStatement ***************************/
1895 ForeachRangeStatement::ForeachRangeStatement(Loc loc
, enum TOK op
, Argument
*arg
,
1896 Expression
*lwr
, Expression
*upr
, Statement
*body
)
1908 Statement
*ForeachRangeStatement::syntaxCopy()
1910 ForeachRangeStatement
*s
= new ForeachRangeStatement(loc
, op
,
1914 body
? body
->syntaxCopy() : NULL
);
1918 Statement
*ForeachRangeStatement::semantic(Scope
*sc
)
1920 //printf("ForeachRangeStatement::semantic() %p\n", this);
1922 Statement
*s
= this;
1924 lwr
= lwr
->semantic(sc
);
1925 lwr
= resolveProperties(sc
, lwr
);
1926 lwr
= lwr
->optimize(WANTvalue
);
1929 error("invalid range lower bound %s", lwr
->toChars());
1933 upr
= upr
->semantic(sc
);
1934 upr
= resolveProperties(sc
, upr
);
1935 upr
= upr
->optimize(WANTvalue
);
1938 error("invalid range upper bound %s", upr
->toChars());
1944 lwr
= lwr
->implicitCastTo(sc
, arg
->type
);
1945 upr
= upr
->implicitCastTo(sc
, arg
->type
);
1949 /* Must infer types from lwr and upr
1951 AddExp
ea(loc
, lwr
, upr
);
1953 arg
->type
= ea
.type
;
1957 if (!arg
->type
->isscalar())
1958 error("%s is not a scalar type", arg
->type
->toChars());
1960 sym
= new ScopeDsymbol();
1961 sym
->parent
= sc
->scopesym
;
1966 key
= new VarDeclaration(loc
, arg
->type
, arg
->ident
, NULL
);
1967 DeclarationExp
*de
= new DeclarationExp(loc
, key
);
1970 if (key
->storage_class
)
1971 error("foreach range: key cannot have storage class");
1974 sc
->scontinue
= this;
1975 body
= body
->semantic(sc
);
1982 int ForeachRangeStatement::hasBreak()
1987 int ForeachRangeStatement::hasContinue()
1992 int ForeachRangeStatement::usesEH()
1994 return body
->usesEH();
1997 int ForeachRangeStatement::blockExit()
1998 { int result
= BEfallthru
;
2000 if (lwr
&& lwr
->canThrow())
2002 else if (upr
&& upr
->canThrow())
2007 result
|= body
->blockExit() & ~(BEbreak
| BEcontinue
);
2012 int ForeachRangeStatement::fallOffEnd()
2019 int ForeachRangeStatement::comeFrom()
2022 return body
->comeFrom();
2026 void ForeachRangeStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2028 buf
->writestring(Token::toChars(op
));
2029 buf
->writestring(" (");
2032 arg
->type
->toCBuffer(buf
, arg
->ident
, hgs
);
2034 buf
->writestring(arg
->ident
->toChars());
2036 buf
->writestring("; ");
2037 lwr
->toCBuffer(buf
, hgs
);
2038 buf
->writestring(" .. ");
2039 upr
->toCBuffer(buf
, hgs
);
2040 buf
->writebyte(')');
2042 buf
->writebyte('{');
2045 body
->toCBuffer(buf
, hgs
);
2046 buf
->writebyte('}');
2050 /******************************** IfStatement ***************************/
2052 IfStatement::IfStatement(Loc loc
, Argument
*arg
, Expression
*condition
, Statement
*ifbody
, Statement
*elsebody
)
2056 this->condition
= condition
;
2057 this->ifbody
= ifbody
;
2058 this->elsebody
= elsebody
;
2062 Statement
*IfStatement::syntaxCopy()
2064 Statement
*i
= NULL
;
2066 i
= ifbody
->syntaxCopy();
2068 Statement
*e
= NULL
;
2070 e
= elsebody
->syntaxCopy();
2072 Argument
*a
= arg
? arg
->syntaxCopy() : NULL
;
2073 IfStatement
*s
= new IfStatement(loc
, a
, condition
->syntaxCopy(), i
, e
);
2077 Statement
*IfStatement::semantic(Scope
*sc
)
2079 condition
= condition
->semantic(sc
);
2080 condition
= resolveProperties(sc
, condition
);
2081 condition
= condition
->checkToBoolean();
2083 // If we can short-circuit evaluate the if statement, don't do the
2084 // semantic analysis of the skipped code.
2085 // This feature allows a limited form of conditional compilation.
2086 condition
= condition
->optimize(WANTflags
);
2088 // Evaluate at runtime
2089 unsigned cs0
= sc
->callSuper
;
2094 { /* Declare arg, which we will set to be the
2095 * result of condition.
2097 ScopeDsymbol
*sym
= new ScopeDsymbol();
2098 sym
->parent
= sc
->scopesym
;
2099 scd
= sc
->push(sym
);
2101 Type
*t
= arg
->type
? arg
->type
: condition
->type
;
2102 match
= new VarDeclaration(loc
, t
->maybe(true), arg
->ident
, NULL
);
2104 match
->semantic(scd
);
2105 if (!scd
->insert(match
))
2107 match
->parent
= sc
->func
;
2112 VarExp
*v
= new VarExp(0, match
);
2113 condition
= new AssignExp(loc
, v
, condition
);
2114 condition
= condition
->semantic(scd
);
2116 if (match
&& match
->type
->ty
== Tmaybe
)
2118 // Matched object cannot be null in the then block
2119 // (and isn't in scope in the else)
2120 match
->type
= match
->type
->nextOf();
2125 ifbody
= ifbody
->semantic(scd
);
2128 cs1
= sc
->callSuper
;
2129 sc
->callSuper
= cs0
;
2131 elsebody
= elsebody
->semanticScope(sc
, NULL
, NULL
);
2132 sc
->mergeCallSuper(loc
, cs1
);
2137 int IfStatement::usesEH()
2139 return (ifbody
&& ifbody
->usesEH()) || (elsebody
&& elsebody
->usesEH());
2142 int IfStatement::blockExit()
2144 //printf("IfStatement::blockExit(%p)\n", this);
2146 int result
= BEnone
;
2147 if (condition
->canThrow())
2150 result
|= ifbody
->blockExit();
2152 result
|= BEfallthru
;
2154 result
|= elsebody
->blockExit();
2156 result
|= BEfallthru
;
2157 //printf("IfStatement::blockExit(%p) = x%x\n", this, result);
2161 int IfStatement::fallOffEnd()
2163 if (!ifbody
|| ifbody
->fallOffEnd() ||
2164 !elsebody
|| elsebody
->fallOffEnd())
2170 void IfStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2172 buf
->writestring("if (");
2176 arg
->type
->toCBuffer(buf
, arg
->ident
, hgs
);
2178 buf
->writestring(arg
->ident
->toChars());
2179 buf
->writebyte(';');
2181 condition
->toCBuffer(buf
, hgs
);
2182 buf
->writebyte(')');
2184 ifbody
->toCBuffer(buf
, hgs
);
2186 { buf
->writestring("else");
2188 elsebody
->toCBuffer(buf
, hgs
);
2192 /******************************** ConditionalStatement ***************************/
2194 ConditionalStatement::ConditionalStatement(Loc loc
, Condition
*condition
, Statement
*ifbody
, Statement
*elsebody
)
2197 this->condition
= condition
;
2198 this->ifbody
= ifbody
;
2199 this->elsebody
= elsebody
;
2202 Statement
*ConditionalStatement::syntaxCopy()
2204 Statement
*e
= NULL
;
2206 e
= elsebody
->syntaxCopy();
2207 ConditionalStatement
*s
= new ConditionalStatement(loc
,
2208 condition
->syntaxCopy(), ifbody
->syntaxCopy(), e
);
2212 Statement
*ConditionalStatement::semantic(Scope
*sc
)
2214 //printf("ConditionalStatement::semantic()\n");
2216 // If we can short-circuit evaluate the if statement, don't do the
2217 // semantic analysis of the skipped code.
2218 // This feature allows a limited form of conditional compilation.
2219 if (condition
->include(sc
, NULL
))
2221 ifbody
= ifbody
->semantic(sc
);
2227 elsebody
= elsebody
->semantic(sc
);
2232 Statements
*ConditionalStatement::flatten(Scope
*sc
)
2236 if (condition
->include(sc
, NULL
))
2241 Statements
*a
= new Statements();
2246 int ConditionalStatement::usesEH()
2248 return (ifbody
&& ifbody
->usesEH()) || (elsebody
&& elsebody
->usesEH());
2251 void ConditionalStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2253 condition
->toCBuffer(buf
, hgs
);
2256 ifbody
->toCBuffer(buf
, hgs
);
2259 buf
->writestring("else");
2261 elsebody
->toCBuffer(buf
, hgs
);
2267 /******************************** PragmaStatement ***************************/
2269 PragmaStatement::PragmaStatement(Loc loc
, Identifier
*ident
, Expressions
*args
, Statement
*body
)
2272 this->ident
= ident
;
2277 Statement
*PragmaStatement::syntaxCopy()
2279 Statement
*b
= NULL
;
2281 b
= body
->syntaxCopy();
2282 PragmaStatement
*s
= new PragmaStatement(loc
,
2283 ident
, Expression::arraySyntaxCopy(args
), b
);
2287 Statement
*PragmaStatement::semantic(Scope
*sc
)
2288 { // Should be merged with PragmaDeclaration
2289 //printf("PragmaStatement::semantic() %s\n", toChars());
2290 //printf("body = %p\n", body);
2291 if (ident
== Id::msg
)
2295 for (size_t i
= 0; i
< args
->dim
; i
++)
2297 Expression
*e
= (Expression
*)args
->data
[i
];
2299 e
= e
->semantic(sc
);
2300 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2301 if (e
->op
== TOKstring
)
2303 StringExp
*se
= (StringExp
*)e
;
2304 fprintf(stdmsg
, "%.*s", (int)se
->len
, se
->string
);
2307 error("string expected for message, not '%s'", e
->toChars());
2309 fprintf(stdmsg
, "\n");
2312 else if (ident
== Id::lib
)
2314 if (!args
|| args
->dim
!= 1)
2315 error("string expected for library name");
2318 Expression
*e
= (Expression
*)args
->data
[0];
2320 e
= e
->semantic(sc
);
2321 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2322 args
->data
[0] = (void *)e
;
2323 if (e
->op
!= TOKstring
)
2324 error("string expected for library name, not '%s'", e
->toChars());
2325 else if (global
.params
.verbose
)
2327 StringExp
*se
= (StringExp
*)e
;
2328 char *name
= (char *)mem
.malloc(se
->len
+ 1);
2329 memcpy(name
, se
->string
, se
->len
);
2331 printf("library %s\n", name
);
2336 else if (ident
== Id::startaddress
)
2338 if (!args
|| args
->dim
!= 1)
2339 error("function name expected for start address");
2342 Expression
*e
= (Expression
*)args
->data
[0];
2343 e
= e
->semantic(sc
);
2344 e
= e
->optimize(WANTvalue
| WANTinterpret
);
2345 args
->data
[0] = (void *)e
;
2346 Dsymbol
*sa
= getDsymbol(e
);
2347 if (!sa
|| !sa
->isFuncDeclaration())
2348 error("function name expected for start address, not '%s'", e
->toChars());
2351 body
= body
->semantic(sc
);
2357 error("unrecognized pragma(%s)", ident
->toChars());
2361 body
= body
->semantic(sc
);
2366 int PragmaStatement::usesEH()
2368 return body
&& body
->usesEH();
2371 int PragmaStatement::blockExit()
2373 int result
= BEfallthru
;
2374 #if 0 // currently, no code is generated for Pragma's, so it's just fallthru
2375 if (arrayExpressionCanThrow(args
))
2378 result
|= body
->blockExit();
2383 int PragmaStatement::fallOffEnd()
2386 return body
->fallOffEnd();
2390 void PragmaStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2392 buf
->writestring("pragma (");
2393 buf
->writestring(ident
->toChars());
2394 if (args
&& args
->dim
)
2396 buf
->writestring(", ");
2397 argsToCBuffer(buf
, args
, hgs
);
2399 buf
->writeByte(')');
2403 buf
->writeByte('{');
2406 body
->toCBuffer(buf
, hgs
);
2408 buf
->writeByte('}');
2413 buf
->writeByte(';');
2419 /******************************** LogStatement ***************************/
2421 LogStatement::LogStatement(Loc loc
, int level
, Expressions
*args
)
2424 this->level
= level
;
2428 Statement
*LogStatement::syntaxCopy()
2430 Expressions
*copied_args
= Expression::arraySyntaxCopy(args
);
2431 LogStatement
*s
= new LogStatement(loc
, level
, copied_args
);
2435 Statement
*LogStatement::semantic(Scope
*sc
)
2437 Expression
*logger
= new GetLoggerExp(loc
);
2440 for (Dsymbol
*s
= sc
->parent
; s
; s
= s
->parent
)
2442 ClassDeclaration
*cd
;
2443 StructDeclaration
*sd
;
2445 cd
= s
->isClassDeclaration();
2454 // We're a top-level function. Generate log messages from the module
2455 args
->shift(new StringExp(loc
, strdup(sc
->module
->ident
->string
)));
2457 args
->shift(new StringExp(loc
, type
->toChars()));
2460 args
->shift(new IntegerExp(loc
, level
, Type::tint32
));
2461 Expression
*callLogger
= new CallExp(loc
, logger
, args
);
2463 Statement
*s
= new ExpStatement(loc
, callLogger
);
2465 return s
->semantic(sc
);
2468 void LogStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2472 case 0: l
= "log_debug"; break;
2473 case 1: l
= "log_info"; break;
2474 case 2: l
= "log_warning"; break;
2475 case 3: l
= "log_error"; break;
2477 error("Unknown log level %d", level
);
2480 buf
->writestring(l
);
2481 buf
->writeByte('(');
2482 argsToCBuffer(buf
, args
, hgs
);
2483 buf
->writeByte(')');
2487 /******************************** StaticAssertStatement ***************************/
2489 StaticAssertStatement::StaticAssertStatement(StaticAssert
*sa
)
2490 : Statement(sa
->loc
)
2495 Statement
*StaticAssertStatement::syntaxCopy()
2497 StaticAssertStatement
*s
= new StaticAssertStatement((StaticAssert
*)sa
->syntaxCopy(NULL
));
2501 Statement
*StaticAssertStatement::semantic(Scope
*sc
)
2507 void StaticAssertStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2509 sa
->toCBuffer(buf
, hgs
);
2513 /******************************** SwitchStatement ***************************/
2515 SwitchStatement::SwitchStatement(Loc loc
, Expression
*c
, Statement
*b
)
2527 Statement
*SwitchStatement::syntaxCopy()
2529 SwitchStatement
*s
= new SwitchStatement(loc
,
2530 condition
->syntaxCopy(), body
->syntaxCopy());
2534 Statement
*SwitchStatement::semantic(Scope
*sc
)
2536 //printf("SwitchStatement::semantic(%p)\n", this);
2538 assert(!cases
); // ensure semantic() is only run once
2539 condition
= condition
->semantic(sc
);
2540 condition
= resolveProperties(sc
, condition
);
2541 if (condition
->type
->isString())
2543 // If it's not an array, cast it to one
2544 if (condition
->type
->ty
!= Tarray
)
2546 condition
= condition
->implicitCastTo(sc
, condition
->type
->nextOf()->arrayOf());
2548 condition
->type
= condition
->type
->constOf();
2551 { condition
= condition
->integralPromotions(sc
);
2552 condition
->checkIntegral();
2554 condition
= condition
->optimize(WANTvalue
);
2560 cases
= new Array();
2561 sc
->noctor
++; // BUG: should use Scope::mergeCallSuper() for each case instead
2562 body
= body
->semantic(sc
);
2565 // Resolve any goto case's with exp
2566 for (int i
= 0; i
< gotoCases
.dim
; i
++)
2568 GotoCaseStatement
*gcs
= (GotoCaseStatement
*)gotoCases
.data
[i
];
2572 gcs
->error("no case statement following goto case;");
2576 for (Scope
*scx
= sc
; scx
; scx
= scx
->enclosing
)
2580 for (int j
= 0; j
< scx
->sw
->cases
->dim
; j
++)
2582 CaseStatement
*cs
= (CaseStatement
*)scx
->sw
->cases
->data
[j
];
2584 if (cs
->exp
->equals(gcs
->exp
))
2591 gcs
->error("case %s not found", gcs
->exp
->toChars());
2597 if (!sc
->sw
->sdefault
)
2600 if (global
.params
.warnings
)
2601 { fprintf(stdmsg
, "warning - ");
2602 error("switch statement has no default");
2605 // Generate runtime error if the default is hit
2606 Statements
*a
= new Statements();
2607 CompoundStatement
*cs
;
2610 if (global
.params
.useSwitchError
)
2611 s
= new SwitchErrorStatement(loc
);
2613 { Expression
*e
= new HaltExp(loc
);
2614 s
= new ExpStatement(loc
, e
);
2619 a
->push(new BreakStatement(loc
, NULL
));
2620 sc
->sw
->sdefault
= new DefaultStatement(loc
, s
);
2621 a
->push(sc
->sw
->sdefault
);
2622 cs
= new CompoundStatement(loc
, a
);
2630 int SwitchStatement::hasBreak()
2635 int SwitchStatement::usesEH()
2637 return body
? body
->usesEH() : 0;
2640 int SwitchStatement::blockExit()
2641 { int result
= BEnone
;
2642 if (condition
->canThrow())
2646 { result
|= body
->blockExit();
2647 if (result
& BEbreak
)
2648 { result
|= BEfallthru
;
2653 result
|= BEfallthru
;
2658 int SwitchStatement::fallOffEnd()
2662 return TRUE
; // need to do this better
2665 void SwitchStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2667 buf
->writestring("switch (");
2668 condition
->toCBuffer(buf
, hgs
);
2669 buf
->writebyte(')');
2673 if (!body
->isScopeStatement())
2674 { buf
->writebyte('{');
2676 body
->toCBuffer(buf
, hgs
);
2677 buf
->writebyte('}');
2682 body
->toCBuffer(buf
, hgs
);
2687 /******************************** CaseStatement ***************************/
2689 CaseStatement::CaseStatement(Loc loc
, Expression
*exp
, Statement
*s
)
2693 this->statement
= s
;
2698 Statement
*CaseStatement::syntaxCopy()
2700 CaseStatement
*s
= new CaseStatement(loc
, exp
->syntaxCopy(), statement
->syntaxCopy());
2704 Statement
*CaseStatement::semantic(Scope
*sc
)
2705 { SwitchStatement
*sw
= sc
->sw
;
2707 //printf("CaseStatement::semantic() %s\n", toChars());
2708 exp
= exp
->semantic(sc
);
2711 exp
= exp
->implicitCastTo(sc
, sw
->condition
->type
);
2712 exp
= exp
->optimize(WANTvalue
| WANTinterpret
);
2714 /* This is where variables are allowed as case expressions.
2716 if (exp
->op
== TOKvar
)
2717 { VarExp
*ve
= (VarExp
*)exp
;
2718 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
2719 Type
*t
= exp
->type
->toBasetype();
2720 if (v
&& (t
->isintegral() || t
->ty
== Tclass
))
2721 { /* Flag that we need to do special code generation
2722 * for this, i.e. generate a sequence of if-then-else
2729 if (exp
->op
!= TOKstring
&& exp
->op
!= TOKint64
)
2731 error("case must be a string or an integral constant, not %s", exp
->toChars());
2732 exp
= new IntegerExp(0);
2736 for (int i
= 0; i
< sw
->cases
->dim
; i
++)
2738 CaseStatement
*cs
= (CaseStatement
*)sw
->cases
->data
[i
];
2740 //printf("comparing '%s' with '%s'\n", exp->toChars(), cs->exp->toChars());
2741 if (cs
->exp
->equals(exp
))
2742 { error("duplicate case %s in switch statement", exp
->toChars());
2747 sw
->cases
->push(this);
2749 // Resolve any goto case's with no exp to this case statement
2750 for (int i
= 0; i
< sw
->gotoCases
.dim
; i
++)
2752 GotoCaseStatement
*gcs
= (GotoCaseStatement
*)sw
->gotoCases
.data
[i
];
2757 sw
->gotoCases
.remove(i
); // remove from array
2761 if (sc
->sw
->tf
!= sc
->tf
)
2762 error("switch and case are in different finally blocks");
2765 error("case not in switch statement");
2766 statement
= statement
->semantic(sc
);
2770 int CaseStatement::compare(Object
*obj
)
2772 // Sort cases so we can do an efficient lookup
2773 CaseStatement
*cs2
= (CaseStatement
*)(obj
);
2775 return exp
->compare(cs2
->exp
);
2778 int CaseStatement::usesEH()
2780 return statement
->usesEH();
2783 int CaseStatement::blockExit()
2789 int CaseStatement::fallOffEnd()
2791 return statement
->fallOffEnd();
2794 int CaseStatement::comeFrom()
2799 void CaseStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2801 buf
->writestring("case ");
2802 exp
->toCBuffer(buf
, hgs
);
2803 buf
->writebyte(':');
2805 statement
->toCBuffer(buf
, hgs
);
2808 /******************************** DefaultStatement ***************************/
2810 DefaultStatement::DefaultStatement(Loc loc
, Statement
*s
)
2813 this->statement
= s
;
2819 Statement
*DefaultStatement::syntaxCopy()
2821 DefaultStatement
*s
= new DefaultStatement(loc
, statement
->syntaxCopy());
2825 Statement
*DefaultStatement::semantic(Scope
*sc
)
2827 //printf("DefaultStatement::semantic()\n");
2830 if (sc
->sw
->sdefault
)
2832 error("switch statement already has a default");
2834 sc
->sw
->sdefault
= this;
2836 if (sc
->sw
->tf
!= sc
->tf
)
2837 error("switch and default are in different finally blocks");
2840 error("default not in switch statement");
2841 statement
= statement
->semantic(sc
);
2845 int DefaultStatement::usesEH()
2847 return statement
->usesEH();
2850 int DefaultStatement::blockExit()
2856 int DefaultStatement::fallOffEnd()
2858 return statement
->fallOffEnd();
2861 int DefaultStatement::comeFrom()
2866 void DefaultStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2868 buf
->writestring("default:\n");
2869 statement
->toCBuffer(buf
, hgs
);
2872 /******************************** GotoDefaultStatement ***************************/
2874 GotoDefaultStatement::GotoDefaultStatement(Loc loc
)
2880 Statement
*GotoDefaultStatement::syntaxCopy()
2882 GotoDefaultStatement
*s
= new GotoDefaultStatement(loc
);
2886 Statement
*GotoDefaultStatement::semantic(Scope
*sc
)
2890 error("goto default not in switch statement");
2894 int GotoDefaultStatement::blockExit()
2899 int GotoDefaultStatement::fallOffEnd()
2904 void GotoDefaultStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2906 buf
->writestring("goto default;\n");
2909 /******************************** GotoCaseStatement ***************************/
2911 GotoCaseStatement::GotoCaseStatement(Loc loc
, Expression
*exp
)
2918 Statement
*GotoCaseStatement::syntaxCopy()
2920 Expression
*e
= exp
? exp
->syntaxCopy() : NULL
;
2921 GotoCaseStatement
*s
= new GotoCaseStatement(loc
, e
);
2925 Statement
*GotoCaseStatement::semantic(Scope
*sc
)
2928 exp
= exp
->semantic(sc
);
2931 error("goto case not in switch statement");
2934 sc
->sw
->gotoCases
.push(this);
2937 exp
= exp
->implicitCastTo(sc
, sc
->sw
->condition
->type
);
2938 exp
= exp
->optimize(WANTvalue
);
2944 int GotoCaseStatement::blockExit()
2949 int GotoCaseStatement::fallOffEnd()
2954 void GotoCaseStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2956 buf
->writestring("goto case");
2958 { buf
->writebyte(' ');
2959 exp
->toCBuffer(buf
, hgs
);
2961 buf
->writebyte(';');
2965 /******************************** SwitchErrorStatement ***************************/
2967 SwitchErrorStatement::SwitchErrorStatement(Loc loc
)
2972 int SwitchErrorStatement::blockExit()
2977 int SwitchErrorStatement::fallOffEnd()
2982 void SwitchErrorStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2984 buf
->writestring("SwitchErrorStatement::toCBuffer()");
2988 /******************************** ReturnStatement ***************************/
2990 ReturnStatement::ReturnStatement(Loc loc
, Expression
*exp
)
2996 Statement
*ReturnStatement::syntaxCopy()
2998 Expression
*e
= NULL
;
3000 e
= exp
->syntaxCopy();
3001 ReturnStatement
*s
= new ReturnStatement(loc
, e
);
3005 Statement
*ReturnStatement::semantic(Scope
*sc
)
3007 //printf("ReturnStatement::semantic() %s\n", toChars());
3009 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
3015 // Find scope of function foreach is in
3016 for (; 1; scx
= scx
->enclosing
)
3019 if (scx
->func
!= fd
)
3020 { fd
= scx
->func
; // fd is now function enclosing foreach
3026 Type
*tret
= fd
->type
->nextOf();
3028 tret
= fd
->tintro
->nextOf();
3032 tbret
= tret
->toBasetype();
3034 // main() returns 0, even if it returns void
3035 if (!exp
&& (!tbret
|| tbret
->ty
== Tvoid
) && fd
->isMain())
3037 exp
= new IntegerExp(0);
3040 if (sc
->incontract
|| scx
->incontract
)
3041 error("return statements cannot be in contracts");
3042 if (sc
->tf
|| scx
->tf
)
3043 error("return statements cannot be in finally, scope(exit) or scope(success) bodies");
3045 if (fd
->isCtorDeclaration())
3047 // Constructors implicitly do:
3049 if (exp
&& exp
->op
!= TOKthis
)
3050 error("cannot return expression from constructor");
3051 exp
= new ThisExp(0);
3059 fd
->hasReturnExp
|= 1;
3061 exp
= exp
->semantic(sc
);
3062 exp
= resolveProperties(sc
, exp
);
3063 exp
= exp
->optimize(WANTvalue
);
3065 if (fd
->nrvo_can
&& exp
->op
== TOKvar
)
3066 { VarExp
*ve
= (VarExp
*)exp
;
3067 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
3069 if (!v
|| v
->isOut() || v
->isRef())
3071 else if (tbret
->ty
== Tstruct
&& ((TypeStruct
*)tbret
)->sym
->dtor
)
3072 // Struct being returned has destructors
3074 else if (fd
->nrvo_var
== NULL
)
3075 { if (!v
->isDataseg() && !v
->isParameter() && v
->toParent2() == fd
)
3076 { //printf("Setting nrvo to %s\n", v->toChars());
3082 else if (fd
->nrvo_var
!= v
)
3088 if (fd
->returnLabel
&& tbret
->ty
!= Tvoid
)
3091 else if (fd
->inferRetType
)
3093 if (fd
->type
->nextOf())
3095 if (!exp
->type
->equals(fd
->type
->nextOf()))
3096 error("mismatched function return type inference of %s and %s",
3097 exp
->type
->toChars(), fd
->type
->nextOf()->toChars());
3101 ((TypeFunction
*)fd
->type
)->next
= exp
->type
;
3102 fd
->type
= fd
->type
->semantic(loc
, sc
);
3104 { tret
= fd
->type
->nextOf();
3105 tbret
= tret
->toBasetype();
3109 else if (tbret
->ty
!= Tvoid
)
3111 exp
= exp
->implicitCastTo(sc
, tret
);
3113 else if (exp
->type
->ty
!= Tvoid
)
3115 error("attempt to return %s from a function declared to return void", exp
->type
->toChars());
3118 else if (fd
->inferRetType
)
3120 if (fd
->type
->nextOf())
3122 if (fd
->type
->nextOf()->ty
!= Tvoid
)
3123 error("mismatched function return type inference of void and %s",
3124 fd
->type
->nextOf()->toChars());
3128 ((TypeFunction
*)fd
->type
)->next
= Type::tvoid
;
3129 fd
->type
= fd
->type
->semantic(loc
, sc
);
3131 { tret
= Type::tvoid
;
3136 else if (tbret
->ty
!= Tvoid
) // if non-void return
3137 error("return expression expected");
3143 if (exp
&& !implicit0
)
3145 exp
= exp
->implicitCastTo(sc
, tret
);
3147 if (!exp
|| exp
->op
== TOKint64
|| exp
->op
== TOKfloat64
||
3148 exp
->op
== TOKimaginary80
|| exp
->op
== TOKcomplex80
||
3149 exp
->op
== TOKthis
|| exp
->op
== TOKsuper
|| exp
->op
== TOKnull
||
3150 exp
->op
== TOKstring
)
3152 sc
->fes
->cases
.push(this);
3153 s
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
3155 else if (fd
->type
->nextOf()->toBasetype() == Type::tvoid
)
3160 s
= new ReturnStatement(0, NULL
);
3161 sc
->fes
->cases
.push(s
);
3163 // Construct: { exp; return cases.dim + 1; }
3164 s1
= new ExpStatement(loc
, exp
);
3165 s2
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
3166 s
= new CompoundStatement(loc
, s1
, s2
);
3174 // Construct: return vresult;
3176 { VarDeclaration
*v
;
3178 v
= new VarDeclaration(loc
, tret
, Id::result
, NULL
);
3181 if (!scx
->insert(v
))
3187 v
= new VarExp(0, fd
->vresult
);
3188 s
= new ReturnStatement(0, v
);
3189 sc
->fes
->cases
.push(s
);
3191 // Construct: { vresult = exp; return cases.dim + 1; }
3192 v
= new VarExp(0, fd
->vresult
);
3193 exp
= new AssignExp(loc
, v
, exp
);
3194 exp
= exp
->semantic(sc
);
3195 s1
= new ExpStatement(loc
, exp
);
3196 s2
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
3197 s
= new CompoundStatement(loc
, s1
, s2
);
3204 if (fd
->returnLabel
&& tbret
->ty
!= Tvoid
)
3206 assert(fd
->vresult
);
3207 VarExp
*v
= new VarExp(0, fd
->vresult
);
3209 exp
= new AssignExp(loc
, v
, exp
);
3210 exp
= exp
->semantic(sc
);
3217 /* BUG: need to issue an error on:
3224 if (sc
->callSuper
& CSXany_ctor
&&
3225 !(sc
->callSuper
& (CSXthis_ctor
| CSXsuper_ctor
)))
3226 error("return without calling constructor");
3228 sc
->callSuper
|= CSXreturn
;
3230 // See if all returns are instead to be replaced with a goto returnLabel;
3231 if (fd
->returnLabel
)
3233 GotoStatement
*gs
= new GotoStatement(loc
, Id::returnLabel
);
3235 gs
->label
= fd
->returnLabel
;
3239 s
= new ExpStatement(0, exp
);
3240 return new CompoundStatement(loc
, s
, gs
);
3245 if (exp
&& tbret
->ty
== Tvoid
&& !fd
->isMain())
3248 s
= new ExpStatement(loc
, exp
);
3251 return new CompoundStatement(loc
, s
, this);
3257 int ReturnStatement::blockExit()
3258 { int result
= BEreturn
;
3260 if (exp
&& exp
->canThrow())
3265 int ReturnStatement::fallOffEnd()
3270 void ReturnStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3272 buf
->printf("return ");
3274 exp
->toCBuffer(buf
, hgs
);
3275 buf
->writeByte(';');
3279 /******************************** BreakStatement ***************************/
3281 BreakStatement::BreakStatement(Loc loc
, Identifier
*ident
)
3284 this->ident
= ident
;
3287 Statement
*BreakStatement::syntaxCopy()
3289 BreakStatement
*s
= new BreakStatement(loc
, ident
);
3293 Statement
*BreakStatement::semantic(Scope
*sc
)
3295 //printf("BreakStatement::semantic()\n");
3297 // break Identifier;
3301 FuncDeclaration
*thisfunc
= sc
->func
;
3303 for (scx
= sc
; scx
; scx
= scx
->enclosing
)
3307 if (scx
->func
!= thisfunc
) // if in enclosing function
3309 if (sc
->fes
) // if this is the body of a foreach
3311 /* Post this statement to the fes, and replace
3312 * it with a return value that caller will put into
3313 * a switch. Caller will figure out where the break
3314 * label actually is.
3315 * Case numbers start with 2, not 0, as 0 is continue
3319 sc
->fes
->cases
.push(this);
3320 s
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
3323 break; // can't break to it
3327 if (ls
&& ls
->ident
== ident
)
3329 Statement
*s
= ls
->statement
;
3332 error("label '%s' has no break", ident
->toChars());
3333 if (ls
->tf
!= sc
->tf
)
3334 error("cannot break out of finally block");
3338 error("enclosing label '%s' for break not found", ident
->toChars());
3340 else if (!sc
->sbreak
)
3345 // Replace break; with return 1;
3346 s
= new ReturnStatement(0, new IntegerExp(1));
3349 error("break is not inside a loop or switch");
3354 int BreakStatement::blockExit()
3356 //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak);
3357 return ident
? BEgoto
: BEbreak
;
3360 int BreakStatement::fallOffEnd()
3365 void BreakStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3367 buf
->writestring("break");
3369 { buf
->writebyte(' ');
3370 buf
->writestring(ident
->toChars());
3372 buf
->writebyte(';');
3376 /******************************** ContinueStatement ***************************/
3378 ContinueStatement::ContinueStatement(Loc loc
, Identifier
*ident
)
3381 this->ident
= ident
;
3384 Statement
*ContinueStatement::syntaxCopy()
3386 ContinueStatement
*s
= new ContinueStatement(loc
, ident
);
3390 Statement
*ContinueStatement::semantic(Scope
*sc
)
3392 //printf("ContinueStatement::semantic() %p\n", this);
3396 FuncDeclaration
*thisfunc
= sc
->func
;
3398 for (scx
= sc
; scx
; scx
= scx
->enclosing
)
3402 if (scx
->func
!= thisfunc
) // if in enclosing function
3404 if (sc
->fes
) // if this is the body of a foreach
3406 for (; scx
; scx
= scx
->enclosing
)
3409 if (ls
&& ls
->ident
== ident
&& ls
->statement
== sc
->fes
)
3411 // Replace continue ident; with return 0;
3412 return new ReturnStatement(0, new IntegerExp(0));
3416 /* Post this statement to the fes, and replace
3417 * it with a return value that caller will put into
3418 * a switch. Caller will figure out where the break
3419 * label actually is.
3420 * Case numbers start with 2, not 0, as 0 is continue
3424 sc
->fes
->cases
.push(this);
3425 s
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
3428 break; // can't continue to it
3432 if (ls
&& ls
->ident
== ident
)
3434 Statement
*s
= ls
->statement
;
3436 if (!s
->hasContinue())
3437 error("label '%s' has no continue", ident
->toChars());
3438 if (ls
->tf
!= sc
->tf
)
3439 error("cannot continue out of finally block");
3443 error("enclosing label '%s' for continue not found", ident
->toChars());
3445 else if (!sc
->scontinue
)
3450 // Replace continue; with return 0;
3451 s
= new ReturnStatement(0, new IntegerExp(0));
3454 error("continue is not inside a loop");
3459 int ContinueStatement::blockExit()
3461 return ident
? BEgoto
: BEcontinue
;
3464 int ContinueStatement::fallOffEnd()
3469 void ContinueStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3471 buf
->writestring("continue");
3473 { buf
->writebyte(' ');
3474 buf
->writestring(ident
->toChars());
3476 buf
->writebyte(';');
3480 /******************************** SynchronizedStatement ***************************/
3482 SynchronizedStatement::SynchronizedStatement(Loc loc
, Expression
*exp
, Statement
*body
)
3490 SynchronizedStatement::SynchronizedStatement(Loc loc
, elem
*esync
, Statement
*body
)
3495 this->esync
= esync
;
3498 Statement
*SynchronizedStatement::syntaxCopy()
3500 Expression
*e
= exp
? exp
->syntaxCopy() : NULL
;
3501 SynchronizedStatement
*s
= new SynchronizedStatement(loc
, e
, body
? body
->syntaxCopy() : NULL
);
3505 Statement
*SynchronizedStatement::semantic(Scope
*sc
)
3508 { ClassDeclaration
*cd
;
3510 exp
= exp
->semantic(sc
);
3511 exp
= resolveProperties(sc
, exp
);
3512 cd
= exp
->type
->isClassHandle();
3514 error("can only synchronize on class objects, not '%s'", exp
->type
->toChars());
3515 else if (cd
->isInterfaceDeclaration())
3516 { Type
*t
= new TypeIdentifier(0, Id::Object
);
3518 t
= t
->semantic(0, sc
);
3519 exp
= new CastExp(loc
, exp
, t
);
3520 exp
= exp
->semantic(sc
);
3524 body
= body
->semantic(sc
);
3528 int SynchronizedStatement::hasBreak()
3530 return FALSE
; //TRUE;
3533 int SynchronizedStatement::hasContinue()
3535 return FALSE
; //TRUE;
3538 int SynchronizedStatement::usesEH()
3543 int SynchronizedStatement::blockExit()
3545 return body
? body
->blockExit() : BEfallthru
;
3548 int SynchronizedStatement::fallOffEnd()
3550 return body
? body
->fallOffEnd() : TRUE
;
3553 void SynchronizedStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3555 buf
->writestring("synchronized");
3557 { buf
->writebyte('(');
3558 exp
->toCBuffer(buf
, hgs
);
3559 buf
->writebyte(')');
3563 buf
->writebyte(' ');
3564 body
->toCBuffer(buf
, hgs
);
3568 /******************************** WithStatement ***************************/
3570 WithStatement::WithStatement(Loc loc
, Expression
*exp
, Statement
*body
)
3578 Statement
*WithStatement::syntaxCopy()
3580 WithStatement
*s
= new WithStatement(loc
, exp
->syntaxCopy(), body
? body
->syntaxCopy() : NULL
);
3584 Statement
*WithStatement::semantic(Scope
*sc
)
3585 { ScopeDsymbol
*sym
;
3588 //printf("WithStatement::semantic()\n");
3589 exp
= exp
->semantic(sc
);
3590 exp
= resolveProperties(sc
, exp
);
3591 if (exp
->op
== TOKimport
)
3592 { ScopeExp
*es
= (ScopeExp
*)exp
;
3596 else if (exp
->op
== TOKtype
)
3597 { TypeExp
*es
= (TypeExp
*)exp
;
3599 sym
= es
->type
->toDsymbol(sc
)->isScopeDsymbol();
3601 { error("%s has no members", es
->toChars());
3602 body
= body
->semantic(sc
);
3607 { Type
*t
= exp
->type
;
3610 t
= t
->toBasetype();
3611 if (t
->isClassHandle())
3613 init
= new ExpInitializer(loc
, exp
);
3614 wthis
= new VarDeclaration(loc
, exp
->type
, Id::withSym
, init
);
3615 wthis
->semantic(sc
);
3617 sym
= new WithScopeSymbol(this);
3618 sym
->parent
= sc
->scopesym
;
3620 else if (t
->ty
== Tstruct
)
3622 Expression
*e
= exp
->addressOf(sc
);
3623 init
= new ExpInitializer(loc
, e
);
3624 wthis
= new VarDeclaration(loc
, e
->type
, Id::withSym
, init
);
3625 wthis
->semantic(sc
);
3626 sym
= new WithScopeSymbol(this);
3627 sym
->parent
= sc
->scopesym
;
3630 { error("with expressions must be class objects, not '%s'", exp
->type
->toChars());
3637 body
= body
->semantic(sc
);
3644 void WithStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3646 buf
->writestring("with (");
3647 exp
->toCBuffer(buf
, hgs
);
3648 buf
->writestring(")\n");
3650 body
->toCBuffer(buf
, hgs
);
3653 int WithStatement::usesEH()
3655 return body
? body
->usesEH() : 0;
3658 int WithStatement::blockExit()
3660 int result
= BEnone
;
3661 if (exp
->canThrow())
3664 result
|= body
->blockExit();
3666 result
|= BEfallthru
;
3670 int WithStatement::fallOffEnd()
3672 return body
? body
->fallOffEnd() : TRUE
;
3675 /******************************** TryCatchStatement ***************************/
3677 TryCatchStatement::TryCatchStatement(Loc loc
, Statement
*body
, Array
*catches
)
3681 this->catches
= catches
;
3684 Statement
*TryCatchStatement::syntaxCopy()
3686 Array
*a
= new Array();
3687 a
->setDim(catches
->dim
);
3688 for (int i
= 0; i
< a
->dim
; i
++)
3691 c
= (Catch
*)catches
->data
[i
];
3692 c
= c
->syntaxCopy();
3695 TryCatchStatement
*s
= new TryCatchStatement(loc
, body
->syntaxCopy(), a
);
3699 Statement
*TryCatchStatement::semantic(Scope
*sc
)
3701 body
= body
->semanticScope(sc
, NULL
/*this*/, NULL
);
3703 /* Even if body is NULL, still do semantic analysis on catches
3705 for (size_t i
= 0; i
< catches
->dim
; i
++)
3706 { Catch
*c
= (Catch
*)catches
->data
[i
];
3709 // Determine if current catch 'hides' any previous catches
3710 for (size_t j
= 0; j
< i
; j
++)
3711 { Catch
*cj
= (Catch
*)catches
->data
[j
];
3712 char *si
= c
->loc
.toChars();
3713 char *sj
= cj
->loc
.toChars();
3715 if (c
->type
->toBasetype()->implicitConvTo(cj
->type
->toBasetype()))
3716 error("catch at %s hides catch at %s", sj
, si
);
3726 int TryCatchStatement::hasBreak()
3728 return FALSE
; //TRUE;
3731 int TryCatchStatement::usesEH()
3736 int TryCatchStatement::blockExit()
3740 result
= body
->blockExit();
3742 for (size_t i
= 0; i
< catches
->dim
; i
++)
3744 Catch
*c
= (Catch
*)catches
->data
[i
];
3745 result
|= c
->blockExit();
3750 int TryCatchStatement::fallOffEnd()
3755 result
= body
->fallOffEnd();
3756 for (int i
= 0; i
< catches
->dim
; i
++)
3759 c
= (Catch
*)catches
->data
[i
];
3761 result
|= c
->handler
->fallOffEnd();
3766 void TryCatchStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3768 buf
->writestring("try");
3771 body
->toCBuffer(buf
, hgs
);
3772 for (size_t i
= 0; i
< catches
->dim
; i
++)
3774 Catch
*c
= (Catch
*)catches
->data
[i
];
3775 c
->toCBuffer(buf
, hgs
);
3779 /******************************** Catch ***************************/
3781 Catch::Catch(Loc loc
, Type
*t
, Identifier
*id
, Statement
*handler
)
3783 //printf("Catch(%s, loc = %s)\n", id->toChars(), loc.toChars());
3787 this->handler
= handler
;
3791 Catch
*Catch::syntaxCopy()
3793 Catch
*c
= new Catch(loc
,
3794 (type
? type
->syntaxCopy() : NULL
),
3796 (handler
? handler
->syntaxCopy() : NULL
));
3800 void Catch::semantic(Scope
*sc
)
3801 { ScopeDsymbol
*sym
;
3803 //printf("Catch::semantic(%s)\n", ident->toChars());
3808 /* This is because the _d_local_unwind() gets the stack munged
3809 * up on this. The workaround is to place any try-catches into
3810 * a separate function, and call that.
3811 * To fix, have the compiler automatically convert the finally
3812 * body into a nested function.
3814 error(loc
, "cannot put catch statement inside finally block");
3818 sym
= new ScopeDsymbol();
3819 sym
->parent
= sc
->scopesym
;
3823 type
= new TypeIdentifier(0, Id::Object
);
3824 type
= type
->semantic(loc
, sc
);
3825 if (!type
->toBasetype()->isClassHandle())
3826 error("can only catch class objects, not '%s'", type
->toChars());
3829 var
= new VarDeclaration(loc
, type
, ident
, NULL
);
3830 var
->parent
= sc
->parent
;
3833 handler
= handler
->semantic(sc
);
3838 int Catch::blockExit()
3840 return handler
? handler
->blockExit() : BEfallthru
;
3843 void Catch::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3845 buf
->writestring("catch");
3847 { buf
->writebyte('(');
3848 type
->toCBuffer(buf
, ident
, hgs
);
3849 buf
->writebyte(')');
3852 buf
->writebyte('{');
3855 handler
->toCBuffer(buf
, hgs
);
3856 buf
->writebyte('}');
3860 /****************************** TryFinallyStatement ***************************/
3862 TryFinallyStatement::TryFinallyStatement(Loc loc
, Statement
*body
, Statement
*finalbody
)
3866 this->finalbody
= finalbody
;
3869 Statement
*TryFinallyStatement::syntaxCopy()
3871 TryFinallyStatement
*s
= new TryFinallyStatement(loc
,
3872 body
->syntaxCopy(), finalbody
->syntaxCopy());
3876 Statement
*TryFinallyStatement::semantic(Scope
*sc
)
3878 //printf("TryFinallyStatement::semantic()\n");
3879 body
= body
->semantic(sc
);
3883 sc
->scontinue
= NULL
; // no break or continue out of finally block
3884 finalbody
= finalbody
->semantic(sc
);
3890 if (body
->blockExit() == BEfallthru
)
3891 { Statement
*s
= new CompoundStatement(loc
, body
, finalbody
);
3897 void TryFinallyStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3899 buf
->printf("try\n{\n");
3900 body
->toCBuffer(buf
, hgs
);
3901 buf
->printf("}\nfinally\n{\n");
3902 finalbody
->toCBuffer(buf
, hgs
);
3903 buf
->writeByte('}');
3907 int TryFinallyStatement::hasBreak()
3909 return FALSE
; //TRUE;
3912 int TryFinallyStatement::hasContinue()
3914 return FALSE
; //TRUE;
3917 int TryFinallyStatement::usesEH()
3922 int TryFinallyStatement::blockExit()
3924 int result
= body
->blockExit();
3928 int TryFinallyStatement::fallOffEnd()
3931 result
= body
->fallOffEnd();
3933 // result = finalbody->fallOffEnd();
3937 /****************************** OnScopeStatement ***************************/
3939 OnScopeStatement::OnScopeStatement(Loc loc
, TOK tok
, Statement
*statement
)
3943 this->statement
= statement
;
3946 Statement
*OnScopeStatement::syntaxCopy()
3948 OnScopeStatement
*s
= new OnScopeStatement(loc
,
3949 tok
, statement
->syntaxCopy());
3953 Statement
*OnScopeStatement::semantic(Scope
*sc
)
3955 /* semantic is called on results of scopeCode() */
3959 int OnScopeStatement::blockExit()
3960 { // At this point, this statement is just an empty placeholder
3964 void OnScopeStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3966 buf
->writestring(Token::toChars(tok
));
3967 buf
->writebyte(' ');
3968 statement
->toCBuffer(buf
, hgs
);
3971 int OnScopeStatement::usesEH()
3976 void OnScopeStatement::scopeCode(Scope
*sc
, Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
3978 //printf("OnScopeStatement::scopeCode()\n");
3985 case TOKon_scope_exit
:
3986 *sfinally
= statement
;
3989 case TOKon_scope_failure
:
3990 *sexception
= statement
;
3993 case TOKon_scope_success
:
3996 * sentry: int x = 0;
3997 * sexception: x = 1;
3998 * sfinally: if (!x) statement;
4000 Identifier
*id
= Lexer::uniqueId("__os");
4002 ExpInitializer
*ie
= new ExpInitializer(loc
, new IntegerExp(0));
4003 VarDeclaration
*v
= new VarDeclaration(loc
, Type::tint32
, id
, ie
);
4004 *sentry
= new DeclarationStatement(loc
, v
);
4006 Expression
*e
= new IntegerExp(1);
4007 e
= new AssignExp(0, new VarExp(0, v
), e
);
4008 *sexception
= new ExpStatement(0, e
);
4010 e
= new VarExp(0, v
);
4011 e
= new NotExp(0, e
);
4012 *sfinally
= new IfStatement(0, NULL
, e
, statement
, NULL
);
4022 /******************************** ThrowStatement ***************************/
4024 ThrowStatement::ThrowStatement(Loc loc
, Expression
*exp
)
4030 Statement
*ThrowStatement::syntaxCopy()
4032 ThrowStatement
*s
= new ThrowStatement(loc
, exp
->syntaxCopy());
4036 Statement
*ThrowStatement::semantic(Scope
*sc
)
4038 //printf("ThrowStatement::semantic()\n");
4040 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
4041 fd
->hasReturnExp
|= 2;
4044 error("Throw statements cannot be in contracts");
4045 exp
= exp
->semantic(sc
);
4046 exp
= resolveProperties(sc
, exp
);
4047 if (!exp
->type
->toBasetype()->isClassHandle())
4048 error("can only throw class objects, not type %s", exp
->type
->toChars());
4052 int ThrowStatement::blockExit()
4054 return BEthrow
; // obviously
4057 int ThrowStatement::fallOffEnd()
4062 void ThrowStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4064 buf
->printf("throw ");
4065 exp
->toCBuffer(buf
, hgs
);
4066 buf
->writeByte(';');
4070 /******************************** VolatileStatement **************************/
4072 VolatileStatement::VolatileStatement(Loc loc
, Statement
*statement
)
4075 this->statement
= statement
;
4078 Statement
*VolatileStatement::syntaxCopy()
4080 VolatileStatement
*s
= new VolatileStatement(loc
,
4081 statement
? statement
->syntaxCopy() : NULL
);
4085 Statement
*VolatileStatement::semantic(Scope
*sc
)
4088 statement
= statement
->semantic(sc
);
4092 Statements
*VolatileStatement::flatten(Scope
*sc
)
4096 a
= statement
? statement
->flatten(sc
) : NULL
;
4098 { for (int i
= 0; i
< a
->dim
; i
++)
4099 { Statement
*s
= (Statement
*)a
->data
[i
];
4101 s
= new VolatileStatement(loc
, s
);
4109 int VolatileStatement::blockExit()
4111 return statement
? statement
->blockExit() : BEfallthru
;
4114 int VolatileStatement::fallOffEnd()
4116 return statement
? statement
->fallOffEnd() : TRUE
;
4119 void VolatileStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4121 buf
->writestring("volatile");
4123 { if (statement
->isScopeStatement())
4126 buf
->writebyte(' ');
4127 statement
->toCBuffer(buf
, hgs
);
4132 /******************************** GotoStatement ***************************/
4134 GotoStatement::GotoStatement(Loc loc
, Identifier
*ident
)
4137 this->ident
= ident
;
4142 Statement
*GotoStatement::syntaxCopy()
4144 GotoStatement
*s
= new GotoStatement(loc
, ident
);
4148 Statement
*GotoStatement::semantic(Scope
*sc
)
4149 { FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
4151 //printf("GotoStatement::semantic()\n");
4153 label
= fd
->searchLabel(ident
);
4154 if (!label
->statement
&& sc
->fes
)
4156 /* Either the goto label is forward referenced or it
4157 * is in the function that the enclosing foreach is in.
4158 * Can't know yet, so wrap the goto in a compound statement
4159 * so we can patch it later, and add it to a 'look at this later'
4162 Statements
*a
= new Statements();
4166 s
= new CompoundStatement(loc
, a
);
4167 sc
->fes
->gotos
.push(s
); // 'look at this later' list
4170 if (label
->statement
&& label
->statement
->tf
!= sc
->tf
)
4171 error("cannot goto in or out of finally block");
4175 int GotoStatement::blockExit()
4177 //printf("GotoStatement::blockExit(%p)\n", this);
4181 int GotoStatement::fallOffEnd()
4186 void GotoStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4188 buf
->writestring("goto ");
4189 buf
->writestring(ident
->toChars());
4190 buf
->writebyte(';');
4194 /******************************** LabelStatement ***************************/
4196 LabelStatement::LabelStatement(Loc loc
, Identifier
*ident
, Statement
*statement
)
4199 this->ident
= ident
;
4200 this->statement
= statement
;
4202 this->lblock
= NULL
;
4203 this->isReturnLabel
= 0;
4206 Statement
*LabelStatement::syntaxCopy()
4208 LabelStatement
*s
= new LabelStatement(loc
, ident
, statement
->syntaxCopy());
4212 Statement
*LabelStatement::semantic(Scope
*sc
)
4214 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
4216 //printf("LabelStatement::semantic()\n");
4217 ls
= fd
->searchLabel(ident
);
4219 error("Label '%s' already defined", ls
->toChars());
4221 ls
->statement
= this;
4224 sc
->scopesym
= sc
->enclosing
->scopesym
;
4225 sc
->callSuper
|= CSXlabel
;
4228 statement
= statement
->semantic(sc
);
4233 Statements
*LabelStatement::flatten(Scope
*sc
)
4235 Statements
*a
= NULL
;
4239 a
= statement
->flatten(sc
);
4244 a
->push(new ExpStatement(loc
, NULL
));
4246 Statement
*s
= (Statement
*)a
->data
[0];
4248 s
= new LabelStatement(loc
, ident
, s
);
4257 int LabelStatement::usesEH()
4259 return statement
? statement
->usesEH() : FALSE
;
4262 int LabelStatement::blockExit()
4264 //printf("LabelStatement::blockExit(%p)\n", this);
4265 return statement
? statement
->blockExit() : BEfallthru
;
4268 int LabelStatement::fallOffEnd()
4270 return statement
? statement
->fallOffEnd() : TRUE
;
4273 int LabelStatement::comeFrom()
4275 //printf("LabelStatement::comeFrom()\n");
4279 void LabelStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
4281 buf
->writestring(ident
->toChars());
4282 buf
->writebyte(':');
4285 statement
->toCBuffer(buf
, hgs
);
4289 /******************************** LabelDsymbol ***************************/
4291 LabelDsymbol::LabelDsymbol(Identifier
*ident
)
4300 LabelDsymbol
*LabelDsymbol::isLabel() // is this a LabelDsymbol()?