2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2007 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"
36 /******************************** Statement ***************************/
38 Statement::Statement(Loc loc
)
42 // If this is an in{} contract scope statement (skip for determining
43 // inlineStatus of a function body for header content)
48 Statement
*Statement::syntaxCopy()
54 void Statement::print()
56 fprintf(stdmsg
, "%s\n", toChars());
60 char *Statement::toChars()
64 buf
= new OutBuffer();
66 return buf
->toChars();
69 void Statement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
71 buf
->printf("Statement::toCBuffer()");
75 Statement
*Statement::semantic(Scope
*sc
)
80 // Same as semantic(), but do create a new scope
82 Statement
*Statement::semanticScope(Scope
*sc
, Statement
*sbreak
, Statement
*scontinue
)
90 scd
->scontinue
= scontinue
;
96 void Statement::error(const char *format
, ...)
100 ::verror(loc
, format
, ap
);
104 int Statement::hasBreak()
106 //printf("Statement::hasBreak()\n");
110 int Statement::hasContinue()
115 // TRUE if statement uses exception handling
117 int Statement::usesEH()
122 // TRUE if statement may fall off the end without a throw or return
124 int Statement::fallOffEnd()
129 // TRUE if statement 'comes from' somewhere else, like a goto
131 int Statement::comeFrom()
133 //printf("Statement::comeFrom()\n");
137 /****************************************
138 * If this statement has code that needs to run in a finally clause
139 * at the end of the current scope, return that code in the form of
142 * *sentry code executed upon entry to the scope
143 * *sexception code executed upon exit from the scope via exception
144 * *sfinally code executed in finally block
147 void Statement::scopeCode(Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
149 //printf("Statement::scopeCode()\n");
156 /*********************************
157 * Flatten out the scope by presenting the statement
158 * as an array of statements.
159 * Returns NULL if no flattening necessary.
162 Statements
*Statement::flatten(Scope
*sc
)
168 /******************************** ExpStatement ***************************/
170 ExpStatement::ExpStatement(Loc loc
, Expression
*exp
)
176 Statement
*ExpStatement::syntaxCopy()
178 Expression
*e
= exp
? exp
->syntaxCopy() : NULL
;
179 ExpStatement
*es
= new ExpStatement(loc
, e
);
183 void ExpStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
186 exp
->toCBuffer(buf
, hgs
);
188 if (!hgs
->FLinit
.init
)
192 Statement
*ExpStatement::semantic(Scope
*sc
)
196 //printf("ExpStatement::semantic() %s\n", exp->toChars());
197 exp
= exp
->semantic(sc
);
198 exp
= resolveProperties(sc
, exp
);
199 exp
->checkSideEffect(0);
200 exp
= exp
->optimize(0);
201 //exp = exp->optimize(isDeclarationStatement() ? WANTvalue : 0);
206 int ExpStatement::fallOffEnd()
210 if (exp
->op
== TOKassert
)
211 { AssertExp
*a
= (AssertExp
*)exp
;
213 if (a
->e1
->isBool(FALSE
)) // if it's an assert(0)
216 else if (exp
->op
== TOKhalt
)
222 /******************************** CompileStatement ***************************/
224 CompileStatement::CompileStatement(Loc loc
, Expression
*exp
)
230 Statement
*CompileStatement::syntaxCopy()
232 Expression
*e
= exp
->syntaxCopy();
233 CompileStatement
*es
= new CompileStatement(loc
, e
);
237 void CompileStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
239 buf
->writestring("mixin(");
240 exp
->toCBuffer(buf
, hgs
);
241 buf
->writestring(");");
242 if (!hgs
->FLinit
.init
)
246 Statement
*CompileStatement::semantic(Scope
*sc
)
248 //printf("CompileStatement::semantic() %s\n", exp->toChars());
249 exp
= exp
->semantic(sc
);
250 exp
= resolveProperties(sc
, exp
);
251 exp
= exp
->optimize(WANTvalue
| WANTinterpret
);
252 if (exp
->op
!= TOKstring
)
253 { error("argument to mixin must be a string, not (%s)", exp
->toChars());
256 StringExp
*se
= (StringExp
*)exp
;
258 Parser
p(sc
->module
, (unsigned char *)se
->string
, se
->len
, 0);
262 Statements
*statements
= new Statements();
263 while (p
.token
.value
!= TOKeof
)
265 Statement
*s
= p
.parseStatement(PSsemi
| PScurlyscope
);
269 Statement
*s
= new CompoundStatement(loc
, statements
);
270 return s
->semantic(sc
);
274 /******************************** DeclarationStatement ***************************/
276 DeclarationStatement::DeclarationStatement(Loc loc
, Dsymbol
*declaration
)
277 : ExpStatement(loc
, new DeclarationExp(loc
, declaration
))
281 DeclarationStatement::DeclarationStatement(Loc loc
, Expression
*exp
)
282 : ExpStatement(loc
, exp
)
286 Statement
*DeclarationStatement::syntaxCopy()
288 DeclarationStatement
*ds
= new DeclarationStatement(loc
, exp
->syntaxCopy());
292 void DeclarationStatement::scopeCode(Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
294 //printf("DeclarationStatement::scopeCode()\n");
303 if (exp
->op
== TOKdeclaration
)
305 DeclarationExp
*de
= (DeclarationExp
*)(exp
);
306 VarDeclaration
*v
= de
->declaration
->isVarDeclaration();
310 e
= v
->callAutoDtor();
313 //printf("dtor is: "); e->print();
314 *sfinally
= new ExpStatement(loc
, e
);
321 void DeclarationStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
323 exp
->toCBuffer(buf
, hgs
);
327 /******************************** InjectorMainBody ***************************/
329 static Expressions
*getAutoArgs(Loc loc
, Arguments
*arguments
) {
330 Expressions
*args
= new Expressions();
332 Expression
*externals
= new IdentifierExp(loc
, Id::externals
);
333 // Collect all the objects we need for the constructor's arguments
334 for (int i
= 0; i
< arguments
->dim
; i
++) {
335 Argument
*arg
= (Argument
*) arguments
->data
[i
];
336 if (arg
->ident
== Id::args
) {
337 // For 'args', just pass through the string[] passed to main()
338 args
->push(new IdentifierExp(loc
, arg
->ident
));
340 // For everything else, call a getter in the _externals module
341 Expression
*getter
= new DotIdExp(loc
, externals
, arg
->ident
);
349 InjectorMainBody::InjectorMainBody(Loc loc
, ClassDeclaration
*mainClass
)
350 : Statement(loc
), mainClass(mainClass
)
354 Statement
*InjectorMainBody::semantic(Scope
*sc
)
356 // Find the constructor and the main method
357 CtorDeclaration
*ctor
= NULL
;
358 FuncDeclaration
*mainDecl
= NULL
;
359 for (int i
= 0; i
< mainClass
->members
->dim
; i
++) {
362 s
= (Dsymbol
*)mainClass
->members
->data
[i
];
364 CtorDeclaration
*thisCtor
= s
->isCtorDeclaration();
367 error("Multiple constructors for Main class!");
374 FuncDeclaration
*thisMethod
= s
->isFuncDeclaration();
375 if (thisMethod
&& thisMethod
->ident
== Id::main
) {
377 error("Multiple main methods for Main class!");
380 mainDecl
= thisMethod
;
385 if (mainDecl
== NULL
) {
386 error("No main method in Main class!");
390 // Externals externals = new _externals.Externals()
391 TypeIdentifier
*extType
= new TypeIdentifier(loc
, Id::_externals
);
392 extType
->addIdent(Id::Externals
);
394 Expression
*newExt
= new NewExp(loc
, NULL
, NULL
, extType
, NULL
);
395 VarDeclaration
*v
= new VarDeclaration(loc
, extType
, Id::externals
,
396 new ExpInitializer(loc
, newExt
));
397 Statement
*assignExt
= new DeclarationStatement(loc
, v
);
398 Expression
*newMain
= new NewExp(loc
, NULL
, NULL
, mainClass
->getType(),
399 ctor
? getAutoArgs(ctor
->loc
, ctor
->arguments
) : NULL
);
401 // Then invoke the main() method inside it
402 // mainObject.main(...)
403 Expression
*mainMethod
= new DotIdExp(mainDecl
->loc
, newMain
, Id::main
);
404 Expression
*mainCall
= new CallExp(mainMethod
->loc
, mainMethod
,
405 getAutoArgs(mainDecl
->loc
,
406 ((TypeFunction
*) mainDecl
->type
)->parameters
));
408 Statement
*s
= new ExpStatement(loc
, mainCall
);
409 Statement
*body
= new CompoundStatement(loc
, assignExt
, s
);
411 return body
->semantic(sc
);
414 /******************************** CompoundStatement ***************************/
416 CompoundStatement::CompoundStatement(Loc loc
, Statements
*s
)
422 CompoundStatement::CompoundStatement(Loc loc
, Statement
*s1
, Statement
*s2
)
425 statements
= new Statements();
426 statements
->reserve(2);
427 statements
->push(s1
);
428 statements
->push(s2
);
431 Statement
*CompoundStatement::syntaxCopy()
433 Statements
*a
= new Statements();
434 a
->setDim(statements
->dim
);
435 for (size_t i
= 0; i
< statements
->dim
; i
++)
436 { Statement
*s
= (Statement
*)statements
->data
[i
];
441 CompoundStatement
*cs
= new CompoundStatement(loc
, a
);
446 Statement
*CompoundStatement::semantic(Scope
*sc
)
449 //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", this, sc);
451 for (size_t i
= 0; i
< statements
->dim
; )
453 s
= (Statement
*) statements
->data
[i
];
455 { Statements
*a
= s
->flatten(sc
);
459 statements
->remove(i
);
460 statements
->insert(i
, a
);
464 statements
->data
[i
] = s
;
468 Statement
*sexception
;
471 s
->scopeCode(&sentry
, &sexception
, &sfinally
);
474 sentry
= sentry
->semantic(sc
);
475 statements
->data
[i
] = sentry
;
479 if (i
+ 1 == statements
->dim
&& !sfinally
)
482 sexception
= sexception
->semantic(sc
);
484 statements
->push(sexception
);
486 // Assume sexception does not throw
487 statements
->push(sfinally
);
498 * { sexception; throw __o; }
501 Statements
*a
= new Statements();
503 for (int j
= i
+ 1; j
< statements
->dim
; j
++)
505 a
->push(statements
->data
[j
]);
507 body
= new CompoundStatement(0, a
);
508 body
= new ScopeStatement(0, body
);
511 char name
[3 + sizeof(num
) * 3 + 1];
512 sprintf(name
, "__o%d", ++num
);
513 Identifier
*id
= Lexer::idPool(name
);
515 Statement
*handler
= new ThrowStatement(0, new IdentifierExp(0, id
));
516 handler
= new CompoundStatement(0, sexception
, handler
);
518 Array
*catches
= new Array();
519 Catch
*ctch
= new Catch(0, NULL
, id
, handler
);
521 s
= new TryCatchStatement(0, body
, catches
);
524 s
= new TryFinallyStatement(0, s
, sfinally
);
526 statements
->setDim(i
+ 1);
533 if (0 && i
+ 1 == statements
->dim
)
535 statements
->push(sfinally
);
542 * s; try { s1; s2; } finally { sfinally; }
545 Statements
*a
= new Statements();
547 for (int j
= i
+ 1; j
< statements
->dim
; j
++)
549 a
->push(statements
->data
[j
]);
551 body
= new CompoundStatement(0, a
);
552 s
= new TryFinallyStatement(0, body
, sfinally
);
554 statements
->setDim(i
+ 1);
563 if (statements
->dim
== 1)
568 Statements
*CompoundStatement::flatten(Scope
*sc
)
573 ReturnStatement
*CompoundStatement::isReturnStatement()
575 ReturnStatement
*rs
= NULL
;
577 for (i
= 0; i
< statements
->dim
; i
++)
580 s
= (Statement
*) statements
->data
[i
];
583 rs
= s
->isReturnStatement();
591 void CompoundStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
594 for (i
= 0; i
< statements
->dim
; i
++)
597 s
= (Statement
*) statements
->data
[i
];
599 s
->toCBuffer(buf
, hgs
);
603 int CompoundStatement::usesEH()
605 for (int i
= 0; i
< statements
->dim
; i
++)
608 s
= (Statement
*) statements
->data
[i
];
609 if (s
&& s
->usesEH())
615 int CompoundStatement::fallOffEnd()
616 { int falloff
= TRUE
;
618 //printf("CompoundStatement::fallOffEnd() %s\n", toChars());
619 for (int i
= 0; i
< statements
->dim
; i
++)
620 { Statement
*s
= (Statement
*)statements
->data
[i
];
625 if (!falloff
&& global
.params
.warnings
&& !s
->comeFrom())
627 fprintf(stdmsg
, "warning - ");
628 s
->error("statement is not reachable");
630 falloff
= s
->fallOffEnd();
635 int CompoundStatement::comeFrom()
636 { int comefrom
= FALSE
;
638 //printf("CompoundStatement::comeFrom()\n");
639 for (int i
= 0; i
< statements
->dim
; i
++)
640 { Statement
*s
= (Statement
*)statements
->data
[i
];
645 comefrom
|= s
->comeFrom();
651 /**************************** UnrolledLoopStatement ***************************/
653 UnrolledLoopStatement::UnrolledLoopStatement(Loc loc
, Statements
*s
)
659 Statement
*UnrolledLoopStatement::syntaxCopy()
661 Statements
*a
= new Statements();
662 a
->setDim(statements
->dim
);
663 for (size_t i
= 0; i
< statements
->dim
; i
++)
664 { Statement
*s
= (Statement
*)statements
->data
[i
];
669 UnrolledLoopStatement
*cs
= new UnrolledLoopStatement(loc
, a
);
674 Statement
*UnrolledLoopStatement::semantic(Scope
*sc
)
676 //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc);
679 Scope
*scd
= sc
->push();
681 scd
->scontinue
= this;
683 for (size_t i
= 0; i
< statements
->dim
; i
++)
685 Statement
*s
= (Statement
*) statements
->data
[i
];
688 s
= s
->semantic(scd
);
689 statements
->data
[i
] = s
;
698 void UnrolledLoopStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
700 buf
->writestring("unrolled {");
703 for (size_t i
= 0; i
< statements
->dim
; i
++)
706 s
= (Statement
*) statements
->data
[i
];
708 s
->toCBuffer(buf
, hgs
);
715 int UnrolledLoopStatement::hasBreak()
720 int UnrolledLoopStatement::hasContinue()
725 int UnrolledLoopStatement::usesEH()
727 for (size_t i
= 0; i
< statements
->dim
; i
++)
730 s
= (Statement
*) statements
->data
[i
];
731 if (s
&& s
->usesEH())
737 int UnrolledLoopStatement::fallOffEnd()
739 //printf("UnrolledLoopStatement::fallOffEnd()\n");
740 for (size_t i
= 0; i
< statements
->dim
; i
++)
741 { Statement
*s
= (Statement
*)statements
->data
[i
];
750 int UnrolledLoopStatement::comeFrom()
751 { int comefrom
= FALSE
;
753 //printf("UnrolledLoopStatement::comeFrom()\n");
754 for (size_t i
= 0; i
< statements
->dim
; i
++)
755 { Statement
*s
= (Statement
*)statements
->data
[i
];
760 comefrom
|= s
->comeFrom();
766 /******************************** ScopeStatement ***************************/
768 ScopeStatement::ScopeStatement(Loc loc
, Statement
*s
)
774 Statement
*ScopeStatement::syntaxCopy()
778 s
= statement
? statement
->syntaxCopy() : NULL
;
779 s
= new ScopeStatement(loc
, s
);
784 Statement
*ScopeStatement::semantic(Scope
*sc
)
787 //printf("ScopeStatement::semantic(sc = %p)\n", sc);
791 sym
= new ScopeDsymbol();
792 sym
->parent
= sc
->scopesym
;
795 a
= statement
->flatten(sc
);
798 statement
= new CompoundStatement(loc
, a
);
801 statement
= statement
->semantic(sc
);
805 Statement
*sexception
;
808 statement
->scopeCode(&sentry
, &sexception
, &sfinally
);
811 //printf("adding sfinally\n");
812 statement
= new CompoundStatement(loc
, statement
, sfinally
);
821 int ScopeStatement::hasBreak()
823 //printf("ScopeStatement::hasBreak() %s\n", toChars());
824 return statement
? statement
->hasBreak() : FALSE
;
827 int ScopeStatement::hasContinue()
829 return statement
? statement
->hasContinue() : FALSE
;
832 int ScopeStatement::usesEH()
834 return statement
? statement
->usesEH() : FALSE
;
837 int ScopeStatement::fallOffEnd()
839 return statement
? statement
->fallOffEnd() : TRUE
;
842 int ScopeStatement::comeFrom()
844 //printf("ScopeStatement::comeFrom()\n");
845 return statement
? statement
->comeFrom() : FALSE
;
848 void ScopeStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
854 statement
->toCBuffer(buf
, hgs
);
860 /******************************** WhileStatement ***************************/
862 WhileStatement::WhileStatement(Loc loc
, Expression
*c
, Statement
*b
)
869 Statement
*WhileStatement::syntaxCopy()
871 WhileStatement
*s
= new WhileStatement(loc
, condition
->syntaxCopy(), body
? body
->syntaxCopy() : NULL
);
876 Statement
*WhileStatement::semantic(Scope
*sc
)
879 if (condition
->op
== TOKmatch
)
881 /* Rewrite while (condition) body as:
885 * while ((_match = _match.opNext), _match);
888 Expression
*ew
= new IdentifierExp(0, Id::_match
);
889 ew
= new DotIdExp(0, ew
, Id::next
);
890 ew
= new AssignExp(0, new IdentifierExp(0, Id::_match
), ew
);
891 ////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0));
892 Expression
*ev
= new IdentifierExp(0, Id::_match
);
893 //ev = new CastExp(0, ev, Type::tvoidptr);
894 ew
= new CommaExp(0, ew
, ev
);
895 Statement
*sw
= new DoStatement(loc
, body
, ew
);
896 Statement
*si
= new IfStatement(loc
, condition
, sw
, NULL
);
897 return si
->semantic(sc
);
901 condition
= condition
->semantic(sc
);
902 condition
= resolveProperties(sc
, condition
);
903 condition
= condition
->optimize(WANTvalue
);
904 condition
= condition
->checkToBoolean();
908 Scope
*scd
= sc
->push();
910 scd
->scontinue
= this;
912 body
= body
->semantic(scd
);
920 int WhileStatement::hasBreak()
925 int WhileStatement::hasContinue()
930 int WhileStatement::usesEH()
932 return body
? body
->usesEH() : 0;
935 int WhileStatement::fallOffEnd()
942 int WhileStatement::comeFrom()
945 return body
->comeFrom();
949 void WhileStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
951 buf
->writestring("while (");
952 condition
->toCBuffer(buf
, hgs
);
956 body
->toCBuffer(buf
, hgs
);
959 /******************************** DoStatement ***************************/
961 DoStatement::DoStatement(Loc loc
, Statement
*b
, Expression
*c
)
968 Statement
*DoStatement::syntaxCopy()
970 DoStatement
*s
= new DoStatement(loc
, body
? body
->syntaxCopy() : NULL
, condition
->syntaxCopy());
975 Statement
*DoStatement::semantic(Scope
*sc
)
979 body
= body
->semanticScope(sc
, this, this);
981 condition
= condition
->semantic(sc
);
982 condition
= resolveProperties(sc
, condition
);
983 condition
= condition
->optimize(WANTvalue
);
985 condition
= condition
->checkToBoolean();
990 int DoStatement::hasBreak()
995 int DoStatement::hasContinue()
1000 int DoStatement::usesEH()
1002 return body
? body
->usesEH() : 0;
1005 int DoStatement::fallOffEnd()
1012 int DoStatement::comeFrom()
1015 return body
->comeFrom();
1019 void DoStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1021 buf
->writestring("do");
1024 body
->toCBuffer(buf
, hgs
);
1025 buf
->writestring("while (");
1026 condition
->toCBuffer(buf
, hgs
);
1027 buf
->writebyte(')');
1030 /******************************** ForStatement ***************************/
1032 ForStatement::ForStatement(Loc loc
, Statement
*init
, Expression
*condition
, Expression
*increment
, Statement
*body
)
1036 this->condition
= condition
;
1037 this->increment
= increment
;
1041 Statement
*ForStatement::syntaxCopy()
1043 Statement
*i
= NULL
;
1045 i
= init
->syntaxCopy();
1046 Expression
*c
= NULL
;
1048 c
= condition
->syntaxCopy();
1049 Expression
*inc
= NULL
;
1051 inc
= increment
->syntaxCopy();
1052 ForStatement
*s
= new ForStatement(loc
, i
, c
, inc
, body
->syntaxCopy());
1056 Statement
*ForStatement::semantic(Scope
*sc
)
1058 ScopeDsymbol
*sym
= new ScopeDsymbol();
1059 sym
->parent
= sc
->scopesym
;
1062 init
= init
->semantic(sc
);
1064 // Use a default value
1065 condition
= new IntegerExp(loc
, 1, Type::tboolean
);
1067 condition
= condition
->semantic(sc
);
1068 condition
= resolveProperties(sc
, condition
);
1069 condition
= condition
->optimize(WANTvalue
);
1070 condition
= condition
->checkToBoolean();
1072 increment
= increment
->semantic(sc
);
1075 sc
->scontinue
= this;
1076 body
= body
->semantic(sc
);
1083 void ForStatement::scopeCode(Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
1085 //printf("ForStatement::scopeCode()\n");
1088 init
->scopeCode(sentry
, sexception
, sfinally
);
1090 Statement::scopeCode(sentry
, sexception
, sfinally
);
1093 int ForStatement::hasBreak()
1095 //printf("ForStatement::hasBreak()\n");
1099 int ForStatement::hasContinue()
1104 int ForStatement::usesEH()
1106 return (init
&& init
->usesEH()) || body
->usesEH();
1109 int ForStatement::fallOffEnd()
1116 int ForStatement::comeFrom()
1118 //printf("ForStatement::comeFrom()\n");
1120 { int result
= body
->comeFrom();
1121 //printf("result = %d\n", result);
1127 void ForStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1129 buf
->writestring("for (");
1133 hgs
->FLinit
.decl
= 0;
1134 init
->toCBuffer(buf
, hgs
);
1135 if (hgs
->FLinit
.decl
> 0)
1136 buf
->writebyte(';');
1137 hgs
->FLinit
.decl
= 0;
1141 buf
->writebyte(';');
1143 { buf
->writebyte(' ');
1144 condition
->toCBuffer(buf
, hgs
);
1146 buf
->writebyte(';');
1148 { buf
->writebyte(' ');
1149 increment
->toCBuffer(buf
, hgs
);
1151 buf
->writebyte(')');
1153 buf
->writebyte('{');
1155 body
->toCBuffer(buf
, hgs
);
1156 buf
->writebyte('}');
1160 /******************************** ForeachStatement ***************************/
1162 ForeachStatement::ForeachStatement(Loc loc
, enum TOK op
, Arguments
*arguments
,
1163 Expression
*aggr
, Statement
*body
)
1167 this->arguments
= arguments
;
1177 Statement
*ForeachStatement::syntaxCopy()
1179 Arguments
*args
= Argument::arraySyntaxCopy(arguments
);
1180 Expression
*exp
= aggr
->syntaxCopy();
1181 ForeachStatement
*s
= new ForeachStatement(loc
, op
, args
, exp
,
1182 body
? body
->syntaxCopy() : NULL
);
1186 Statement
*ForeachStatement::semantic(Scope
*sc
)
1188 //printf("ForeachStatement::semantic() %p\n", this);
1190 Statement
*s
= this;
1191 int dim
= arguments
->dim
;
1193 TypeAArray
*taa
= NULL
;
1200 func
= func
->fes
->func
;
1202 aggr
= aggr
->semantic(sc
);
1203 aggr
= resolveProperties(sc
, aggr
);
1206 error("invalid foreach aggregate %s", aggr
->toChars());
1210 inferApplyArgTypes(op
, arguments
, aggr
);
1212 /* Check for inference errors
1214 if (dim
!= arguments
->dim
)
1216 //printf("dim = %d, arguments->dim = %d\n", dim, arguments->dim);
1217 error("cannot uniquely infer foreach argument types");
1221 Type
*tab
= aggr
->type
->toBasetype();
1223 if (tab
->ty
== Ttuple
) // don't generate new scope for tuple loops
1225 if (dim
< 1 || dim
> 2)
1227 error("only one (value) or two (key,value) arguments for tuple foreach");
1231 TypeTuple
*tuple
= (TypeTuple
*)tab
;
1232 Statements
*statements
= new Statements();
1233 //printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars());
1235 TupleExp
*te
= NULL
;
1236 if (aggr
->op
== TOKtuple
) // expression tuple
1237 { te
= (TupleExp
*)aggr
;
1240 else if (aggr
->op
== TOKtype
) // type tuple
1242 n
= Argument::dim(tuple
->arguments
);
1246 for (size_t j
= 0; j
< n
; j
++)
1247 { size_t k
= (op
== TOKforeach
) ? j
: n
- 1 - j
;
1251 e
= (Expression
*)te
->exps
->data
[k
];
1253 t
= Argument::getNth(tuple
->arguments
, k
)->type
;
1254 Argument
*arg
= (Argument
*)arguments
->data
[0];
1255 Statements
*st
= new Statements();
1259 if (arg
->storageClass
& (STCout
| STCref
| STClazy
))
1260 error("no storage class for key %s", arg
->ident
->toChars());
1261 TY keyty
= arg
->type
->ty
;
1262 if ((keyty
!= Tint32
&& keyty
!= Tuns32
) &&
1263 (! global
.params
.isX86_64
||
1264 (keyty
!= Tint64
&& keyty
!= Tuns64
))
1267 error("foreach: key type must be int or uint, not %s", arg
->type
->toChars());
1269 Initializer
*ie
= new ExpInitializer(0, new IntegerExp(k
));
1270 VarDeclaration
*var
= new VarDeclaration(loc
, arg
->type
, arg
->ident
, ie
);
1271 var
->storage_class
|= STCconst
;
1272 DeclarationExp
*de
= new DeclarationExp(loc
, var
);
1273 st
->push(new ExpStatement(loc
, de
));
1274 arg
= (Argument
*)arguments
->data
[1]; // value
1277 if (arg
->storageClass
& (STCout
| STCref
| STClazy
))
1278 error("no storage class for value %s", arg
->ident
->toChars());
1282 if (e
->type
->toBasetype()->ty
== Tfunction
&&
1284 { VarExp
*ve
= (VarExp
*)e
;
1285 var
= new AliasDeclaration(loc
, arg
->ident
, ve
->var
);
1289 arg
->type
= e
->type
;
1290 Initializer
*ie
= new ExpInitializer(0, e
);
1291 VarDeclaration
*v
= new VarDeclaration(loc
, arg
->type
, arg
->ident
, ie
);
1293 v
->storage_class
|= STCconst
;
1296 v
->storage_class
|= STCfinal
;
1303 var
= new AliasDeclaration(loc
, arg
->ident
, t
);
1305 DeclarationExp
*de
= new DeclarationExp(loc
, var
);
1306 st
->push(new ExpStatement(loc
, de
));
1308 st
->push(body
->syntaxCopy());
1309 s
= new CompoundStatement(loc
, st
);
1310 s
= new ScopeStatement(loc
, s
);
1311 statements
->push(s
);
1314 s
= new UnrolledLoopStatement(loc
, statements
);
1315 s
= s
->semantic(sc
);
1319 for (i
= 0; i
< dim
; i
++)
1320 { Argument
*arg
= (Argument
*)arguments
->data
[i
];
1323 error("cannot infer type for %s", arg
->ident
->toChars());
1328 sym
= new ScopeDsymbol();
1329 sym
->parent
= sc
->scopesym
;
1338 if (dim
< 1 || dim
> 2)
1340 error("only one or two arguments for array foreach");
1344 /* Look for special case of parsing char types out of char type
1347 tn
= tab
->nextOf()->toBasetype();
1348 if (tn
->ty
== Tchar
|| tn
->ty
== Twchar
|| tn
->ty
== Tdchar
)
1351 i
= (dim
== 1) ? 0 : 1; // index of value
1352 arg
= (Argument
*)arguments
->data
[i
];
1353 arg
->type
= arg
->type
->semantic(loc
, sc
);
1354 tnv
= arg
->type
->toBasetype();
1355 if (tnv
->ty
!= tn
->ty
&&
1356 (tnv
->ty
== Tchar
|| tnv
->ty
== Twchar
|| tnv
->ty
== Tdchar
))
1358 if (arg
->storageClass
& STCref
)
1359 error("foreach: value of UTF conversion cannot be ref");
1361 { arg
= (Argument
*)arguments
->data
[0];
1362 if (arg
->storageClass
& STCref
)
1363 error("foreach: key cannot be ref");
1369 for (i
= 0; i
< dim
; i
++)
1371 Argument
*arg
= (Argument
*)arguments
->data
[i
];
1372 VarDeclaration
*var
;
1374 var
= new VarDeclaration(loc
, arg
->type
, arg
->ident
, NULL
);
1375 var
->storage_class
|= STCforeach
;
1376 var
->storage_class
|= arg
->storageClass
& (STCin
| STCout
| STCref
);
1378 DeclarationExp
*de
= new DeclarationExp(loc
, var
);
1382 if (!sc
->insert(var
))
1383 error("%s already defined", var
->ident
->toChars());
1385 if (dim
== 2 && i
== 0)
1392 sc
->scontinue
= this;
1393 body
= body
->semantic(sc
);
1395 if (!value
->type
->equals(tab
->next
))
1397 if (aggr
->op
== TOKstring
)
1398 aggr
= aggr
->implicitCastTo(sc
, value
->type
->arrayOf());
1400 error("foreach: %s is not an array of %s", tab
->toChars(), value
->type
->toChars());
1404 ((key
->type
->ty
!= Tint32
&& key
->type
->ty
!= Tuns32
) &&
1405 (! global
.params
.isX86_64
||
1406 (key
->type
->ty
!= Tint64
&& key
->type
->ty
!= Tuns64
))
1410 error("foreach: key type must be int or uint, not %s", key
->type
->toChars());
1413 if (key
&& key
->storage_class
& (STCout
| STCref
))
1414 error("foreach: key cannot be out or ref");
1418 taa
= (TypeAArray
*)tab
;
1419 if (dim
< 1 || dim
> 2)
1421 error("only one or two arguments for associative array foreach");
1424 if (op
== TOKforeach_reverse
)
1426 error("no reverse iteration on associative arrays");
1434 { FuncDeclaration
*fdapply
;
1438 FuncLiteralDeclaration
*fld
;
1445 tret
= func
->type
->nextOf();
1447 // Need a variable to hold value from any return statements in body.
1448 if (!sc
->func
->vresult
&& tret
&& tret
!= Type::tvoid
)
1449 { VarDeclaration
*v
;
1451 v
= new VarDeclaration(loc
, tret
, Id::result
, NULL
);
1456 v
->parent
= sc
->func
;
1457 sc
->func
->vresult
= v
;
1460 /* Turn body into the function literal:
1461 * int delegate(ref T arg) { body }
1463 args
= new Arguments();
1464 for (i
= 0; i
< dim
; i
++)
1465 { Argument
*arg
= (Argument
*)arguments
->data
[i
];
1467 arg
->type
= arg
->type
->semantic(loc
, sc
);
1468 if (arg
->storageClass
& STCref
)
1471 { // Make a copy of the ref argument so it isn't
1475 char applyArg
[10 + sizeof(i
)*3 + 1];
1477 sprintf(applyArg
, "__applyArg%d", i
);
1478 id
= Lexer::idPool(applyArg
);
1480 ie
= new ExpInitializer(0, new IdentifierExp(0, id
));
1481 v
= new VarDeclaration(0, arg
->type
, arg
->ident
, ie
);
1482 s
= new DeclarationStatement(0, v
);
1483 body
= new CompoundStatement(loc
, s
, body
);
1485 a
= new Argument(STCref
, arg
->type
, id
, NULL
);
1488 t
= new TypeFunction(args
, Type::tint32
, 0, LINKd
);
1489 fld
= new FuncLiteralDeclaration(loc
, 0, t
, TOKdelegate
, this);
1491 flde
= new FuncExp(loc
, fld
);
1492 flde
= flde
->semantic(sc
);
1494 // Resolve any forward referenced goto's
1495 for (int i
= 0; i
< gotos
.dim
; i
++)
1496 { CompoundStatement
*cs
= (CompoundStatement
*)gotos
.data
[i
];
1497 GotoStatement
*gs
= (GotoStatement
*)cs
->statements
->data
[0];
1499 if (!gs
->label
->statement
)
1500 { // 'Promote' it to this scope, and replace with a return
1502 s
= new ReturnStatement(0, new IntegerExp(cases
.dim
+ 1));
1503 cs
->statements
->data
[0] = (void *)s
;
1507 if (tab
->ty
== Taarray
)
1510 Argument
*arg
= (Argument
*)arguments
->data
[0];
1513 if (arg
->storageClass
& STCref
)
1514 error("foreach: index cannot be ref");
1515 if (!arg
->type
->equals(taa
->index
))
1516 error("foreach: index must be type %s, not %s", taa
->index
->toChars(), arg
->type
->toChars());
1517 arg
= (Argument
*)arguments
->data
[1];
1519 if (!arg
->type
->equals(taa
->nextOf()))
1520 error("foreach: value must be type %s, not %s", taa
->nextOf()->toChars(), arg
->type
->toChars());
1523 * _aaApply(aggr, keysize, flde)
1526 fdapply
= FuncDeclaration::genCfunc(Type::tint32
, "_aaApply2",
1527 Type::tvoid
->arrayOf(), Type::tsize_t
, flde
->type
); // flde->type is not generic
1529 fdapply
= FuncDeclaration::genCfunc(Type::tint32
, "_aaApply",
1530 Type::tvoid
->arrayOf(), Type::tsize_t
, flde
->type
); // flde->type is not generic);
1531 ec
= new VarExp(0, fdapply
);
1532 Expressions
*exps
= new Expressions();
1534 size_t keysize
= taa
->key
->size();
1535 keysize
= (keysize
+ (PTRSIZE
-1)) & ~(PTRSIZE
-1);
1536 exps
->push(new IntegerExp(0, keysize
, Type::tsize_t
));
1538 e
= new CallExp(loc
, ec
, exps
);
1539 e
->type
= Type::tint32
; // don't run semantic() on e
1541 else if (tab
->ty
== Tarray
|| tab
->ty
== Tsarray
)
1544 * _aApply(aggr, flde)
1546 static char fntab
[9][3] =
1551 char fdname
[7+1+2+ sizeof(dim
)*3 + 1];
1556 case Tchar
: flag
= 0; break;
1557 case Twchar
: flag
= 3; break;
1558 case Tdchar
: flag
= 6; break;
1563 case Tchar
: flag
+= 0; break;
1564 case Twchar
: flag
+= 1; break;
1565 case Tdchar
: flag
+= 2; break;
1568 const char *r
= (op
== TOKforeach_reverse
) ? "R" : "";
1569 int j
= sprintf(fdname
, "_aApply%s%.*s%d", r
, 2, fntab
[flag
], dim
);
1570 assert(j
< sizeof(fdname
));
1571 fdapply
= FuncDeclaration::genCfunc(Type::tint32
, fdname
,
1572 Type::tvoid
->arrayOf(), flde
->type
); // flde->type is not generic
1574 ec
= new VarExp(0, fdapply
);
1575 Expressions
*exps
= new Expressions();
1576 if (tab
->ty
== Tsarray
)
1577 aggr
= aggr
->castTo(sc
, tn
->arrayOf());
1580 e
= new CallExp(loc
, ec
, exps
);
1581 e
->type
= Type::tint32
; // don't run semantic() on e
1583 else if (tab
->ty
== Tdelegate
)
1588 Expressions
*exps
= new Expressions();
1590 e
= new CallExp(loc
, aggr
, exps
);
1591 e
= e
->semantic(sc
);
1592 if (e
->type
!= Type::tint32
)
1593 error("opApply() function for %s must return an int", tab
->toChars());
1600 ec
= new DotIdExp(loc
, aggr
,
1601 (op
== TOKforeach_reverse
) ? Id::applyReverse
1603 Expressions
*exps
= new Expressions();
1605 e
= new CallExp(loc
, ec
, exps
);
1606 e
= e
->semantic(sc
);
1607 if (e
->type
!= Type::tint32
)
1608 error("opApply() function for %s must return an int", tab
->toChars());
1612 // Easy case, a clean exit from the loop
1613 s
= new ExpStatement(loc
, e
);
1615 { // Construct a switch statement around the return value
1616 // of the apply function.
1617 Statements
*a
= new Statements();
1619 // default: break; takes care of cases 0 and 1
1620 s
= new BreakStatement(0, NULL
);
1621 s
= new DefaultStatement(0, s
);
1625 for (int i
= 0; i
< cases
.dim
; i
++)
1627 s
= (Statement
*)cases
.data
[i
];
1628 s
= new CaseStatement(0, new IntegerExp(i
+ 2), s
);
1632 s
= new CompoundStatement(loc
, a
);
1633 s
= new SwitchStatement(loc
, e
, s
);
1634 s
= s
->semantic(sc
);
1640 error("foreach: %s is not an aggregate type", aggr
->type
->toChars());
1648 int ForeachStatement::hasBreak()
1653 int ForeachStatement::hasContinue()
1658 int ForeachStatement::usesEH()
1660 return body
->usesEH();
1663 int ForeachStatement::fallOffEnd()
1670 int ForeachStatement::comeFrom()
1673 return body
->comeFrom();
1677 void ForeachStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1679 buf
->writestring(Token::toChars(op
));
1680 buf
->writestring(" (");
1682 for (int i
= 0; i
< arguments
->dim
; i
++)
1684 Argument
*a
= (Argument
*)arguments
->data
[i
];
1686 buf
->writestring(", ");
1687 if (a
->storageClass
& STCref
)
1688 buf
->writestring((global
.params
.Dversion
== 1)
1689 ? (char*)"inout " : (char*)"ref ");
1691 a
->type
->toCBuffer(buf
, a
->ident
, hgs
);
1693 buf
->writestring(a
->ident
->toChars());
1695 buf
->writestring("; ");
1696 aggr
->toCBuffer(buf
, hgs
);
1697 buf
->writebyte(')');
1699 buf
->writebyte('{');
1702 body
->toCBuffer(buf
, hgs
);
1703 buf
->writebyte('}');
1707 /******************************** IfStatement ***************************/
1709 IfStatement::IfStatement(Loc loc
, Argument
*arg
, Expression
*condition
, Statement
*ifbody
, Statement
*elsebody
)
1713 this->condition
= condition
;
1714 this->ifbody
= ifbody
;
1715 this->elsebody
= elsebody
;
1719 Statement
*IfStatement::syntaxCopy()
1721 Statement
*i
= NULL
;
1723 i
= ifbody
->syntaxCopy();
1725 Statement
*e
= NULL
;
1727 e
= elsebody
->syntaxCopy();
1729 Argument
*a
= arg
? arg
->syntaxCopy() : NULL
;
1730 IfStatement
*s
= new IfStatement(loc
, a
, condition
->syntaxCopy(), i
, e
);
1734 Statement
*IfStatement::semantic(Scope
*sc
)
1736 condition
= condition
->semantic(sc
);
1737 condition
= resolveProperties(sc
, condition
);
1738 condition
= condition
->checkToBoolean();
1740 // If we can short-circuit evaluate the if statement, don't do the
1741 // semantic analysis of the skipped code.
1742 // This feature allows a limited form of conditional compilation.
1743 condition
= condition
->optimize(WANTflags
);
1745 // Evaluate at runtime
1746 unsigned cs0
= sc
->callSuper
;
1751 { /* Declare arg, which we will set to be the
1752 * result of condition.
1754 ScopeDsymbol
*sym
= new ScopeDsymbol();
1755 sym
->parent
= sc
->scopesym
;
1756 scd
= sc
->push(sym
);
1758 Type
*t
= arg
->type
? arg
->type
: condition
->type
;
1759 match
= new VarDeclaration(loc
, t
, arg
->ident
, NULL
);
1761 match
->semantic(scd
);
1762 if (!scd
->insert(match
))
1764 match
->parent
= sc
->func
;
1769 VarExp
*v
= new VarExp(0, match
);
1770 condition
= new AssignExp(loc
, v
, condition
);
1771 condition
= condition
->semantic(scd
);
1775 ifbody
= ifbody
->semantic(scd
);
1778 cs1
= sc
->callSuper
;
1779 sc
->callSuper
= cs0
;
1781 elsebody
= elsebody
->semanticScope(sc
, NULL
, NULL
);
1782 sc
->mergeCallSuper(loc
, cs1
);
1787 int IfStatement::usesEH()
1789 return (ifbody
&& ifbody
->usesEH()) || (elsebody
&& elsebody
->usesEH());
1792 int IfStatement::fallOffEnd()
1794 if (!ifbody
|| ifbody
->fallOffEnd() ||
1795 !elsebody
|| elsebody
->fallOffEnd())
1801 void IfStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1803 buf
->writestring("if (");
1807 arg
->type
->toCBuffer(buf
, arg
->ident
, hgs
);
1809 buf
->writestring(arg
->ident
->toChars());
1810 buf
->writebyte(';');
1812 condition
->toCBuffer(buf
, hgs
);
1813 buf
->writebyte(')');
1815 ifbody
->toCBuffer(buf
, hgs
);
1817 { buf
->writestring("else");
1819 elsebody
->toCBuffer(buf
, hgs
);
1823 /******************************** ConditionalStatement ***************************/
1825 ConditionalStatement::ConditionalStatement(Loc loc
, Condition
*condition
, Statement
*ifbody
, Statement
*elsebody
)
1828 this->condition
= condition
;
1829 this->ifbody
= ifbody
;
1830 this->elsebody
= elsebody
;
1833 Statement
*ConditionalStatement::syntaxCopy()
1835 Statement
*e
= NULL
;
1837 e
= elsebody
->syntaxCopy();
1838 ConditionalStatement
*s
= new ConditionalStatement(loc
,
1839 condition
->syntaxCopy(), ifbody
->syntaxCopy(), e
);
1843 Statement
*ConditionalStatement::semantic(Scope
*sc
)
1845 //printf("ConditionalStatement::semantic()\n");
1847 // If we can short-circuit evaluate the if statement, don't do the
1848 // semantic analysis of the skipped code.
1849 // This feature allows a limited form of conditional compilation.
1850 if (condition
->include(sc
, NULL
))
1852 ifbody
= ifbody
->semantic(sc
);
1858 elsebody
= elsebody
->semantic(sc
);
1863 Statements
*ConditionalStatement::flatten(Scope
*sc
)
1867 if (condition
->include(sc
, NULL
))
1872 Statements
*a
= new Statements();
1877 int ConditionalStatement::usesEH()
1879 return (ifbody
&& ifbody
->usesEH()) || (elsebody
&& elsebody
->usesEH());
1882 void ConditionalStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1884 condition
->toCBuffer(buf
, hgs
);
1887 ifbody
->toCBuffer(buf
, hgs
);
1890 buf
->writestring("else");
1892 elsebody
->toCBuffer(buf
, hgs
);
1898 /******************************** PragmaStatement ***************************/
1900 PragmaStatement::PragmaStatement(Loc loc
, Identifier
*ident
, Expressions
*args
, Statement
*body
)
1903 this->ident
= ident
;
1908 Statement
*PragmaStatement::syntaxCopy()
1910 Statement
*b
= NULL
;
1912 b
= body
->syntaxCopy();
1913 PragmaStatement
*s
= new PragmaStatement(loc
,
1914 ident
, Expression::arraySyntaxCopy(args
), b
);
1918 Statement
*PragmaStatement::semantic(Scope
*sc
)
1919 { // Should be merged with PragmaDeclaration
1920 //printf("PragmaStatement::semantic() %s\n", toChars());
1921 //printf("body = %p\n", body);
1922 if (ident
== Id::msg
)
1926 for (size_t i
= 0; i
< args
->dim
; i
++)
1928 Expression
*e
= (Expression
*)args
->data
[i
];
1930 e
= e
->semantic(sc
);
1931 e
= e
->optimize(WANTvalue
| WANTinterpret
);
1932 if (e
->op
== TOKstring
)
1934 StringExp
*se
= (StringExp
*)e
;
1935 fprintf(stdmsg
, "%.*s", (int)se
->len
, se
->string
);
1938 error("string expected for message, not '%s'", e
->toChars());
1940 fprintf(stdmsg
, "\n");
1943 else if (ident
== Id::lib
)
1945 if (!args
|| args
->dim
!= 1)
1946 error("string expected for library name");
1949 Expression
*e
= (Expression
*)args
->data
[0];
1951 e
= e
->semantic(sc
);
1952 e
= e
->optimize(WANTvalue
| WANTinterpret
);
1953 args
->data
[0] = (void *)e
;
1954 if (e
->op
!= TOKstring
)
1955 error("string expected for library name, not '%s'", e
->toChars());
1956 else if (global
.params
.verbose
)
1958 StringExp
*se
= (StringExp
*)e
;
1959 char *name
= (char *)mem
.malloc(se
->len
+ 1);
1960 memcpy(name
, se
->string
, se
->len
);
1962 printf("library %s\n", name
);
1968 error("unrecognized pragma(%s)", ident
->toChars());
1972 body
= body
->semantic(sc
);
1977 int PragmaStatement::usesEH()
1979 return body
&& body
->usesEH();
1982 int PragmaStatement::fallOffEnd()
1985 return body
->fallOffEnd();
1989 void PragmaStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1991 buf
->writestring("pragma (");
1992 buf
->writestring(ident
->toChars());
1993 if (args
&& args
->dim
)
1995 buf
->writestring(", ");
1996 argsToCBuffer(buf
, args
, hgs
);
1998 buf
->writeByte(')');
2002 buf
->writeByte('{');
2005 body
->toCBuffer(buf
, hgs
);
2007 buf
->writeByte('}');
2012 buf
->writeByte(';');
2018 /******************************** StaticAssertStatement ***************************/
2020 StaticAssertStatement::StaticAssertStatement(StaticAssert
*sa
)
2021 : Statement(sa
->loc
)
2026 Statement
*StaticAssertStatement::syntaxCopy()
2028 StaticAssertStatement
*s
= new StaticAssertStatement((StaticAssert
*)sa
->syntaxCopy(NULL
));
2032 Statement
*StaticAssertStatement::semantic(Scope
*sc
)
2038 void StaticAssertStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2040 sa
->toCBuffer(buf
, hgs
);
2044 /******************************** SwitchStatement ***************************/
2046 SwitchStatement::SwitchStatement(Loc loc
, Expression
*c
, Statement
*b
)
2056 Statement
*SwitchStatement::syntaxCopy()
2058 SwitchStatement
*s
= new SwitchStatement(loc
,
2059 condition
->syntaxCopy(), body
->syntaxCopy());
2063 Statement
*SwitchStatement::semantic(Scope
*sc
)
2065 //printf("SwitchStatement::semantic(%p)\n", this);
2066 assert(!cases
); // ensure semantic() is only run once
2067 condition
= condition
->semantic(sc
);
2068 condition
= resolveProperties(sc
, condition
);
2069 if (condition
->type
->isString())
2071 // If it's not an array, cast it to one
2072 if (condition
->type
->ty
!= Tarray
)
2074 condition
= condition
->implicitCastTo(sc
, condition
->type
->nextOf()->arrayOf());
2078 { condition
= condition
->integralPromotions(sc
);
2079 condition
->checkIntegral();
2081 condition
= condition
->optimize(WANTvalue
);
2087 cases
= new Array();
2088 sc
->noctor
++; // BUG: should use Scope::mergeCallSuper() for each case instead
2089 body
= body
->semantic(sc
);
2092 // Resolve any goto case's with exp
2093 for (int i
= 0; i
< gotoCases
.dim
; i
++)
2095 GotoCaseStatement
*gcs
= (GotoCaseStatement
*)gotoCases
.data
[i
];
2099 gcs
->error("no case statement following goto case;");
2103 for (Scope
*scx
= sc
; scx
; scx
= scx
->enclosing
)
2107 for (int j
= 0; j
< scx
->sw
->cases
->dim
; j
++)
2109 CaseStatement
*cs
= (CaseStatement
*)scx
->sw
->cases
->data
[j
];
2111 if (cs
->exp
->equals(gcs
->exp
))
2118 gcs
->error("case %s not found", gcs
->exp
->toChars());
2124 if (!sc
->sw
->sdefault
)
2127 if (global
.params
.warnings
)
2128 { fprintf(stdmsg
, "warning - ");
2129 error("switch statement has no default");
2132 // Generate runtime error if the default is hit
2133 Statements
*a
= new Statements();
2134 CompoundStatement
*cs
;
2137 if (global
.params
.useSwitchError
)
2138 s
= new SwitchErrorStatement(loc
);
2140 { Expression
*e
= new HaltExp(loc
);
2141 s
= new ExpStatement(loc
, e
);
2146 a
->push(new BreakStatement(loc
, NULL
));
2147 sc
->sw
->sdefault
= new DefaultStatement(loc
, s
);
2148 a
->push(sc
->sw
->sdefault
);
2149 cs
= new CompoundStatement(loc
, a
);
2157 int SwitchStatement::hasBreak()
2162 int SwitchStatement::usesEH()
2164 return body
? body
->usesEH() : 0;
2167 int SwitchStatement::fallOffEnd()
2171 return TRUE
; // need to do this better
2174 void SwitchStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2176 buf
->writestring("switch (");
2177 condition
->toCBuffer(buf
, hgs
);
2178 buf
->writebyte(')');
2182 if (!body
->isScopeStatement())
2183 { buf
->writebyte('{');
2185 body
->toCBuffer(buf
, hgs
);
2186 buf
->writebyte('}');
2191 body
->toCBuffer(buf
, hgs
);
2196 /******************************** CaseStatement ***************************/
2198 CaseStatement::CaseStatement(Loc loc
, Expression
*exp
, Statement
*s
)
2202 this->statement
= s
;
2206 Statement
*CaseStatement::syntaxCopy()
2208 CaseStatement
*s
= new CaseStatement(loc
, exp
->syntaxCopy(), statement
->syntaxCopy());
2212 Statement
*CaseStatement::semantic(Scope
*sc
)
2213 { SwitchStatement
*sw
= sc
->sw
;
2215 //printf("CaseStatement::semantic() %s\n", toChars());
2216 exp
= exp
->semantic(sc
);
2220 exp
= exp
->implicitCastTo(sc
, sw
->condition
->type
);
2221 exp
= exp
->optimize(WANTvalue
| WANTinterpret
);
2222 if (exp
->op
!= TOKstring
&& exp
->op
!= TOKint64
)
2224 error("case must be a string or an integral constant, not %s", exp
->toChars());
2225 exp
= new IntegerExp(0);
2228 for (i
= 0; i
< sw
->cases
->dim
; i
++)
2230 CaseStatement
*cs
= (CaseStatement
*)sw
->cases
->data
[i
];
2232 //printf("comparing '%s' with '%s'\n", exp->toChars(), cs->exp->toChars());
2233 if (cs
->exp
->equals(exp
))
2234 { error("duplicate case %s in switch statement", exp
->toChars());
2239 sw
->cases
->push(this);
2241 // Resolve any goto case's with no exp to this case statement
2242 for (i
= 0; i
< sw
->gotoCases
.dim
; i
++)
2244 GotoCaseStatement
*gcs
= (GotoCaseStatement
*)sw
->gotoCases
.data
[i
];
2249 sw
->gotoCases
.remove(i
); // remove from array
2254 error("case not in switch statement");
2255 statement
= statement
->semantic(sc
);
2259 int CaseStatement::compare(Object
*obj
)
2261 // Sort cases so we can do an efficient lookup
2262 CaseStatement
*cs2
= (CaseStatement
*)(obj
);
2264 return exp
->compare(cs2
->exp
);
2267 int CaseStatement::usesEH()
2269 return statement
->usesEH();
2272 int CaseStatement::fallOffEnd()
2274 return statement
->fallOffEnd();
2277 int CaseStatement::comeFrom()
2282 void CaseStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2284 buf
->writestring("case ");
2285 exp
->toCBuffer(buf
, hgs
);
2286 buf
->writebyte(':');
2288 statement
->toCBuffer(buf
, hgs
);
2291 /******************************** DefaultStatement ***************************/
2293 DefaultStatement::DefaultStatement(Loc loc
, Statement
*s
)
2296 this->statement
= s
;
2302 Statement
*DefaultStatement::syntaxCopy()
2304 DefaultStatement
*s
= new DefaultStatement(loc
, statement
->syntaxCopy());
2308 Statement
*DefaultStatement::semantic(Scope
*sc
)
2312 if (sc
->sw
->sdefault
)
2314 error("switch statement already has a default");
2316 sc
->sw
->sdefault
= this;
2319 error("default not in switch statement");
2320 statement
= statement
->semantic(sc
);
2324 int DefaultStatement::usesEH()
2326 return statement
->usesEH();
2329 int DefaultStatement::fallOffEnd()
2331 return statement
->fallOffEnd();
2334 int DefaultStatement::comeFrom()
2339 void DefaultStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2341 buf
->writestring("default:\n");
2342 statement
->toCBuffer(buf
, hgs
);
2345 /******************************** GotoDefaultStatement ***************************/
2347 GotoDefaultStatement::GotoDefaultStatement(Loc loc
)
2353 Statement
*GotoDefaultStatement::syntaxCopy()
2355 GotoDefaultStatement
*s
= new GotoDefaultStatement(loc
);
2359 Statement
*GotoDefaultStatement::semantic(Scope
*sc
)
2363 error("goto default not in switch statement");
2367 int GotoDefaultStatement::fallOffEnd()
2372 void GotoDefaultStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2374 buf
->writestring("goto default;\n");
2377 /******************************** GotoCaseStatement ***************************/
2379 GotoCaseStatement::GotoCaseStatement(Loc loc
, Expression
*exp
)
2386 Statement
*GotoCaseStatement::syntaxCopy()
2388 Expression
*e
= exp
? exp
->syntaxCopy() : NULL
;
2389 GotoCaseStatement
*s
= new GotoCaseStatement(loc
, e
);
2393 Statement
*GotoCaseStatement::semantic(Scope
*sc
)
2396 exp
= exp
->semantic(sc
);
2399 error("goto case not in switch statement");
2402 sc
->sw
->gotoCases
.push(this);
2405 exp
= exp
->implicitCastTo(sc
, sc
->sw
->condition
->type
);
2406 exp
= exp
->optimize(WANTvalue
);
2412 int GotoCaseStatement::fallOffEnd()
2417 void GotoCaseStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2419 buf
->writestring("goto case");
2421 { buf
->writebyte(' ');
2422 exp
->toCBuffer(buf
, hgs
);
2424 buf
->writebyte(';');
2428 /******************************** SwitchErrorStatement ***************************/
2430 SwitchErrorStatement::SwitchErrorStatement(Loc loc
)
2435 int SwitchErrorStatement::fallOffEnd()
2440 void SwitchErrorStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2442 buf
->writestring("SwitchErrorStatement::toCBuffer()");
2446 /******************************** ReturnStatement ***************************/
2448 ReturnStatement::ReturnStatement(Loc loc
, Expression
*exp
)
2454 Statement
*ReturnStatement::syntaxCopy()
2456 Expression
*e
= NULL
;
2458 e
= exp
->syntaxCopy();
2459 ReturnStatement
*s
= new ReturnStatement(loc
, e
);
2463 Statement
*ReturnStatement::semantic(Scope
*sc
)
2465 //printf("ReturnStatement::semantic() %s\n", toChars());
2467 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
2473 // Find scope of function foreach is in
2474 for (; 1; scx
= scx
->enclosing
)
2477 if (scx
->func
!= fd
)
2478 { fd
= scx
->func
; // fd is now function enclosing foreach
2484 Type
*tret
= fd
->type
->nextOf();
2486 tret
= fd
->tintro
->nextOf();
2490 tbret
= tret
->toBasetype();
2492 // main() returns 0, even if it returns void
2493 if (!exp
&& (!tbret
|| tbret
->ty
== Tvoid
) && fd
->isMain())
2495 exp
= new IntegerExp(0);
2498 if (sc
->incontract
|| scx
->incontract
)
2499 error("return statements cannot be in contracts");
2500 if (sc
->tf
|| scx
->tf
)
2501 error("return statements cannot be in finally, scope(exit) or scope(success) bodies");
2503 if (fd
->isCtorDeclaration())
2505 // Constructors implicitly do:
2507 if (exp
&& exp
->op
!= TOKthis
)
2508 error("cannot return expression from constructor");
2509 exp
= new ThisExp(0);
2517 fd
->hasReturnExp
|= 1;
2519 exp
= exp
->semantic(sc
);
2520 exp
= resolveProperties(sc
, exp
);
2521 exp
= exp
->optimize(WANTvalue
);
2523 if (fd
->nrvo_can
&& exp
->op
== TOKvar
)
2524 { VarExp
*ve
= (VarExp
*)exp
;
2525 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
2527 if (!v
|| v
->isOut() || v
->isRef())
2529 else if (fd
->nrvo_var
== NULL
)
2530 { if (!v
->isDataseg() && !v
->isParameter() && v
->toParent2() == fd
)
2535 else if (fd
->nrvo_var
!= v
)
2541 if (fd
->returnLabel
&& tbret
->ty
!= Tvoid
)
2544 else if (fd
->inferRetType
)
2546 if (fd
->type
->nextOf())
2548 if (!exp
->type
->equals(fd
->type
->nextOf()))
2549 error("mismatched function return type inference of %s and %s",
2550 exp
->type
->toChars(), fd
->type
->nextOf()->toChars());
2554 fd
->type
->next
= exp
->type
;
2555 fd
->type
= fd
->type
->semantic(loc
, sc
);
2557 { tret
= fd
->type
->nextOf();
2558 tbret
= tret
->toBasetype();
2562 else if (tbret
->ty
!= Tvoid
)
2564 exp
= exp
->implicitCastTo(sc
, tret
);
2567 else if (fd
->inferRetType
)
2569 if (fd
->type
->nextOf())
2571 if (fd
->type
->nextOf()->ty
!= Tvoid
)
2572 error("mismatched function return type inference of void and %s",
2573 fd
->type
->nextOf()->toChars());
2577 fd
->type
->next
= Type::tvoid
;
2578 fd
->type
= fd
->type
->semantic(loc
, sc
);
2580 { tret
= Type::tvoid
;
2585 else if (tbret
->ty
!= Tvoid
) // if non-void return
2586 error("return expression expected");
2592 if (exp
&& !implicit0
)
2594 exp
= exp
->implicitCastTo(sc
, tret
);
2596 if (!exp
|| exp
->op
== TOKint64
|| exp
->op
== TOKfloat64
||
2597 exp
->op
== TOKimaginary80
|| exp
->op
== TOKcomplex80
||
2598 exp
->op
== TOKthis
|| exp
->op
== TOKsuper
|| exp
->op
== TOKnull
||
2599 exp
->op
== TOKstring
)
2601 sc
->fes
->cases
.push(this);
2602 s
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
2604 else if (fd
->type
->nextOf()->toBasetype() == Type::tvoid
)
2609 s
= new ReturnStatement(0, NULL
);
2610 sc
->fes
->cases
.push(s
);
2612 // Construct: { exp; return cases.dim + 1; }
2613 s1
= new ExpStatement(loc
, exp
);
2614 s2
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
2615 s
= new CompoundStatement(loc
, s1
, s2
);
2623 // Construct: return vresult;
2625 { VarDeclaration
*v
;
2627 v
= new VarDeclaration(loc
, tret
, Id::result
, NULL
);
2630 if (!scx
->insert(v
))
2636 v
= new VarExp(0, fd
->vresult
);
2637 s
= new ReturnStatement(0, v
);
2638 sc
->fes
->cases
.push(s
);
2640 // Construct: { vresult = exp; return cases.dim + 1; }
2641 v
= new VarExp(0, fd
->vresult
);
2642 exp
= new AssignExp(loc
, v
, exp
);
2643 exp
= exp
->semantic(sc
);
2644 s1
= new ExpStatement(loc
, exp
);
2645 s2
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
2646 s
= new CompoundStatement(loc
, s1
, s2
);
2653 if (fd
->returnLabel
&& tbret
->ty
!= Tvoid
)
2655 assert(fd
->vresult
);
2656 VarExp
*v
= new VarExp(0, fd
->vresult
);
2658 exp
= new AssignExp(loc
, v
, exp
);
2659 exp
= exp
->semantic(sc
);
2666 /* BUG: need to issue an error on:
2673 if (sc
->callSuper
& CSXany_ctor
&&
2674 !(sc
->callSuper
& (CSXthis_ctor
| CSXsuper_ctor
)))
2675 error("return without calling constructor");
2677 sc
->callSuper
|= CSXreturn
;
2679 // See if all returns are instead to be replaced with a goto returnLabel;
2680 if (fd
->returnLabel
)
2682 GotoStatement
*gs
= new GotoStatement(loc
, Id::returnLabel
);
2684 gs
->label
= fd
->returnLabel
;
2688 s
= new ExpStatement(0, exp
);
2689 return new CompoundStatement(loc
, s
, gs
);
2694 if (exp
&& tbret
->ty
== Tvoid
&& !fd
->isMain())
2697 s
= new ExpStatement(loc
, exp
);
2700 return new CompoundStatement(loc
, s
, this);
2706 int ReturnStatement::fallOffEnd()
2711 void ReturnStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2713 buf
->printf("return ");
2715 exp
->toCBuffer(buf
, hgs
);
2716 buf
->writeByte(';');
2720 /******************************** BreakStatement ***************************/
2722 BreakStatement::BreakStatement(Loc loc
, Identifier
*ident
)
2725 this->ident
= ident
;
2728 Statement
*BreakStatement::syntaxCopy()
2730 BreakStatement
*s
= new BreakStatement(loc
, ident
);
2734 Statement
*BreakStatement::semantic(Scope
*sc
)
2737 // break Identifier;
2741 FuncDeclaration
*thisfunc
= sc
->func
;
2743 for (scx
= sc
; scx
; scx
= scx
->enclosing
)
2747 if (scx
->func
!= thisfunc
) // if in enclosing function
2749 if (sc
->fes
) // if this is the body of a foreach
2751 /* Post this statement to the fes, and replace
2752 * it with a return value that caller will put into
2753 * a switch. Caller will figure out where the break
2754 * label actually is.
2755 * Case numbers start with 2, not 0, as 0 is continue
2759 sc
->fes
->cases
.push(this);
2760 s
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
2763 break; // can't break to it
2767 if (ls
&& ls
->ident
== ident
)
2769 Statement
*s
= ls
->statement
;
2772 error("label '%s' has no break", ident
->toChars());
2773 if (ls
->tf
!= sc
->tf
)
2774 error("cannot break out of finally block");
2778 error("enclosing label '%s' for break not found", ident
->toChars());
2780 else if (!sc
->sbreak
)
2785 // Replace break; with return 1;
2786 s
= new ReturnStatement(0, new IntegerExp(1));
2789 error("break is not inside a loop or switch");
2794 int BreakStatement::fallOffEnd()
2799 void BreakStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2801 buf
->writestring("break");
2803 { buf
->writebyte(' ');
2804 buf
->writestring(ident
->toChars());
2806 buf
->writebyte(';');
2810 /******************************** ContinueStatement ***************************/
2812 ContinueStatement::ContinueStatement(Loc loc
, Identifier
*ident
)
2815 this->ident
= ident
;
2818 Statement
*ContinueStatement::syntaxCopy()
2820 ContinueStatement
*s
= new ContinueStatement(loc
, ident
);
2824 Statement
*ContinueStatement::semantic(Scope
*sc
)
2826 //printf("ContinueStatement::semantic() %p\n", this);
2830 FuncDeclaration
*thisfunc
= sc
->func
;
2832 for (scx
= sc
; scx
; scx
= scx
->enclosing
)
2836 if (scx
->func
!= thisfunc
) // if in enclosing function
2838 if (sc
->fes
) // if this is the body of a foreach
2840 for (; scx
; scx
= scx
->enclosing
)
2843 if (ls
&& ls
->ident
== ident
&& ls
->statement
== sc
->fes
)
2845 // Replace continue ident; with return 0;
2846 return new ReturnStatement(0, new IntegerExp(0));
2850 /* Post this statement to the fes, and replace
2851 * it with a return value that caller will put into
2852 * a switch. Caller will figure out where the break
2853 * label actually is.
2854 * Case numbers start with 2, not 0, as 0 is continue
2858 sc
->fes
->cases
.push(this);
2859 s
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
2862 break; // can't continue to it
2866 if (ls
&& ls
->ident
== ident
)
2868 Statement
*s
= ls
->statement
;
2870 if (!s
->hasContinue())
2871 error("label '%s' has no continue", ident
->toChars());
2872 if (ls
->tf
!= sc
->tf
)
2873 error("cannot continue out of finally block");
2877 error("enclosing label '%s' for continue not found", ident
->toChars());
2879 else if (!sc
->scontinue
)
2884 // Replace continue; with return 0;
2885 s
= new ReturnStatement(0, new IntegerExp(0));
2888 error("continue is not inside a loop");
2893 int ContinueStatement::fallOffEnd()
2898 void ContinueStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2900 buf
->writestring("continue");
2902 { buf
->writebyte(' ');
2903 buf
->writestring(ident
->toChars());
2905 buf
->writebyte(';');
2909 /******************************** SynchronizedStatement ***************************/
2911 SynchronizedStatement::SynchronizedStatement(Loc loc
, Expression
*exp
, Statement
*body
)
2919 SynchronizedStatement::SynchronizedStatement(Loc loc
, elem
*esync
, Statement
*body
)
2924 this->esync
= esync
;
2927 Statement
*SynchronizedStatement::syntaxCopy()
2929 Expression
*e
= exp
? exp
->syntaxCopy() : NULL
;
2930 SynchronizedStatement
*s
= new SynchronizedStatement(loc
, e
, body
? body
->syntaxCopy() : NULL
);
2934 Statement
*SynchronizedStatement::semantic(Scope
*sc
)
2937 { ClassDeclaration
*cd
;
2939 exp
= exp
->semantic(sc
);
2940 exp
= resolveProperties(sc
, exp
);
2941 cd
= exp
->type
->isClassHandle();
2943 error("can only synchronize on class objects, not '%s'", exp
->type
->toChars());
2944 else if (cd
->isInterfaceDeclaration())
2945 { Type
*t
= new TypeIdentifier(0, Id::Object
);
2947 t
= t
->semantic(0, sc
);
2948 exp
= new CastExp(loc
, exp
, t
);
2949 exp
= exp
->semantic(sc
);
2953 body
= body
->semantic(sc
);
2957 int SynchronizedStatement::hasBreak()
2959 return FALSE
; //TRUE;
2962 int SynchronizedStatement::hasContinue()
2964 return FALSE
; //TRUE;
2967 int SynchronizedStatement::usesEH()
2972 int SynchronizedStatement::fallOffEnd()
2974 return body
? body
->fallOffEnd() : TRUE
;
2977 void SynchronizedStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2979 buf
->writestring("synchronized");
2981 { buf
->writebyte('(');
2982 exp
->toCBuffer(buf
, hgs
);
2983 buf
->writebyte(')');
2987 buf
->writebyte(' ');
2988 body
->toCBuffer(buf
, hgs
);
2992 /******************************** WithStatement ***************************/
2994 WithStatement::WithStatement(Loc loc
, Expression
*exp
, Statement
*body
)
3002 Statement
*WithStatement::syntaxCopy()
3004 WithStatement
*s
= new WithStatement(loc
, exp
->syntaxCopy(), body
? body
->syntaxCopy() : NULL
);
3008 Statement
*WithStatement::semantic(Scope
*sc
)
3009 { ScopeDsymbol
*sym
;
3012 //printf("WithStatement::semantic()\n");
3013 exp
= exp
->semantic(sc
);
3014 exp
= resolveProperties(sc
, exp
);
3015 if (exp
->op
== TOKimport
)
3016 { ScopeExp
*es
= (ScopeExp
*)exp
;
3020 else if (exp
->op
== TOKtype
)
3021 { TypeExp
*es
= (TypeExp
*)exp
;
3023 sym
= es
->type
->toDsymbol(sc
)->isScopeDsymbol();
3025 { error("%s has no members", es
->toChars());
3026 body
= body
->semantic(sc
);
3031 { Type
*t
= exp
->type
;
3034 t
= t
->toBasetype();
3035 if (t
->isClassHandle())
3037 init
= new ExpInitializer(loc
, exp
);
3038 wthis
= new VarDeclaration(loc
, exp
->type
, Id::withSym
, init
);
3039 wthis
->semantic(sc
);
3041 sym
= new WithScopeSymbol(this);
3042 sym
->parent
= sc
->scopesym
;
3044 else if (t
->ty
== Tstruct
)
3046 Expression
*e
= exp
->addressOf(sc
);
3047 init
= new ExpInitializer(loc
, e
);
3048 wthis
= new VarDeclaration(loc
, e
->type
, Id::withSym
, init
);
3049 wthis
->semantic(sc
);
3050 sym
= new WithScopeSymbol(this);
3051 sym
->parent
= sc
->scopesym
;
3054 { error("with expressions must be class objects, not '%s'", exp
->type
->toChars());
3061 body
= body
->semantic(sc
);
3068 void WithStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3070 buf
->writestring("with (");
3071 exp
->toCBuffer(buf
, hgs
);
3072 buf
->writestring(")\n");
3074 body
->toCBuffer(buf
, hgs
);
3077 int WithStatement::usesEH()
3079 return body
? body
->usesEH() : 0;
3082 int WithStatement::fallOffEnd()
3084 return body
? body
->fallOffEnd() : TRUE
;
3087 /******************************** TryCatchStatement ***************************/
3089 TryCatchStatement::TryCatchStatement(Loc loc
, Statement
*body
, Array
*catches
)
3093 this->catches
= catches
;
3096 Statement
*TryCatchStatement::syntaxCopy()
3098 Array
*a
= new Array();
3099 a
->setDim(catches
->dim
);
3100 for (int i
= 0; i
< a
->dim
; i
++)
3103 c
= (Catch
*)catches
->data
[i
];
3104 c
= c
->syntaxCopy();
3107 TryCatchStatement
*s
= new TryCatchStatement(loc
, body
->syntaxCopy(), a
);
3111 Statement
*TryCatchStatement::semantic(Scope
*sc
)
3113 body
= body
->semanticScope(sc
, NULL
/*this*/, NULL
);
3115 for (int i
= 0; i
< catches
->dim
; i
++)
3118 c
= (Catch
*)catches
->data
[i
];
3121 // Determine if current catch 'hides' any previous catches
3122 for (int j
= 0; j
< i
; j
++)
3123 { Catch
*cj
= (Catch
*)catches
->data
[j
];
3124 char *si
= c
->loc
.toChars();
3125 char *sj
= cj
->loc
.toChars();
3127 if (c
->type
->toBasetype()->implicitConvTo(cj
->type
->toBasetype()))
3128 error("catch at %s hides catch at %s", sj
, si
);
3134 int TryCatchStatement::hasBreak()
3136 return FALSE
; //TRUE;
3139 int TryCatchStatement::usesEH()
3144 int TryCatchStatement::fallOffEnd()
3149 result
= body
->fallOffEnd();
3150 for (int i
= 0; i
< catches
->dim
; i
++)
3153 c
= (Catch
*)catches
->data
[i
];
3155 result
|= c
->handler
->fallOffEnd();
3160 void TryCatchStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3162 buf
->writestring("try");
3165 body
->toCBuffer(buf
, hgs
);
3167 for (i
= 0; i
< catches
->dim
; i
++)
3169 Catch
*c
= (Catch
*)catches
->data
[i
];
3170 c
->toCBuffer(buf
, hgs
);
3174 /******************************** Catch ***************************/
3176 Catch::Catch(Loc loc
, Type
*t
, Identifier
*id
, Statement
*handler
)
3178 //printf("Catch(%s, loc = %s)\n", id->toChars(), loc.toChars());
3182 this->handler
= handler
;
3186 Catch
*Catch::syntaxCopy()
3188 Catch
*c
= new Catch(loc
,
3189 (type
? type
->syntaxCopy() : NULL
),
3191 (handler
? handler
->syntaxCopy() : NULL
));
3195 void Catch::semantic(Scope
*sc
)
3196 { ScopeDsymbol
*sym
;
3198 //printf("Catch::semantic(%s)\n", ident->toChars());
3203 /* This is because the _d_local_unwind() gets the stack munged
3204 * up on this. The workaround is to place any try-catches into
3205 * a separate function, and call that.
3206 * To fix, have the compiler automatically convert the finally
3207 * body into a nested function.
3209 error(loc
, "cannot put catch statement inside finally block");
3213 sym
= new ScopeDsymbol();
3214 sym
->parent
= sc
->scopesym
;
3218 type
= new TypeIdentifier(0, Id::Object
);
3219 type
= type
->semantic(loc
, sc
);
3220 if (!type
->toBasetype()->isClassHandle())
3221 error("can only catch class objects, not '%s'", type
->toChars());
3224 var
= new VarDeclaration(loc
, type
, ident
, NULL
);
3225 var
->parent
= sc
->parent
;
3228 handler
= handler
->semantic(sc
);
3233 void Catch::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3235 buf
->writestring("catch");
3237 { buf
->writebyte('(');
3238 type
->toCBuffer(buf
, ident
, hgs
);
3239 buf
->writebyte(')');
3242 buf
->writebyte('{');
3244 handler
->toCBuffer(buf
, hgs
);
3245 buf
->writebyte('}');
3249 /****************************** TryFinallyStatement ***************************/
3251 TryFinallyStatement::TryFinallyStatement(Loc loc
, Statement
*body
, Statement
*finalbody
)
3255 this->finalbody
= finalbody
;
3258 Statement
*TryFinallyStatement::syntaxCopy()
3260 TryFinallyStatement
*s
= new TryFinallyStatement(loc
,
3261 body
->syntaxCopy(), finalbody
->syntaxCopy());
3265 Statement
*TryFinallyStatement::semantic(Scope
*sc
)
3267 //printf("TryFinallyStatement::semantic()\n");
3268 body
= body
->semantic(sc
);
3272 sc
->scontinue
= NULL
; // no break or continue out of finally block
3273 finalbody
= finalbody
->semantic(sc
);
3278 void TryFinallyStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3280 buf
->printf("try\n{\n");
3281 body
->toCBuffer(buf
, hgs
);
3282 buf
->printf("}\nfinally\n{\n");
3283 finalbody
->toCBuffer(buf
, hgs
);
3284 buf
->writeByte('}');
3288 int TryFinallyStatement::hasBreak()
3290 return FALSE
; //TRUE;
3293 int TryFinallyStatement::hasContinue()
3295 return FALSE
; //TRUE;
3298 int TryFinallyStatement::usesEH()
3303 int TryFinallyStatement::fallOffEnd()
3306 result
= body
? body
->fallOffEnd() : TRUE
;
3308 // result = finalbody->fallOffEnd();
3312 /****************************** OnScopeStatement ***************************/
3314 OnScopeStatement::OnScopeStatement(Loc loc
, TOK tok
, Statement
*statement
)
3318 this->statement
= statement
;
3321 Statement
*OnScopeStatement::syntaxCopy()
3323 OnScopeStatement
*s
= new OnScopeStatement(loc
,
3324 tok
, statement
->syntaxCopy());
3328 Statement
*OnScopeStatement::semantic(Scope
*sc
)
3330 /* semantic is called on results of scopeCode() */
3334 void OnScopeStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3336 buf
->writestring(Token::toChars(tok
));
3337 buf
->writebyte(' ');
3338 statement
->toCBuffer(buf
, hgs
);
3341 int OnScopeStatement::usesEH()
3343 return (tok
!= TOKon_scope_success
);
3346 void OnScopeStatement::scopeCode(Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
3348 //printf("OnScopeStatement::scopeCode()\n");
3355 case TOKon_scope_exit
:
3356 *sfinally
= statement
;
3359 case TOKon_scope_failure
:
3360 *sexception
= statement
;
3363 case TOKon_scope_success
:
3366 * sentry: int x = 0;
3367 * sexception: x = 1;
3368 * sfinally: if (!x) statement;
3371 char name
[5 + sizeof(num
) * 3 + 1];
3372 sprintf(name
, "__osf%d", ++num
);
3373 Identifier
*id
= Lexer::idPool(name
);
3375 ExpInitializer
*ie
= new ExpInitializer(loc
, new IntegerExp(0));
3376 VarDeclaration
*v
= new VarDeclaration(loc
, Type::tint32
, id
, ie
);
3377 *sentry
= new DeclarationStatement(loc
, v
);
3379 Expression
*e
= new IntegerExp(1);
3380 e
= new AssignExp(0, new VarExp(0, v
), e
);
3381 *sexception
= new ExpStatement(0, e
);
3383 e
= new VarExp(0, v
);
3384 e
= new NotExp(0, e
);
3385 *sfinally
= new IfStatement(0, NULL
, e
, statement
, NULL
);
3395 /******************************** ThrowStatement ***************************/
3397 ThrowStatement::ThrowStatement(Loc loc
, Expression
*exp
)
3403 Statement
*ThrowStatement::syntaxCopy()
3405 ThrowStatement
*s
= new ThrowStatement(loc
, exp
->syntaxCopy());
3409 Statement
*ThrowStatement::semantic(Scope
*sc
)
3411 //printf("ThrowStatement::semantic()\n");
3413 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
3414 fd
->hasReturnExp
|= 2;
3417 error("Throw statements cannot be in contracts");
3418 exp
= exp
->semantic(sc
);
3419 exp
= resolveProperties(sc
, exp
);
3420 if (!exp
->type
->toBasetype()->isClassHandle())
3421 error("can only throw class objects, not type %s", exp
->type
->toChars());
3425 int ThrowStatement::fallOffEnd()
3430 void ThrowStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3432 buf
->printf("throw ");
3433 exp
->toCBuffer(buf
, hgs
);
3434 buf
->writeByte(';');
3438 /******************************** VolatileStatement **************************/
3440 VolatileStatement::VolatileStatement(Loc loc
, Statement
*statement
)
3443 this->statement
= statement
;
3446 Statement
*VolatileStatement::syntaxCopy()
3448 VolatileStatement
*s
= new VolatileStatement(loc
,
3449 statement
? statement
->syntaxCopy() : NULL
);
3453 Statement
*VolatileStatement::semantic(Scope
*sc
)
3455 statement
= statement
? statement
->semantic(sc
) : NULL
;
3459 Statements
*VolatileStatement::flatten(Scope
*sc
)
3463 a
= statement
? statement
->flatten(sc
) : NULL
;
3465 { for (int i
= 0; i
< a
->dim
; i
++)
3466 { Statement
*s
= (Statement
*)a
->data
[i
];
3468 s
= new VolatileStatement(loc
, s
);
3476 int VolatileStatement::fallOffEnd()
3478 return statement
? statement
->fallOffEnd() : TRUE
;
3481 void VolatileStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3483 buf
->writestring("volatile");
3485 { if (statement
->isScopeStatement())
3488 buf
->writebyte(' ');
3489 statement
->toCBuffer(buf
, hgs
);
3494 /******************************** GotoStatement ***************************/
3496 GotoStatement::GotoStatement(Loc loc
, Identifier
*ident
)
3499 this->ident
= ident
;
3504 Statement
*GotoStatement::syntaxCopy()
3506 GotoStatement
*s
= new GotoStatement(loc
, ident
);
3510 Statement
*GotoStatement::semantic(Scope
*sc
)
3511 { FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
3513 //printf("GotoStatement::semantic()\n");
3515 label
= fd
->searchLabel(ident
);
3516 if (!label
->statement
&& sc
->fes
)
3518 /* Either the goto label is forward referenced or it
3519 * is in the function that the enclosing foreach is in.
3520 * Can't know yet, so wrap the goto in a compound statement
3521 * so we can patch it later, and add it to a 'look at this later'
3524 Statements
*a
= new Statements();
3528 s
= new CompoundStatement(loc
, a
);
3529 sc
->fes
->gotos
.push(s
); // 'look at this later' list
3532 if (label
->statement
&& label
->statement
->tf
!= sc
->tf
)
3533 error("cannot goto in or out of finally block");
3537 int GotoStatement::fallOffEnd()
3542 void GotoStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3544 buf
->writestring("goto ");
3545 buf
->writestring(ident
->toChars());
3546 buf
->writebyte(';');
3550 /******************************** LabelStatement ***************************/
3552 LabelStatement::LabelStatement(Loc loc
, Identifier
*ident
, Statement
*statement
)
3555 this->ident
= ident
;
3556 this->statement
= statement
;
3558 this->lblock
= NULL
;
3559 this->isReturnLabel
= 0;
3562 Statement
*LabelStatement::syntaxCopy()
3564 LabelStatement
*s
= new LabelStatement(loc
, ident
, statement
->syntaxCopy());
3568 Statement
*LabelStatement::semantic(Scope
*sc
)
3570 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
3572 //printf("LabelStatement::semantic()\n");
3573 ls
= fd
->searchLabel(ident
);
3575 error("Label '%s' already defined", ls
->toChars());
3577 ls
->statement
= this;
3580 sc
->scopesym
= sc
->enclosing
->scopesym
;
3581 sc
->callSuper
|= CSXlabel
;
3584 statement
= statement
->semantic(sc
);
3589 Statements
*LabelStatement::flatten(Scope
*sc
)
3591 Statements
*a
= NULL
;
3595 a
= statement
->flatten(sc
);
3600 a
->push(new ExpStatement(loc
, NULL
));
3602 Statement
*s
= (Statement
*)a
->data
[0];
3604 s
= new LabelStatement(loc
, ident
, s
);
3613 int LabelStatement::usesEH()
3615 return statement
? statement
->usesEH() : FALSE
;
3618 int LabelStatement::fallOffEnd()
3620 return statement
? statement
->fallOffEnd() : TRUE
;
3623 int LabelStatement::comeFrom()
3625 //printf("LabelStatement::comeFrom()\n");
3629 void LabelStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3631 buf
->writestring(ident
->toChars());
3632 buf
->writebyte(':');
3635 statement
->toCBuffer(buf
, hgs
);
3639 /******************************** LabelDsymbol ***************************/
3641 LabelDsymbol::LabelDsymbol(Identifier
*ident
)
3650 LabelDsymbol
*LabelDsymbol::isLabel() // is this a LabelDsymbol()?