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
*runMain
= new CompoundStatement(loc
, assignExt
, s
);
411 // catch (SystemExit)
412 Array
*catches
= new Array();
413 Statement
*handler
= new ExpStatement(loc
, new CallExp(loc
,
415 new IdentifierExp(loc
, Id::externals
),
417 new IdentifierExp(loc
, Id::result
)));
418 Catch
*c
= new Catch(loc
, new TypeIdentifier(loc
, Id::SystemExit
), Id::result
, handler
);
420 Statement
*body
= new TryCatchStatement(loc
, runMain
, catches
);
421 return body
->semantic(sc
);
424 /******************************** CompoundStatement ***************************/
426 CompoundStatement::CompoundStatement(Loc loc
, Statements
*s
)
432 CompoundStatement::CompoundStatement(Loc loc
, Statement
*s1
, Statement
*s2
)
435 statements
= new Statements();
436 statements
->reserve(2);
437 statements
->push(s1
);
438 statements
->push(s2
);
441 Statement
*CompoundStatement::syntaxCopy()
443 Statements
*a
= new Statements();
444 a
->setDim(statements
->dim
);
445 for (size_t i
= 0; i
< statements
->dim
; i
++)
446 { Statement
*s
= (Statement
*)statements
->data
[i
];
451 CompoundStatement
*cs
= new CompoundStatement(loc
, a
);
456 Statement
*CompoundStatement::semantic(Scope
*sc
)
459 //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", this, sc);
461 for (size_t i
= 0; i
< statements
->dim
; )
463 s
= (Statement
*) statements
->data
[i
];
465 { Statements
*a
= s
->flatten(sc
);
469 statements
->remove(i
);
470 statements
->insert(i
, a
);
474 statements
->data
[i
] = s
;
478 Statement
*sexception
;
481 s
->scopeCode(&sentry
, &sexception
, &sfinally
);
484 sentry
= sentry
->semantic(sc
);
485 statements
->data
[i
] = sentry
;
489 if (i
+ 1 == statements
->dim
&& !sfinally
)
492 sexception
= sexception
->semantic(sc
);
494 statements
->push(sexception
);
496 // Assume sexception does not throw
497 statements
->push(sfinally
);
508 * { sexception; throw __o; }
511 Statements
*a
= new Statements();
513 for (int j
= i
+ 1; j
< statements
->dim
; j
++)
515 a
->push(statements
->data
[j
]);
517 body
= new CompoundStatement(0, a
);
518 body
= new ScopeStatement(0, body
);
521 char name
[3 + sizeof(num
) * 3 + 1];
522 sprintf(name
, "__o%d", ++num
);
523 Identifier
*id
= Lexer::idPool(name
);
525 Statement
*handler
= new ThrowStatement(0, new IdentifierExp(0, id
));
526 handler
= new CompoundStatement(0, sexception
, handler
);
528 Array
*catches
= new Array();
529 Catch
*ctch
= new Catch(0, NULL
, id
, handler
);
531 s
= new TryCatchStatement(0, body
, catches
);
534 s
= new TryFinallyStatement(0, s
, sfinally
);
536 statements
->setDim(i
+ 1);
543 if (0 && i
+ 1 == statements
->dim
)
545 statements
->push(sfinally
);
552 * s; try { s1; s2; } finally { sfinally; }
555 Statements
*a
= new Statements();
557 for (int j
= i
+ 1; j
< statements
->dim
; j
++)
559 a
->push(statements
->data
[j
]);
561 body
= new CompoundStatement(0, a
);
562 s
= new TryFinallyStatement(0, body
, sfinally
);
564 statements
->setDim(i
+ 1);
573 if (statements
->dim
== 1)
578 Statements
*CompoundStatement::flatten(Scope
*sc
)
583 ReturnStatement
*CompoundStatement::isReturnStatement()
585 ReturnStatement
*rs
= NULL
;
587 for (i
= 0; i
< statements
->dim
; i
++)
590 s
= (Statement
*) statements
->data
[i
];
593 rs
= s
->isReturnStatement();
601 void CompoundStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
604 for (i
= 0; i
< statements
->dim
; i
++)
607 s
= (Statement
*) statements
->data
[i
];
609 s
->toCBuffer(buf
, hgs
);
613 int CompoundStatement::usesEH()
615 for (int i
= 0; i
< statements
->dim
; i
++)
618 s
= (Statement
*) statements
->data
[i
];
619 if (s
&& s
->usesEH())
625 int CompoundStatement::fallOffEnd()
626 { int falloff
= TRUE
;
628 //printf("CompoundStatement::fallOffEnd() %s\n", toChars());
629 for (int i
= 0; i
< statements
->dim
; i
++)
630 { Statement
*s
= (Statement
*)statements
->data
[i
];
635 if (!falloff
&& global
.params
.warnings
&& !s
->comeFrom())
637 fprintf(stdmsg
, "warning - ");
638 s
->error("statement is not reachable");
640 falloff
= s
->fallOffEnd();
645 int CompoundStatement::comeFrom()
646 { int comefrom
= FALSE
;
648 //printf("CompoundStatement::comeFrom()\n");
649 for (int i
= 0; i
< statements
->dim
; i
++)
650 { Statement
*s
= (Statement
*)statements
->data
[i
];
655 comefrom
|= s
->comeFrom();
661 /**************************** UnrolledLoopStatement ***************************/
663 UnrolledLoopStatement::UnrolledLoopStatement(Loc loc
, Statements
*s
)
669 Statement
*UnrolledLoopStatement::syntaxCopy()
671 Statements
*a
= new Statements();
672 a
->setDim(statements
->dim
);
673 for (size_t i
= 0; i
< statements
->dim
; i
++)
674 { Statement
*s
= (Statement
*)statements
->data
[i
];
679 UnrolledLoopStatement
*cs
= new UnrolledLoopStatement(loc
, a
);
684 Statement
*UnrolledLoopStatement::semantic(Scope
*sc
)
686 //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc);
689 Scope
*scd
= sc
->push();
691 scd
->scontinue
= this;
693 for (size_t i
= 0; i
< statements
->dim
; i
++)
695 Statement
*s
= (Statement
*) statements
->data
[i
];
698 s
= s
->semantic(scd
);
699 statements
->data
[i
] = s
;
708 void UnrolledLoopStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
710 buf
->writestring("unrolled {");
713 for (size_t i
= 0; i
< statements
->dim
; i
++)
716 s
= (Statement
*) statements
->data
[i
];
718 s
->toCBuffer(buf
, hgs
);
725 int UnrolledLoopStatement::hasBreak()
730 int UnrolledLoopStatement::hasContinue()
735 int UnrolledLoopStatement::usesEH()
737 for (size_t i
= 0; i
< statements
->dim
; i
++)
740 s
= (Statement
*) statements
->data
[i
];
741 if (s
&& s
->usesEH())
747 int UnrolledLoopStatement::fallOffEnd()
749 //printf("UnrolledLoopStatement::fallOffEnd()\n");
750 for (size_t i
= 0; i
< statements
->dim
; i
++)
751 { Statement
*s
= (Statement
*)statements
->data
[i
];
760 int UnrolledLoopStatement::comeFrom()
761 { int comefrom
= FALSE
;
763 //printf("UnrolledLoopStatement::comeFrom()\n");
764 for (size_t i
= 0; i
< statements
->dim
; i
++)
765 { Statement
*s
= (Statement
*)statements
->data
[i
];
770 comefrom
|= s
->comeFrom();
776 /******************************** ScopeStatement ***************************/
778 ScopeStatement::ScopeStatement(Loc loc
, Statement
*s
)
784 Statement
*ScopeStatement::syntaxCopy()
788 s
= statement
? statement
->syntaxCopy() : NULL
;
789 s
= new ScopeStatement(loc
, s
);
794 Statement
*ScopeStatement::semantic(Scope
*sc
)
797 //printf("ScopeStatement::semantic(sc = %p)\n", sc);
801 sym
= new ScopeDsymbol();
802 sym
->parent
= sc
->scopesym
;
805 a
= statement
->flatten(sc
);
808 statement
= new CompoundStatement(loc
, a
);
811 statement
= statement
->semantic(sc
);
815 Statement
*sexception
;
818 statement
->scopeCode(&sentry
, &sexception
, &sfinally
);
821 //printf("adding sfinally\n");
822 statement
= new CompoundStatement(loc
, statement
, sfinally
);
831 int ScopeStatement::hasBreak()
833 //printf("ScopeStatement::hasBreak() %s\n", toChars());
834 return statement
? statement
->hasBreak() : FALSE
;
837 int ScopeStatement::hasContinue()
839 return statement
? statement
->hasContinue() : FALSE
;
842 int ScopeStatement::usesEH()
844 return statement
? statement
->usesEH() : FALSE
;
847 int ScopeStatement::fallOffEnd()
849 return statement
? statement
->fallOffEnd() : TRUE
;
852 int ScopeStatement::comeFrom()
854 //printf("ScopeStatement::comeFrom()\n");
855 return statement
? statement
->comeFrom() : FALSE
;
858 void ScopeStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
864 statement
->toCBuffer(buf
, hgs
);
870 /******************************** WhileStatement ***************************/
872 WhileStatement::WhileStatement(Loc loc
, Expression
*c
, Statement
*b
)
879 Statement
*WhileStatement::syntaxCopy()
881 WhileStatement
*s
= new WhileStatement(loc
, condition
->syntaxCopy(), body
? body
->syntaxCopy() : NULL
);
886 Statement
*WhileStatement::semantic(Scope
*sc
)
889 if (condition
->op
== TOKmatch
)
891 /* Rewrite while (condition) body as:
895 * while ((_match = _match.opNext), _match);
898 Expression
*ew
= new IdentifierExp(0, Id::_match
);
899 ew
= new DotIdExp(0, ew
, Id::next
);
900 ew
= new AssignExp(0, new IdentifierExp(0, Id::_match
), ew
);
901 ////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0));
902 Expression
*ev
= new IdentifierExp(0, Id::_match
);
903 //ev = new CastExp(0, ev, Type::tvoidptr);
904 ew
= new CommaExp(0, ew
, ev
);
905 Statement
*sw
= new DoStatement(loc
, body
, ew
);
906 Statement
*si
= new IfStatement(loc
, condition
, sw
, NULL
);
907 return si
->semantic(sc
);
911 condition
= condition
->semantic(sc
);
912 condition
= resolveProperties(sc
, condition
);
913 condition
= condition
->optimize(WANTvalue
);
914 condition
= condition
->checkToBoolean();
918 Scope
*scd
= sc
->push();
920 scd
->scontinue
= this;
922 body
= body
->semantic(scd
);
930 int WhileStatement::hasBreak()
935 int WhileStatement::hasContinue()
940 int WhileStatement::usesEH()
942 return body
? body
->usesEH() : 0;
945 int WhileStatement::fallOffEnd()
952 int WhileStatement::comeFrom()
955 return body
->comeFrom();
959 void WhileStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
961 buf
->writestring("while (");
962 condition
->toCBuffer(buf
, hgs
);
966 body
->toCBuffer(buf
, hgs
);
969 /******************************** DoStatement ***************************/
971 DoStatement::DoStatement(Loc loc
, Statement
*b
, Expression
*c
)
978 Statement
*DoStatement::syntaxCopy()
980 DoStatement
*s
= new DoStatement(loc
, body
? body
->syntaxCopy() : NULL
, condition
->syntaxCopy());
985 Statement
*DoStatement::semantic(Scope
*sc
)
989 body
= body
->semanticScope(sc
, this, this);
991 condition
= condition
->semantic(sc
);
992 condition
= resolveProperties(sc
, condition
);
993 condition
= condition
->optimize(WANTvalue
);
995 condition
= condition
->checkToBoolean();
1000 int DoStatement::hasBreak()
1005 int DoStatement::hasContinue()
1010 int DoStatement::usesEH()
1012 return body
? body
->usesEH() : 0;
1015 int DoStatement::fallOffEnd()
1022 int DoStatement::comeFrom()
1025 return body
->comeFrom();
1029 void DoStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1031 buf
->writestring("do");
1034 body
->toCBuffer(buf
, hgs
);
1035 buf
->writestring("while (");
1036 condition
->toCBuffer(buf
, hgs
);
1037 buf
->writebyte(')');
1040 /******************************** ForStatement ***************************/
1042 ForStatement::ForStatement(Loc loc
, Statement
*init
, Expression
*condition
, Expression
*increment
, Statement
*body
)
1046 this->condition
= condition
;
1047 this->increment
= increment
;
1051 Statement
*ForStatement::syntaxCopy()
1053 Statement
*i
= NULL
;
1055 i
= init
->syntaxCopy();
1056 Expression
*c
= NULL
;
1058 c
= condition
->syntaxCopy();
1059 Expression
*inc
= NULL
;
1061 inc
= increment
->syntaxCopy();
1062 ForStatement
*s
= new ForStatement(loc
, i
, c
, inc
, body
->syntaxCopy());
1066 Statement
*ForStatement::semantic(Scope
*sc
)
1068 ScopeDsymbol
*sym
= new ScopeDsymbol();
1069 sym
->parent
= sc
->scopesym
;
1072 init
= init
->semantic(sc
);
1074 // Use a default value
1075 condition
= new IntegerExp(loc
, 1, Type::tboolean
);
1077 condition
= condition
->semantic(sc
);
1078 condition
= resolveProperties(sc
, condition
);
1079 condition
= condition
->optimize(WANTvalue
);
1080 condition
= condition
->checkToBoolean();
1082 increment
= increment
->semantic(sc
);
1085 sc
->scontinue
= this;
1086 body
= body
->semantic(sc
);
1093 void ForStatement::scopeCode(Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
1095 //printf("ForStatement::scopeCode()\n");
1098 init
->scopeCode(sentry
, sexception
, sfinally
);
1100 Statement::scopeCode(sentry
, sexception
, sfinally
);
1103 int ForStatement::hasBreak()
1105 //printf("ForStatement::hasBreak()\n");
1109 int ForStatement::hasContinue()
1114 int ForStatement::usesEH()
1116 return (init
&& init
->usesEH()) || body
->usesEH();
1119 int ForStatement::fallOffEnd()
1126 int ForStatement::comeFrom()
1128 //printf("ForStatement::comeFrom()\n");
1130 { int result
= body
->comeFrom();
1131 //printf("result = %d\n", result);
1137 void ForStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1139 buf
->writestring("for (");
1143 hgs
->FLinit
.decl
= 0;
1144 init
->toCBuffer(buf
, hgs
);
1145 if (hgs
->FLinit
.decl
> 0)
1146 buf
->writebyte(';');
1147 hgs
->FLinit
.decl
= 0;
1151 buf
->writebyte(';');
1153 { buf
->writebyte(' ');
1154 condition
->toCBuffer(buf
, hgs
);
1156 buf
->writebyte(';');
1158 { buf
->writebyte(' ');
1159 increment
->toCBuffer(buf
, hgs
);
1161 buf
->writebyte(')');
1163 buf
->writebyte('{');
1165 body
->toCBuffer(buf
, hgs
);
1166 buf
->writebyte('}');
1170 /******************************** ForeachStatement ***************************/
1172 ForeachStatement::ForeachStatement(Loc loc
, enum TOK op
, Arguments
*arguments
,
1173 Expression
*aggr
, Statement
*body
)
1177 this->arguments
= arguments
;
1187 Statement
*ForeachStatement::syntaxCopy()
1189 Arguments
*args
= Argument::arraySyntaxCopy(arguments
);
1190 Expression
*exp
= aggr
->syntaxCopy();
1191 ForeachStatement
*s
= new ForeachStatement(loc
, op
, args
, exp
,
1192 body
? body
->syntaxCopy() : NULL
);
1196 Statement
*ForeachStatement::semantic(Scope
*sc
)
1198 //printf("ForeachStatement::semantic() %p\n", this);
1200 Statement
*s
= this;
1201 int dim
= arguments
->dim
;
1203 TypeAArray
*taa
= NULL
;
1210 func
= func
->fes
->func
;
1212 aggr
= aggr
->semantic(sc
);
1213 aggr
= resolveProperties(sc
, aggr
);
1216 error("invalid foreach aggregate %s", aggr
->toChars());
1220 inferApplyArgTypes(op
, arguments
, aggr
);
1222 /* Check for inference errors
1224 if (dim
!= arguments
->dim
)
1226 //printf("dim = %d, arguments->dim = %d\n", dim, arguments->dim);
1227 error("cannot uniquely infer foreach argument types");
1231 Type
*tab
= aggr
->type
->toBasetype();
1233 if (tab
->ty
== Ttuple
) // don't generate new scope for tuple loops
1235 if (dim
< 1 || dim
> 2)
1237 error("only one (value) or two (key,value) arguments for tuple foreach");
1241 TypeTuple
*tuple
= (TypeTuple
*)tab
;
1242 Statements
*statements
= new Statements();
1243 //printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars());
1245 TupleExp
*te
= NULL
;
1246 if (aggr
->op
== TOKtuple
) // expression tuple
1247 { te
= (TupleExp
*)aggr
;
1250 else if (aggr
->op
== TOKtype
) // type tuple
1252 n
= Argument::dim(tuple
->arguments
);
1256 for (size_t j
= 0; j
< n
; j
++)
1257 { size_t k
= (op
== TOKforeach
) ? j
: n
- 1 - j
;
1261 e
= (Expression
*)te
->exps
->data
[k
];
1263 t
= Argument::getNth(tuple
->arguments
, k
)->type
;
1264 Argument
*arg
= (Argument
*)arguments
->data
[0];
1265 Statements
*st
= new Statements();
1269 if (arg
->storageClass
& (STCout
| STCref
| STClazy
))
1270 error("no storage class for key %s", arg
->ident
->toChars());
1271 TY keyty
= arg
->type
->ty
;
1272 if ((keyty
!= Tint32
&& keyty
!= Tuns32
) &&
1273 (! global
.params
.isX86_64
||
1274 (keyty
!= Tint64
&& keyty
!= Tuns64
))
1277 error("foreach: key type must be int or uint, not %s", arg
->type
->toChars());
1279 Initializer
*ie
= new ExpInitializer(0, new IntegerExp(k
));
1280 VarDeclaration
*var
= new VarDeclaration(loc
, arg
->type
, arg
->ident
, ie
);
1281 var
->storage_class
|= STCconst
;
1282 DeclarationExp
*de
= new DeclarationExp(loc
, var
);
1283 st
->push(new ExpStatement(loc
, de
));
1284 arg
= (Argument
*)arguments
->data
[1]; // value
1287 if (arg
->storageClass
& (STCout
| STCref
| STClazy
))
1288 error("no storage class for value %s", arg
->ident
->toChars());
1292 if (e
->type
->toBasetype()->ty
== Tfunction
&&
1294 { VarExp
*ve
= (VarExp
*)e
;
1295 var
= new AliasDeclaration(loc
, arg
->ident
, ve
->var
);
1299 arg
->type
= e
->type
;
1300 Initializer
*ie
= new ExpInitializer(0, e
);
1301 VarDeclaration
*v
= new VarDeclaration(loc
, arg
->type
, arg
->ident
, ie
);
1303 v
->storage_class
|= STCconst
;
1306 v
->storage_class
|= STCfinal
;
1313 var
= new AliasDeclaration(loc
, arg
->ident
, t
);
1315 DeclarationExp
*de
= new DeclarationExp(loc
, var
);
1316 st
->push(new ExpStatement(loc
, de
));
1318 st
->push(body
->syntaxCopy());
1319 s
= new CompoundStatement(loc
, st
);
1320 s
= new ScopeStatement(loc
, s
);
1321 statements
->push(s
);
1324 s
= new UnrolledLoopStatement(loc
, statements
);
1325 s
= s
->semantic(sc
);
1329 for (i
= 0; i
< dim
; i
++)
1330 { Argument
*arg
= (Argument
*)arguments
->data
[i
];
1333 error("cannot infer type for %s", arg
->ident
->toChars());
1338 sym
= new ScopeDsymbol();
1339 sym
->parent
= sc
->scopesym
;
1348 if (dim
< 1 || dim
> 2)
1350 error("only one or two arguments for array foreach");
1354 /* Look for special case of parsing char types out of char type
1357 tn
= tab
->nextOf()->toBasetype();
1358 if (tn
->ty
== Tchar
|| tn
->ty
== Twchar
|| tn
->ty
== Tdchar
)
1361 i
= (dim
== 1) ? 0 : 1; // index of value
1362 arg
= (Argument
*)arguments
->data
[i
];
1363 arg
->type
= arg
->type
->semantic(loc
, sc
);
1364 tnv
= arg
->type
->toBasetype();
1365 if (tnv
->ty
!= tn
->ty
&&
1366 (tnv
->ty
== Tchar
|| tnv
->ty
== Twchar
|| tnv
->ty
== Tdchar
))
1368 if (arg
->storageClass
& STCref
)
1369 error("foreach: value of UTF conversion cannot be ref");
1371 { arg
= (Argument
*)arguments
->data
[0];
1372 if (arg
->storageClass
& STCref
)
1373 error("foreach: key cannot be ref");
1379 for (i
= 0; i
< dim
; i
++)
1381 Argument
*arg
= (Argument
*)arguments
->data
[i
];
1382 VarDeclaration
*var
;
1384 var
= new VarDeclaration(loc
, arg
->type
, arg
->ident
, NULL
);
1385 var
->storage_class
|= STCforeach
;
1386 var
->storage_class
|= arg
->storageClass
& (STCin
| STCout
| STCref
);
1388 DeclarationExp
*de
= new DeclarationExp(loc
, var
);
1392 if (!sc
->insert(var
))
1393 error("%s already defined", var
->ident
->toChars());
1395 if (dim
== 2 && i
== 0)
1402 sc
->scontinue
= this;
1403 body
= body
->semantic(sc
);
1405 if (!value
->type
->equals(tab
->next
))
1407 if (aggr
->op
== TOKstring
)
1408 aggr
= aggr
->implicitCastTo(sc
, value
->type
->arrayOf());
1410 error("foreach: %s is not an array of %s", tab
->toChars(), value
->type
->toChars());
1414 ((key
->type
->ty
!= Tint32
&& key
->type
->ty
!= Tuns32
) &&
1415 (! global
.params
.isX86_64
||
1416 (key
->type
->ty
!= Tint64
&& key
->type
->ty
!= Tuns64
))
1420 error("foreach: key type must be int or uint, not %s", key
->type
->toChars());
1423 if (key
&& key
->storage_class
& (STCout
| STCref
))
1424 error("foreach: key cannot be out or ref");
1428 taa
= (TypeAArray
*)tab
;
1429 if (dim
< 1 || dim
> 2)
1431 error("only one or two arguments for associative array foreach");
1434 if (op
== TOKforeach_reverse
)
1436 error("no reverse iteration on associative arrays");
1444 { FuncDeclaration
*fdapply
;
1448 FuncLiteralDeclaration
*fld
;
1455 tret
= func
->type
->nextOf();
1457 // Need a variable to hold value from any return statements in body.
1458 if (!sc
->func
->vresult
&& tret
&& tret
!= Type::tvoid
)
1459 { VarDeclaration
*v
;
1461 v
= new VarDeclaration(loc
, tret
, Id::result
, NULL
);
1466 v
->parent
= sc
->func
;
1467 sc
->func
->vresult
= v
;
1470 /* Turn body into the function literal:
1471 * int delegate(ref T arg) { body }
1473 args
= new Arguments();
1474 for (i
= 0; i
< dim
; i
++)
1475 { Argument
*arg
= (Argument
*)arguments
->data
[i
];
1477 arg
->type
= arg
->type
->semantic(loc
, sc
);
1478 if (arg
->storageClass
& STCref
)
1481 { // Make a copy of the ref argument so it isn't
1485 char applyArg
[10 + sizeof(i
)*3 + 1];
1487 sprintf(applyArg
, "__applyArg%d", i
);
1488 id
= Lexer::idPool(applyArg
);
1490 ie
= new ExpInitializer(0, new IdentifierExp(0, id
));
1491 v
= new VarDeclaration(0, arg
->type
, arg
->ident
, ie
);
1492 s
= new DeclarationStatement(0, v
);
1493 body
= new CompoundStatement(loc
, s
, body
);
1495 a
= new Argument(STCref
, arg
->type
, id
, NULL
);
1498 t
= new TypeFunction(args
, Type::tint32
, 0, LINKd
);
1499 fld
= new FuncLiteralDeclaration(loc
, 0, t
, TOKdelegate
, this);
1501 flde
= new FuncExp(loc
, fld
);
1502 flde
= flde
->semantic(sc
);
1504 // Resolve any forward referenced goto's
1505 for (int i
= 0; i
< gotos
.dim
; i
++)
1506 { CompoundStatement
*cs
= (CompoundStatement
*)gotos
.data
[i
];
1507 GotoStatement
*gs
= (GotoStatement
*)cs
->statements
->data
[0];
1509 if (!gs
->label
->statement
)
1510 { // 'Promote' it to this scope, and replace with a return
1512 s
= new ReturnStatement(0, new IntegerExp(cases
.dim
+ 1));
1513 cs
->statements
->data
[0] = (void *)s
;
1517 if (tab
->ty
== Taarray
)
1520 Argument
*arg
= (Argument
*)arguments
->data
[0];
1523 if (arg
->storageClass
& STCref
)
1524 error("foreach: index cannot be ref");
1525 if (!arg
->type
->equals(taa
->index
))
1526 error("foreach: index must be type %s, not %s", taa
->index
->toChars(), arg
->type
->toChars());
1527 arg
= (Argument
*)arguments
->data
[1];
1529 if (!arg
->type
->equals(taa
->nextOf()))
1530 error("foreach: value must be type %s, not %s", taa
->nextOf()->toChars(), arg
->type
->toChars());
1533 * _aaApply(aggr, keysize, flde)
1536 fdapply
= FuncDeclaration::genCfunc(Type::tint32
, "_aaApply2",
1537 Type::tvoid
->arrayOf(), Type::tsize_t
, flde
->type
); // flde->type is not generic
1539 fdapply
= FuncDeclaration::genCfunc(Type::tint32
, "_aaApply",
1540 Type::tvoid
->arrayOf(), Type::tsize_t
, flde
->type
); // flde->type is not generic);
1541 ec
= new VarExp(0, fdapply
);
1542 Expressions
*exps
= new Expressions();
1544 size_t keysize
= taa
->key
->size();
1545 keysize
= (keysize
+ (PTRSIZE
-1)) & ~(PTRSIZE
-1);
1546 exps
->push(new IntegerExp(0, keysize
, Type::tsize_t
));
1548 e
= new CallExp(loc
, ec
, exps
);
1549 e
->type
= Type::tint32
; // don't run semantic() on e
1551 else if (tab
->ty
== Tarray
|| tab
->ty
== Tsarray
)
1554 * _aApply(aggr, flde)
1556 static char fntab
[9][3] =
1561 char fdname
[7+1+2+ sizeof(dim
)*3 + 1];
1566 case Tchar
: flag
= 0; break;
1567 case Twchar
: flag
= 3; break;
1568 case Tdchar
: flag
= 6; break;
1573 case Tchar
: flag
+= 0; break;
1574 case Twchar
: flag
+= 1; break;
1575 case Tdchar
: flag
+= 2; break;
1578 const char *r
= (op
== TOKforeach_reverse
) ? "R" : "";
1579 int j
= sprintf(fdname
, "_aApply%s%.*s%d", r
, 2, fntab
[flag
], dim
);
1580 assert(j
< sizeof(fdname
));
1581 fdapply
= FuncDeclaration::genCfunc(Type::tint32
, fdname
,
1582 Type::tvoid
->arrayOf(), flde
->type
); // flde->type is not generic
1584 ec
= new VarExp(0, fdapply
);
1585 Expressions
*exps
= new Expressions();
1586 if (tab
->ty
== Tsarray
)
1587 aggr
= aggr
->castTo(sc
, tn
->arrayOf());
1590 e
= new CallExp(loc
, ec
, exps
);
1591 e
->type
= Type::tint32
; // don't run semantic() on e
1593 else if (tab
->ty
== Tdelegate
)
1598 Expressions
*exps
= new Expressions();
1600 e
= new CallExp(loc
, aggr
, exps
);
1601 e
= e
->semantic(sc
);
1602 if (e
->type
!= Type::tint32
)
1603 error("opApply() function for %s must return an int", tab
->toChars());
1610 ec
= new DotIdExp(loc
, aggr
,
1611 (op
== TOKforeach_reverse
) ? Id::applyReverse
1613 Expressions
*exps
= new Expressions();
1615 e
= new CallExp(loc
, ec
, exps
);
1616 e
= e
->semantic(sc
);
1617 if (e
->type
!= Type::tint32
)
1618 error("opApply() function for %s must return an int", tab
->toChars());
1622 // Easy case, a clean exit from the loop
1623 s
= new ExpStatement(loc
, e
);
1625 { // Construct a switch statement around the return value
1626 // of the apply function.
1627 Statements
*a
= new Statements();
1629 // default: break; takes care of cases 0 and 1
1630 s
= new BreakStatement(0, NULL
);
1631 s
= new DefaultStatement(0, s
);
1635 for (int i
= 0; i
< cases
.dim
; i
++)
1637 s
= (Statement
*)cases
.data
[i
];
1638 s
= new CaseStatement(0, new IntegerExp(i
+ 2), s
);
1642 s
= new CompoundStatement(loc
, a
);
1643 s
= new SwitchStatement(loc
, e
, s
);
1644 s
= s
->semantic(sc
);
1650 error("foreach: %s is not an aggregate type", aggr
->type
->toChars());
1658 int ForeachStatement::hasBreak()
1663 int ForeachStatement::hasContinue()
1668 int ForeachStatement::usesEH()
1670 return body
->usesEH();
1673 int ForeachStatement::fallOffEnd()
1680 int ForeachStatement::comeFrom()
1683 return body
->comeFrom();
1687 void ForeachStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1689 buf
->writestring(Token::toChars(op
));
1690 buf
->writestring(" (");
1692 for (int i
= 0; i
< arguments
->dim
; i
++)
1694 Argument
*a
= (Argument
*)arguments
->data
[i
];
1696 buf
->writestring(", ");
1697 if (a
->storageClass
& STCref
)
1698 buf
->writestring((global
.params
.Dversion
== 1)
1699 ? (char*)"inout " : (char*)"ref ");
1701 a
->type
->toCBuffer(buf
, a
->ident
, hgs
);
1703 buf
->writestring(a
->ident
->toChars());
1705 buf
->writestring("; ");
1706 aggr
->toCBuffer(buf
, hgs
);
1707 buf
->writebyte(')');
1709 buf
->writebyte('{');
1712 body
->toCBuffer(buf
, hgs
);
1713 buf
->writebyte('}');
1717 /******************************** IfStatement ***************************/
1719 IfStatement::IfStatement(Loc loc
, Argument
*arg
, Expression
*condition
, Statement
*ifbody
, Statement
*elsebody
)
1723 this->condition
= condition
;
1724 this->ifbody
= ifbody
;
1725 this->elsebody
= elsebody
;
1729 Statement
*IfStatement::syntaxCopy()
1731 Statement
*i
= NULL
;
1733 i
= ifbody
->syntaxCopy();
1735 Statement
*e
= NULL
;
1737 e
= elsebody
->syntaxCopy();
1739 Argument
*a
= arg
? arg
->syntaxCopy() : NULL
;
1740 IfStatement
*s
= new IfStatement(loc
, a
, condition
->syntaxCopy(), i
, e
);
1744 Statement
*IfStatement::semantic(Scope
*sc
)
1746 condition
= condition
->semantic(sc
);
1747 condition
= resolveProperties(sc
, condition
);
1748 condition
= condition
->checkToBoolean();
1750 // If we can short-circuit evaluate the if statement, don't do the
1751 // semantic analysis of the skipped code.
1752 // This feature allows a limited form of conditional compilation.
1753 condition
= condition
->optimize(WANTflags
);
1755 // Evaluate at runtime
1756 unsigned cs0
= sc
->callSuper
;
1761 { /* Declare arg, which we will set to be the
1762 * result of condition.
1764 ScopeDsymbol
*sym
= new ScopeDsymbol();
1765 sym
->parent
= sc
->scopesym
;
1766 scd
= sc
->push(sym
);
1768 Type
*t
= arg
->type
? arg
->type
: condition
->type
;
1769 match
= new VarDeclaration(loc
, t
, arg
->ident
, NULL
);
1771 match
->semantic(scd
);
1772 if (!scd
->insert(match
))
1774 match
->parent
= sc
->func
;
1779 VarExp
*v
= new VarExp(0, match
);
1780 condition
= new AssignExp(loc
, v
, condition
);
1781 condition
= condition
->semantic(scd
);
1785 ifbody
= ifbody
->semantic(scd
);
1788 cs1
= sc
->callSuper
;
1789 sc
->callSuper
= cs0
;
1791 elsebody
= elsebody
->semanticScope(sc
, NULL
, NULL
);
1792 sc
->mergeCallSuper(loc
, cs1
);
1797 int IfStatement::usesEH()
1799 return (ifbody
&& ifbody
->usesEH()) || (elsebody
&& elsebody
->usesEH());
1802 int IfStatement::fallOffEnd()
1804 if (!ifbody
|| ifbody
->fallOffEnd() ||
1805 !elsebody
|| elsebody
->fallOffEnd())
1811 void IfStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1813 buf
->writestring("if (");
1817 arg
->type
->toCBuffer(buf
, arg
->ident
, hgs
);
1819 buf
->writestring(arg
->ident
->toChars());
1820 buf
->writebyte(';');
1822 condition
->toCBuffer(buf
, hgs
);
1823 buf
->writebyte(')');
1825 ifbody
->toCBuffer(buf
, hgs
);
1827 { buf
->writestring("else");
1829 elsebody
->toCBuffer(buf
, hgs
);
1833 /******************************** ConditionalStatement ***************************/
1835 ConditionalStatement::ConditionalStatement(Loc loc
, Condition
*condition
, Statement
*ifbody
, Statement
*elsebody
)
1838 this->condition
= condition
;
1839 this->ifbody
= ifbody
;
1840 this->elsebody
= elsebody
;
1843 Statement
*ConditionalStatement::syntaxCopy()
1845 Statement
*e
= NULL
;
1847 e
= elsebody
->syntaxCopy();
1848 ConditionalStatement
*s
= new ConditionalStatement(loc
,
1849 condition
->syntaxCopy(), ifbody
->syntaxCopy(), e
);
1853 Statement
*ConditionalStatement::semantic(Scope
*sc
)
1855 //printf("ConditionalStatement::semantic()\n");
1857 // If we can short-circuit evaluate the if statement, don't do the
1858 // semantic analysis of the skipped code.
1859 // This feature allows a limited form of conditional compilation.
1860 if (condition
->include(sc
, NULL
))
1862 ifbody
= ifbody
->semantic(sc
);
1868 elsebody
= elsebody
->semantic(sc
);
1873 Statements
*ConditionalStatement::flatten(Scope
*sc
)
1877 if (condition
->include(sc
, NULL
))
1882 Statements
*a
= new Statements();
1887 int ConditionalStatement::usesEH()
1889 return (ifbody
&& ifbody
->usesEH()) || (elsebody
&& elsebody
->usesEH());
1892 void ConditionalStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
1894 condition
->toCBuffer(buf
, hgs
);
1897 ifbody
->toCBuffer(buf
, hgs
);
1900 buf
->writestring("else");
1902 elsebody
->toCBuffer(buf
, hgs
);
1908 /******************************** PragmaStatement ***************************/
1910 PragmaStatement::PragmaStatement(Loc loc
, Identifier
*ident
, Expressions
*args
, Statement
*body
)
1913 this->ident
= ident
;
1918 Statement
*PragmaStatement::syntaxCopy()
1920 Statement
*b
= NULL
;
1922 b
= body
->syntaxCopy();
1923 PragmaStatement
*s
= new PragmaStatement(loc
,
1924 ident
, Expression::arraySyntaxCopy(args
), b
);
1928 Statement
*PragmaStatement::semantic(Scope
*sc
)
1929 { // Should be merged with PragmaDeclaration
1930 //printf("PragmaStatement::semantic() %s\n", toChars());
1931 //printf("body = %p\n", body);
1932 if (ident
== Id::msg
)
1936 for (size_t i
= 0; i
< args
->dim
; i
++)
1938 Expression
*e
= (Expression
*)args
->data
[i
];
1940 e
= e
->semantic(sc
);
1941 e
= e
->optimize(WANTvalue
| WANTinterpret
);
1942 if (e
->op
== TOKstring
)
1944 StringExp
*se
= (StringExp
*)e
;
1945 fprintf(stdmsg
, "%.*s", (int)se
->len
, se
->string
);
1948 error("string expected for message, not '%s'", e
->toChars());
1950 fprintf(stdmsg
, "\n");
1953 else if (ident
== Id::lib
)
1955 if (!args
|| args
->dim
!= 1)
1956 error("string expected for library name");
1959 Expression
*e
= (Expression
*)args
->data
[0];
1961 e
= e
->semantic(sc
);
1962 e
= e
->optimize(WANTvalue
| WANTinterpret
);
1963 args
->data
[0] = (void *)e
;
1964 if (e
->op
!= TOKstring
)
1965 error("string expected for library name, not '%s'", e
->toChars());
1966 else if (global
.params
.verbose
)
1968 StringExp
*se
= (StringExp
*)e
;
1969 char *name
= (char *)mem
.malloc(se
->len
+ 1);
1970 memcpy(name
, se
->string
, se
->len
);
1972 printf("library %s\n", name
);
1978 error("unrecognized pragma(%s)", ident
->toChars());
1982 body
= body
->semantic(sc
);
1987 int PragmaStatement::usesEH()
1989 return body
&& body
->usesEH();
1992 int PragmaStatement::fallOffEnd()
1995 return body
->fallOffEnd();
1999 void PragmaStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2001 buf
->writestring("pragma (");
2002 buf
->writestring(ident
->toChars());
2003 if (args
&& args
->dim
)
2005 buf
->writestring(", ");
2006 argsToCBuffer(buf
, args
, hgs
);
2008 buf
->writeByte(')');
2012 buf
->writeByte('{');
2015 body
->toCBuffer(buf
, hgs
);
2017 buf
->writeByte('}');
2022 buf
->writeByte(';');
2028 /******************************** LogStatement ***************************/
2030 LogStatement::LogStatement(Loc loc
, int level
, Expressions
*args
)
2033 this->level
= level
;
2037 Statement
*LogStatement::semantic(Scope
*sc
)
2039 Expression
*logger
= new GetLoggerExp(loc
);
2042 for (Dsymbol
*s
= sc
->parent
; s
; s
= s
->parent
)
2044 ClassDeclaration
*cd
;
2045 StructDeclaration
*sd
;
2047 cd
= s
->isClassDeclaration();
2056 // We're a top-level function. Generate log messages from the module
2057 args
->shift(new StringExp(loc
, strdup(sc
->module
->ident
->string
)));
2059 args
->shift(new StringExp(loc
, type
->toChars()));
2062 args
->shift(new IntegerExp(loc
, level
, Type::tint32
));
2063 Expression
*callLogger
= new CallExp(loc
, logger
, args
);
2065 Statement
*s
= new ExpStatement(loc
, callLogger
);
2067 return s
->semantic(sc
);
2070 void LogStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2074 case 10: l
= "log_debug"; break;
2075 case 20: l
= "log_info"; break;
2076 case 30: l
= "log_warning"; break;
2077 case 40: l
= "log_error"; break;
2079 error("Unknown log level %d", level
);
2082 buf
->writestring(l
);
2083 buf
->writeByte('(');
2084 argsToCBuffer(buf
, args
, hgs
);
2085 buf
->writeByte(')');
2089 /******************************** StaticAssertStatement ***************************/
2091 StaticAssertStatement::StaticAssertStatement(StaticAssert
*sa
)
2092 : Statement(sa
->loc
)
2097 Statement
*StaticAssertStatement::syntaxCopy()
2099 StaticAssertStatement
*s
= new StaticAssertStatement((StaticAssert
*)sa
->syntaxCopy(NULL
));
2103 Statement
*StaticAssertStatement::semantic(Scope
*sc
)
2109 void StaticAssertStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2111 sa
->toCBuffer(buf
, hgs
);
2115 /******************************** SwitchStatement ***************************/
2117 SwitchStatement::SwitchStatement(Loc loc
, Expression
*c
, Statement
*b
)
2127 Statement
*SwitchStatement::syntaxCopy()
2129 SwitchStatement
*s
= new SwitchStatement(loc
,
2130 condition
->syntaxCopy(), body
->syntaxCopy());
2134 Statement
*SwitchStatement::semantic(Scope
*sc
)
2136 //printf("SwitchStatement::semantic(%p)\n", this);
2137 assert(!cases
); // ensure semantic() is only run once
2138 condition
= condition
->semantic(sc
);
2139 condition
= resolveProperties(sc
, condition
);
2140 if (condition
->type
->isString())
2142 // If it's not an array, cast it to one
2143 if (condition
->type
->ty
!= Tarray
)
2145 condition
= condition
->implicitCastTo(sc
, condition
->type
->nextOf()->arrayOf());
2149 { condition
= condition
->integralPromotions(sc
);
2150 condition
->checkIntegral();
2152 condition
= condition
->optimize(WANTvalue
);
2158 cases
= new Array();
2159 sc
->noctor
++; // BUG: should use Scope::mergeCallSuper() for each case instead
2160 body
= body
->semantic(sc
);
2163 // Resolve any goto case's with exp
2164 for (int i
= 0; i
< gotoCases
.dim
; i
++)
2166 GotoCaseStatement
*gcs
= (GotoCaseStatement
*)gotoCases
.data
[i
];
2170 gcs
->error("no case statement following goto case;");
2174 for (Scope
*scx
= sc
; scx
; scx
= scx
->enclosing
)
2178 for (int j
= 0; j
< scx
->sw
->cases
->dim
; j
++)
2180 CaseStatement
*cs
= (CaseStatement
*)scx
->sw
->cases
->data
[j
];
2182 if (cs
->exp
->equals(gcs
->exp
))
2189 gcs
->error("case %s not found", gcs
->exp
->toChars());
2195 if (!sc
->sw
->sdefault
)
2198 if (global
.params
.warnings
)
2199 { fprintf(stdmsg
, "warning - ");
2200 error("switch statement has no default");
2203 // Generate runtime error if the default is hit
2204 Statements
*a
= new Statements();
2205 CompoundStatement
*cs
;
2208 if (global
.params
.useSwitchError
)
2209 s
= new SwitchErrorStatement(loc
);
2211 { Expression
*e
= new HaltExp(loc
);
2212 s
= new ExpStatement(loc
, e
);
2217 a
->push(new BreakStatement(loc
, NULL
));
2218 sc
->sw
->sdefault
= new DefaultStatement(loc
, s
);
2219 a
->push(sc
->sw
->sdefault
);
2220 cs
= new CompoundStatement(loc
, a
);
2228 int SwitchStatement::hasBreak()
2233 int SwitchStatement::usesEH()
2235 return body
? body
->usesEH() : 0;
2238 int SwitchStatement::fallOffEnd()
2242 return TRUE
; // need to do this better
2245 void SwitchStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2247 buf
->writestring("switch (");
2248 condition
->toCBuffer(buf
, hgs
);
2249 buf
->writebyte(')');
2253 if (!body
->isScopeStatement())
2254 { buf
->writebyte('{');
2256 body
->toCBuffer(buf
, hgs
);
2257 buf
->writebyte('}');
2262 body
->toCBuffer(buf
, hgs
);
2267 /******************************** CaseStatement ***************************/
2269 CaseStatement::CaseStatement(Loc loc
, Expression
*exp
, Statement
*s
)
2273 this->statement
= s
;
2277 Statement
*CaseStatement::syntaxCopy()
2279 CaseStatement
*s
= new CaseStatement(loc
, exp
->syntaxCopy(), statement
->syntaxCopy());
2283 Statement
*CaseStatement::semantic(Scope
*sc
)
2284 { SwitchStatement
*sw
= sc
->sw
;
2286 //printf("CaseStatement::semantic() %s\n", toChars());
2287 exp
= exp
->semantic(sc
);
2291 exp
= exp
->implicitCastTo(sc
, sw
->condition
->type
);
2292 exp
= exp
->optimize(WANTvalue
| WANTinterpret
);
2293 if (exp
->op
!= TOKstring
&& exp
->op
!= TOKint64
)
2295 error("case must be a string or an integral constant, not %s", exp
->toChars());
2296 exp
= new IntegerExp(0);
2299 for (i
= 0; i
< sw
->cases
->dim
; i
++)
2301 CaseStatement
*cs
= (CaseStatement
*)sw
->cases
->data
[i
];
2303 //printf("comparing '%s' with '%s'\n", exp->toChars(), cs->exp->toChars());
2304 if (cs
->exp
->equals(exp
))
2305 { error("duplicate case %s in switch statement", exp
->toChars());
2310 sw
->cases
->push(this);
2312 // Resolve any goto case's with no exp to this case statement
2313 for (i
= 0; i
< sw
->gotoCases
.dim
; i
++)
2315 GotoCaseStatement
*gcs
= (GotoCaseStatement
*)sw
->gotoCases
.data
[i
];
2320 sw
->gotoCases
.remove(i
); // remove from array
2325 error("case not in switch statement");
2326 statement
= statement
->semantic(sc
);
2330 int CaseStatement::compare(Object
*obj
)
2332 // Sort cases so we can do an efficient lookup
2333 CaseStatement
*cs2
= (CaseStatement
*)(obj
);
2335 return exp
->compare(cs2
->exp
);
2338 int CaseStatement::usesEH()
2340 return statement
->usesEH();
2343 int CaseStatement::fallOffEnd()
2345 return statement
->fallOffEnd();
2348 int CaseStatement::comeFrom()
2353 void CaseStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2355 buf
->writestring("case ");
2356 exp
->toCBuffer(buf
, hgs
);
2357 buf
->writebyte(':');
2359 statement
->toCBuffer(buf
, hgs
);
2362 /******************************** DefaultStatement ***************************/
2364 DefaultStatement::DefaultStatement(Loc loc
, Statement
*s
)
2367 this->statement
= s
;
2373 Statement
*DefaultStatement::syntaxCopy()
2375 DefaultStatement
*s
= new DefaultStatement(loc
, statement
->syntaxCopy());
2379 Statement
*DefaultStatement::semantic(Scope
*sc
)
2383 if (sc
->sw
->sdefault
)
2385 error("switch statement already has a default");
2387 sc
->sw
->sdefault
= this;
2390 error("default not in switch statement");
2391 statement
= statement
->semantic(sc
);
2395 int DefaultStatement::usesEH()
2397 return statement
->usesEH();
2400 int DefaultStatement::fallOffEnd()
2402 return statement
->fallOffEnd();
2405 int DefaultStatement::comeFrom()
2410 void DefaultStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2412 buf
->writestring("default:\n");
2413 statement
->toCBuffer(buf
, hgs
);
2416 /******************************** GotoDefaultStatement ***************************/
2418 GotoDefaultStatement::GotoDefaultStatement(Loc loc
)
2424 Statement
*GotoDefaultStatement::syntaxCopy()
2426 GotoDefaultStatement
*s
= new GotoDefaultStatement(loc
);
2430 Statement
*GotoDefaultStatement::semantic(Scope
*sc
)
2434 error("goto default not in switch statement");
2438 int GotoDefaultStatement::fallOffEnd()
2443 void GotoDefaultStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2445 buf
->writestring("goto default;\n");
2448 /******************************** GotoCaseStatement ***************************/
2450 GotoCaseStatement::GotoCaseStatement(Loc loc
, Expression
*exp
)
2457 Statement
*GotoCaseStatement::syntaxCopy()
2459 Expression
*e
= exp
? exp
->syntaxCopy() : NULL
;
2460 GotoCaseStatement
*s
= new GotoCaseStatement(loc
, e
);
2464 Statement
*GotoCaseStatement::semantic(Scope
*sc
)
2467 exp
= exp
->semantic(sc
);
2470 error("goto case not in switch statement");
2473 sc
->sw
->gotoCases
.push(this);
2476 exp
= exp
->implicitCastTo(sc
, sc
->sw
->condition
->type
);
2477 exp
= exp
->optimize(WANTvalue
);
2483 int GotoCaseStatement::fallOffEnd()
2488 void GotoCaseStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2490 buf
->writestring("goto case");
2492 { buf
->writebyte(' ');
2493 exp
->toCBuffer(buf
, hgs
);
2495 buf
->writebyte(';');
2499 /******************************** SwitchErrorStatement ***************************/
2501 SwitchErrorStatement::SwitchErrorStatement(Loc loc
)
2506 int SwitchErrorStatement::fallOffEnd()
2511 void SwitchErrorStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2513 buf
->writestring("SwitchErrorStatement::toCBuffer()");
2517 /******************************** ReturnStatement ***************************/
2519 ReturnStatement::ReturnStatement(Loc loc
, Expression
*exp
)
2525 Statement
*ReturnStatement::syntaxCopy()
2527 Expression
*e
= NULL
;
2529 e
= exp
->syntaxCopy();
2530 ReturnStatement
*s
= new ReturnStatement(loc
, e
);
2534 Statement
*ReturnStatement::semantic(Scope
*sc
)
2536 //printf("ReturnStatement::semantic() %s\n", toChars());
2538 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
2544 // Find scope of function foreach is in
2545 for (; 1; scx
= scx
->enclosing
)
2548 if (scx
->func
!= fd
)
2549 { fd
= scx
->func
; // fd is now function enclosing foreach
2555 Type
*tret
= fd
->type
->nextOf();
2557 tret
= fd
->tintro
->nextOf();
2561 tbret
= tret
->toBasetype();
2563 // main() returns 0, even if it returns void
2564 if (!exp
&& (!tbret
|| tbret
->ty
== Tvoid
) && fd
->isMain())
2566 exp
= new IntegerExp(0);
2569 if (sc
->incontract
|| scx
->incontract
)
2570 error("return statements cannot be in contracts");
2571 if (sc
->tf
|| scx
->tf
)
2572 error("return statements cannot be in finally, scope(exit) or scope(success) bodies");
2574 if (fd
->isCtorDeclaration())
2576 // Constructors implicitly do:
2578 if (exp
&& exp
->op
!= TOKthis
)
2579 error("cannot return expression from constructor");
2580 exp
= new ThisExp(0);
2588 fd
->hasReturnExp
|= 1;
2590 exp
= exp
->semantic(sc
);
2591 exp
= resolveProperties(sc
, exp
);
2592 exp
= exp
->optimize(WANTvalue
);
2594 if (fd
->nrvo_can
&& exp
->op
== TOKvar
)
2595 { VarExp
*ve
= (VarExp
*)exp
;
2596 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
2598 if (!v
|| v
->isOut() || v
->isRef())
2600 else if (fd
->nrvo_var
== NULL
)
2601 { if (!v
->isDataseg() && !v
->isParameter() && v
->toParent2() == fd
)
2606 else if (fd
->nrvo_var
!= v
)
2612 if (fd
->returnLabel
&& tbret
->ty
!= Tvoid
)
2615 else if (fd
->inferRetType
)
2617 if (fd
->type
->nextOf())
2619 if (!exp
->type
->equals(fd
->type
->nextOf()))
2620 error("mismatched function return type inference of %s and %s",
2621 exp
->type
->toChars(), fd
->type
->nextOf()->toChars());
2625 fd
->type
->next
= exp
->type
;
2626 fd
->type
= fd
->type
->semantic(loc
, sc
);
2628 { tret
= fd
->type
->nextOf();
2629 tbret
= tret
->toBasetype();
2633 else if (tbret
->ty
!= Tvoid
)
2635 exp
= exp
->implicitCastTo(sc
, tret
);
2638 else if (fd
->inferRetType
)
2640 if (fd
->type
->nextOf())
2642 if (fd
->type
->nextOf()->ty
!= Tvoid
)
2643 error("mismatched function return type inference of void and %s",
2644 fd
->type
->nextOf()->toChars());
2648 fd
->type
->next
= Type::tvoid
;
2649 fd
->type
= fd
->type
->semantic(loc
, sc
);
2651 { tret
= Type::tvoid
;
2656 else if (tbret
->ty
!= Tvoid
) // if non-void return
2657 error("return expression expected");
2663 if (exp
&& !implicit0
)
2665 exp
= exp
->implicitCastTo(sc
, tret
);
2667 if (!exp
|| exp
->op
== TOKint64
|| exp
->op
== TOKfloat64
||
2668 exp
->op
== TOKimaginary80
|| exp
->op
== TOKcomplex80
||
2669 exp
->op
== TOKthis
|| exp
->op
== TOKsuper
|| exp
->op
== TOKnull
||
2670 exp
->op
== TOKstring
)
2672 sc
->fes
->cases
.push(this);
2673 s
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
2675 else if (fd
->type
->nextOf()->toBasetype() == Type::tvoid
)
2680 s
= new ReturnStatement(0, NULL
);
2681 sc
->fes
->cases
.push(s
);
2683 // Construct: { exp; return cases.dim + 1; }
2684 s1
= new ExpStatement(loc
, exp
);
2685 s2
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
2686 s
= new CompoundStatement(loc
, s1
, s2
);
2694 // Construct: return vresult;
2696 { VarDeclaration
*v
;
2698 v
= new VarDeclaration(loc
, tret
, Id::result
, NULL
);
2701 if (!scx
->insert(v
))
2707 v
= new VarExp(0, fd
->vresult
);
2708 s
= new ReturnStatement(0, v
);
2709 sc
->fes
->cases
.push(s
);
2711 // Construct: { vresult = exp; return cases.dim + 1; }
2712 v
= new VarExp(0, fd
->vresult
);
2713 exp
= new AssignExp(loc
, v
, exp
);
2714 exp
= exp
->semantic(sc
);
2715 s1
= new ExpStatement(loc
, exp
);
2716 s2
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
2717 s
= new CompoundStatement(loc
, s1
, s2
);
2724 if (fd
->returnLabel
&& tbret
->ty
!= Tvoid
)
2726 assert(fd
->vresult
);
2727 VarExp
*v
= new VarExp(0, fd
->vresult
);
2729 exp
= new AssignExp(loc
, v
, exp
);
2730 exp
= exp
->semantic(sc
);
2737 /* BUG: need to issue an error on:
2744 if (sc
->callSuper
& CSXany_ctor
&&
2745 !(sc
->callSuper
& (CSXthis_ctor
| CSXsuper_ctor
)))
2746 error("return without calling constructor");
2748 sc
->callSuper
|= CSXreturn
;
2750 // See if all returns are instead to be replaced with a goto returnLabel;
2751 if (fd
->returnLabel
)
2753 GotoStatement
*gs
= new GotoStatement(loc
, Id::returnLabel
);
2755 gs
->label
= fd
->returnLabel
;
2759 s
= new ExpStatement(0, exp
);
2760 return new CompoundStatement(loc
, s
, gs
);
2765 if (exp
&& tbret
->ty
== Tvoid
&& !fd
->isMain())
2768 s
= new ExpStatement(loc
, exp
);
2771 return new CompoundStatement(loc
, s
, this);
2777 int ReturnStatement::fallOffEnd()
2782 void ReturnStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2784 buf
->printf("return ");
2786 exp
->toCBuffer(buf
, hgs
);
2787 buf
->writeByte(';');
2791 /******************************** BreakStatement ***************************/
2793 BreakStatement::BreakStatement(Loc loc
, Identifier
*ident
)
2796 this->ident
= ident
;
2799 Statement
*BreakStatement::syntaxCopy()
2801 BreakStatement
*s
= new BreakStatement(loc
, ident
);
2805 Statement
*BreakStatement::semantic(Scope
*sc
)
2808 // break Identifier;
2812 FuncDeclaration
*thisfunc
= sc
->func
;
2814 for (scx
= sc
; scx
; scx
= scx
->enclosing
)
2818 if (scx
->func
!= thisfunc
) // if in enclosing function
2820 if (sc
->fes
) // if this is the body of a foreach
2822 /* Post this statement to the fes, and replace
2823 * it with a return value that caller will put into
2824 * a switch. Caller will figure out where the break
2825 * label actually is.
2826 * Case numbers start with 2, not 0, as 0 is continue
2830 sc
->fes
->cases
.push(this);
2831 s
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
2834 break; // can't break to it
2838 if (ls
&& ls
->ident
== ident
)
2840 Statement
*s
= ls
->statement
;
2843 error("label '%s' has no break", ident
->toChars());
2844 if (ls
->tf
!= sc
->tf
)
2845 error("cannot break out of finally block");
2849 error("enclosing label '%s' for break not found", ident
->toChars());
2851 else if (!sc
->sbreak
)
2856 // Replace break; with return 1;
2857 s
= new ReturnStatement(0, new IntegerExp(1));
2860 error("break is not inside a loop or switch");
2865 int BreakStatement::fallOffEnd()
2870 void BreakStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2872 buf
->writestring("break");
2874 { buf
->writebyte(' ');
2875 buf
->writestring(ident
->toChars());
2877 buf
->writebyte(';');
2881 /******************************** ContinueStatement ***************************/
2883 ContinueStatement::ContinueStatement(Loc loc
, Identifier
*ident
)
2886 this->ident
= ident
;
2889 Statement
*ContinueStatement::syntaxCopy()
2891 ContinueStatement
*s
= new ContinueStatement(loc
, ident
);
2895 Statement
*ContinueStatement::semantic(Scope
*sc
)
2897 //printf("ContinueStatement::semantic() %p\n", this);
2901 FuncDeclaration
*thisfunc
= sc
->func
;
2903 for (scx
= sc
; scx
; scx
= scx
->enclosing
)
2907 if (scx
->func
!= thisfunc
) // if in enclosing function
2909 if (sc
->fes
) // if this is the body of a foreach
2911 for (; scx
; scx
= scx
->enclosing
)
2914 if (ls
&& ls
->ident
== ident
&& ls
->statement
== sc
->fes
)
2916 // Replace continue ident; with return 0;
2917 return new ReturnStatement(0, new IntegerExp(0));
2921 /* Post this statement to the fes, and replace
2922 * it with a return value that caller will put into
2923 * a switch. Caller will figure out where the break
2924 * label actually is.
2925 * Case numbers start with 2, not 0, as 0 is continue
2929 sc
->fes
->cases
.push(this);
2930 s
= new ReturnStatement(0, new IntegerExp(sc
->fes
->cases
.dim
+ 1));
2933 break; // can't continue to it
2937 if (ls
&& ls
->ident
== ident
)
2939 Statement
*s
= ls
->statement
;
2941 if (!s
->hasContinue())
2942 error("label '%s' has no continue", ident
->toChars());
2943 if (ls
->tf
!= sc
->tf
)
2944 error("cannot continue out of finally block");
2948 error("enclosing label '%s' for continue not found", ident
->toChars());
2950 else if (!sc
->scontinue
)
2955 // Replace continue; with return 0;
2956 s
= new ReturnStatement(0, new IntegerExp(0));
2959 error("continue is not inside a loop");
2964 int ContinueStatement::fallOffEnd()
2969 void ContinueStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
2971 buf
->writestring("continue");
2973 { buf
->writebyte(' ');
2974 buf
->writestring(ident
->toChars());
2976 buf
->writebyte(';');
2980 /******************************** SynchronizedStatement ***************************/
2982 SynchronizedStatement::SynchronizedStatement(Loc loc
, Expression
*exp
, Statement
*body
)
2990 SynchronizedStatement::SynchronizedStatement(Loc loc
, elem
*esync
, Statement
*body
)
2995 this->esync
= esync
;
2998 Statement
*SynchronizedStatement::syntaxCopy()
3000 Expression
*e
= exp
? exp
->syntaxCopy() : NULL
;
3001 SynchronizedStatement
*s
= new SynchronizedStatement(loc
, e
, body
? body
->syntaxCopy() : NULL
);
3005 Statement
*SynchronizedStatement::semantic(Scope
*sc
)
3008 { ClassDeclaration
*cd
;
3010 exp
= exp
->semantic(sc
);
3011 exp
= resolveProperties(sc
, exp
);
3012 cd
= exp
->type
->isClassHandle();
3014 error("can only synchronize on class objects, not '%s'", exp
->type
->toChars());
3015 else if (cd
->isInterfaceDeclaration())
3016 { Type
*t
= new TypeIdentifier(0, Id::Object
);
3018 t
= t
->semantic(0, sc
);
3019 exp
= new CastExp(loc
, exp
, t
);
3020 exp
= exp
->semantic(sc
);
3024 body
= body
->semantic(sc
);
3028 int SynchronizedStatement::hasBreak()
3030 return FALSE
; //TRUE;
3033 int SynchronizedStatement::hasContinue()
3035 return FALSE
; //TRUE;
3038 int SynchronizedStatement::usesEH()
3043 int SynchronizedStatement::fallOffEnd()
3045 return body
? body
->fallOffEnd() : TRUE
;
3048 void SynchronizedStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3050 buf
->writestring("synchronized");
3052 { buf
->writebyte('(');
3053 exp
->toCBuffer(buf
, hgs
);
3054 buf
->writebyte(')');
3058 buf
->writebyte(' ');
3059 body
->toCBuffer(buf
, hgs
);
3063 /******************************** WithStatement ***************************/
3065 WithStatement::WithStatement(Loc loc
, Expression
*exp
, Statement
*body
)
3073 Statement
*WithStatement::syntaxCopy()
3075 WithStatement
*s
= new WithStatement(loc
, exp
->syntaxCopy(), body
? body
->syntaxCopy() : NULL
);
3079 Statement
*WithStatement::semantic(Scope
*sc
)
3080 { ScopeDsymbol
*sym
;
3083 //printf("WithStatement::semantic()\n");
3084 exp
= exp
->semantic(sc
);
3085 exp
= resolveProperties(sc
, exp
);
3086 if (exp
->op
== TOKimport
)
3087 { ScopeExp
*es
= (ScopeExp
*)exp
;
3091 else if (exp
->op
== TOKtype
)
3092 { TypeExp
*es
= (TypeExp
*)exp
;
3094 sym
= es
->type
->toDsymbol(sc
)->isScopeDsymbol();
3096 { error("%s has no members", es
->toChars());
3097 body
= body
->semantic(sc
);
3102 { Type
*t
= exp
->type
;
3105 t
= t
->toBasetype();
3106 if (t
->isClassHandle())
3108 init
= new ExpInitializer(loc
, exp
);
3109 wthis
= new VarDeclaration(loc
, exp
->type
, Id::withSym
, init
);
3110 wthis
->semantic(sc
);
3112 sym
= new WithScopeSymbol(this);
3113 sym
->parent
= sc
->scopesym
;
3115 else if (t
->ty
== Tstruct
)
3117 Expression
*e
= exp
->addressOf(sc
);
3118 init
= new ExpInitializer(loc
, e
);
3119 wthis
= new VarDeclaration(loc
, e
->type
, Id::withSym
, init
);
3120 wthis
->semantic(sc
);
3121 sym
= new WithScopeSymbol(this);
3122 sym
->parent
= sc
->scopesym
;
3125 { error("with expressions must be class objects, not '%s'", exp
->type
->toChars());
3132 body
= body
->semantic(sc
);
3139 void WithStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3141 buf
->writestring("with (");
3142 exp
->toCBuffer(buf
, hgs
);
3143 buf
->writestring(")\n");
3145 body
->toCBuffer(buf
, hgs
);
3148 int WithStatement::usesEH()
3150 return body
? body
->usesEH() : 0;
3153 int WithStatement::fallOffEnd()
3155 return body
? body
->fallOffEnd() : TRUE
;
3158 /******************************** TryCatchStatement ***************************/
3160 TryCatchStatement::TryCatchStatement(Loc loc
, Statement
*body
, Array
*catches
)
3164 this->catches
= catches
;
3167 Statement
*TryCatchStatement::syntaxCopy()
3169 Array
*a
= new Array();
3170 a
->setDim(catches
->dim
);
3171 for (int i
= 0; i
< a
->dim
; i
++)
3174 c
= (Catch
*)catches
->data
[i
];
3175 c
= c
->syntaxCopy();
3178 TryCatchStatement
*s
= new TryCatchStatement(loc
, body
->syntaxCopy(), a
);
3182 Statement
*TryCatchStatement::semantic(Scope
*sc
)
3184 body
= body
->semanticScope(sc
, NULL
/*this*/, NULL
);
3186 for (int i
= 0; i
< catches
->dim
; i
++)
3189 c
= (Catch
*)catches
->data
[i
];
3192 // Determine if current catch 'hides' any previous catches
3193 for (int j
= 0; j
< i
; j
++)
3194 { Catch
*cj
= (Catch
*)catches
->data
[j
];
3195 char *si
= c
->loc
.toChars();
3196 char *sj
= cj
->loc
.toChars();
3198 if (c
->type
->toBasetype()->implicitConvTo(cj
->type
->toBasetype()))
3199 error("catch at %s hides catch at %s", sj
, si
);
3205 int TryCatchStatement::hasBreak()
3207 return FALSE
; //TRUE;
3210 int TryCatchStatement::usesEH()
3215 int TryCatchStatement::fallOffEnd()
3220 result
= body
->fallOffEnd();
3221 for (int i
= 0; i
< catches
->dim
; i
++)
3224 c
= (Catch
*)catches
->data
[i
];
3226 result
|= c
->handler
->fallOffEnd();
3231 void TryCatchStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3233 buf
->writestring("try");
3236 body
->toCBuffer(buf
, hgs
);
3238 for (i
= 0; i
< catches
->dim
; i
++)
3240 Catch
*c
= (Catch
*)catches
->data
[i
];
3241 c
->toCBuffer(buf
, hgs
);
3245 /******************************** Catch ***************************/
3247 Catch::Catch(Loc loc
, Type
*t
, Identifier
*id
, Statement
*handler
)
3249 //printf("Catch(%s, loc = %s)\n", id->toChars(), loc.toChars());
3253 this->handler
= handler
;
3257 Catch
*Catch::syntaxCopy()
3259 Catch
*c
= new Catch(loc
,
3260 (type
? type
->syntaxCopy() : NULL
),
3262 (handler
? handler
->syntaxCopy() : NULL
));
3266 void Catch::semantic(Scope
*sc
)
3267 { ScopeDsymbol
*sym
;
3269 //printf("Catch::semantic(%s)\n", ident->toChars());
3274 /* This is because the _d_local_unwind() gets the stack munged
3275 * up on this. The workaround is to place any try-catches into
3276 * a separate function, and call that.
3277 * To fix, have the compiler automatically convert the finally
3278 * body into a nested function.
3280 error(loc
, "cannot put catch statement inside finally block");
3284 sym
= new ScopeDsymbol();
3285 sym
->parent
= sc
->scopesym
;
3289 type
= new TypeIdentifier(0, Id::Object
);
3290 type
= type
->semantic(loc
, sc
);
3291 if (!type
->toBasetype()->isClassHandle())
3292 error("can only catch class objects, not '%s'", type
->toChars());
3295 var
= new VarDeclaration(loc
, type
, ident
, NULL
);
3296 var
->parent
= sc
->parent
;
3299 handler
= handler
->semantic(sc
);
3304 void Catch::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3306 buf
->writestring("catch");
3308 { buf
->writebyte('(');
3309 type
->toCBuffer(buf
, ident
, hgs
);
3310 buf
->writebyte(')');
3313 buf
->writebyte('{');
3315 handler
->toCBuffer(buf
, hgs
);
3316 buf
->writebyte('}');
3320 /****************************** TryFinallyStatement ***************************/
3322 TryFinallyStatement::TryFinallyStatement(Loc loc
, Statement
*body
, Statement
*finalbody
)
3326 this->finalbody
= finalbody
;
3329 Statement
*TryFinallyStatement::syntaxCopy()
3331 TryFinallyStatement
*s
= new TryFinallyStatement(loc
,
3332 body
->syntaxCopy(), finalbody
->syntaxCopy());
3336 Statement
*TryFinallyStatement::semantic(Scope
*sc
)
3338 //printf("TryFinallyStatement::semantic()\n");
3339 body
= body
->semantic(sc
);
3343 sc
->scontinue
= NULL
; // no break or continue out of finally block
3344 finalbody
= finalbody
->semantic(sc
);
3349 void TryFinallyStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3351 buf
->printf("try\n{\n");
3352 body
->toCBuffer(buf
, hgs
);
3353 buf
->printf("}\nfinally\n{\n");
3354 finalbody
->toCBuffer(buf
, hgs
);
3355 buf
->writeByte('}');
3359 int TryFinallyStatement::hasBreak()
3361 return FALSE
; //TRUE;
3364 int TryFinallyStatement::hasContinue()
3366 return FALSE
; //TRUE;
3369 int TryFinallyStatement::usesEH()
3374 int TryFinallyStatement::fallOffEnd()
3377 result
= body
? body
->fallOffEnd() : TRUE
;
3379 // result = finalbody->fallOffEnd();
3383 /****************************** OnScopeStatement ***************************/
3385 OnScopeStatement::OnScopeStatement(Loc loc
, TOK tok
, Statement
*statement
)
3389 this->statement
= statement
;
3392 Statement
*OnScopeStatement::syntaxCopy()
3394 OnScopeStatement
*s
= new OnScopeStatement(loc
,
3395 tok
, statement
->syntaxCopy());
3399 Statement
*OnScopeStatement::semantic(Scope
*sc
)
3401 /* semantic is called on results of scopeCode() */
3405 void OnScopeStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3407 buf
->writestring(Token::toChars(tok
));
3408 buf
->writebyte(' ');
3409 statement
->toCBuffer(buf
, hgs
);
3412 int OnScopeStatement::usesEH()
3414 return (tok
!= TOKon_scope_success
);
3417 void OnScopeStatement::scopeCode(Statement
**sentry
, Statement
**sexception
, Statement
**sfinally
)
3419 //printf("OnScopeStatement::scopeCode()\n");
3426 case TOKon_scope_exit
:
3427 *sfinally
= statement
;
3430 case TOKon_scope_failure
:
3431 *sexception
= statement
;
3434 case TOKon_scope_success
:
3437 * sentry: int x = 0;
3438 * sexception: x = 1;
3439 * sfinally: if (!x) statement;
3442 char name
[5 + sizeof(num
) * 3 + 1];
3443 sprintf(name
, "__osf%d", ++num
);
3444 Identifier
*id
= Lexer::idPool(name
);
3446 ExpInitializer
*ie
= new ExpInitializer(loc
, new IntegerExp(0));
3447 VarDeclaration
*v
= new VarDeclaration(loc
, Type::tint32
, id
, ie
);
3448 *sentry
= new DeclarationStatement(loc
, v
);
3450 Expression
*e
= new IntegerExp(1);
3451 e
= new AssignExp(0, new VarExp(0, v
), e
);
3452 *sexception
= new ExpStatement(0, e
);
3454 e
= new VarExp(0, v
);
3455 e
= new NotExp(0, e
);
3456 *sfinally
= new IfStatement(0, NULL
, e
, statement
, NULL
);
3466 /******************************** ThrowStatement ***************************/
3468 ThrowStatement::ThrowStatement(Loc loc
, Expression
*exp
)
3474 Statement
*ThrowStatement::syntaxCopy()
3476 ThrowStatement
*s
= new ThrowStatement(loc
, exp
->syntaxCopy());
3480 Statement
*ThrowStatement::semantic(Scope
*sc
)
3482 //printf("ThrowStatement::semantic()\n");
3484 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
3485 fd
->hasReturnExp
|= 2;
3488 error("Throw statements cannot be in contracts");
3489 exp
= exp
->semantic(sc
);
3490 exp
= resolveProperties(sc
, exp
);
3491 if (!exp
->type
->toBasetype()->isClassHandle())
3492 error("can only throw class objects, not type %s", exp
->type
->toChars());
3496 int ThrowStatement::fallOffEnd()
3501 void ThrowStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3503 buf
->printf("throw ");
3504 exp
->toCBuffer(buf
, hgs
);
3505 buf
->writeByte(';');
3509 /******************************** VolatileStatement **************************/
3511 VolatileStatement::VolatileStatement(Loc loc
, Statement
*statement
)
3514 this->statement
= statement
;
3517 Statement
*VolatileStatement::syntaxCopy()
3519 VolatileStatement
*s
= new VolatileStatement(loc
,
3520 statement
? statement
->syntaxCopy() : NULL
);
3524 Statement
*VolatileStatement::semantic(Scope
*sc
)
3526 statement
= statement
? statement
->semantic(sc
) : NULL
;
3530 Statements
*VolatileStatement::flatten(Scope
*sc
)
3534 a
= statement
? statement
->flatten(sc
) : NULL
;
3536 { for (int i
= 0; i
< a
->dim
; i
++)
3537 { Statement
*s
= (Statement
*)a
->data
[i
];
3539 s
= new VolatileStatement(loc
, s
);
3547 int VolatileStatement::fallOffEnd()
3549 return statement
? statement
->fallOffEnd() : TRUE
;
3552 void VolatileStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3554 buf
->writestring("volatile");
3556 { if (statement
->isScopeStatement())
3559 buf
->writebyte(' ');
3560 statement
->toCBuffer(buf
, hgs
);
3565 /******************************** GotoStatement ***************************/
3567 GotoStatement::GotoStatement(Loc loc
, Identifier
*ident
)
3570 this->ident
= ident
;
3575 Statement
*GotoStatement::syntaxCopy()
3577 GotoStatement
*s
= new GotoStatement(loc
, ident
);
3581 Statement
*GotoStatement::semantic(Scope
*sc
)
3582 { FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
3584 //printf("GotoStatement::semantic()\n");
3586 label
= fd
->searchLabel(ident
);
3587 if (!label
->statement
&& sc
->fes
)
3589 /* Either the goto label is forward referenced or it
3590 * is in the function that the enclosing foreach is in.
3591 * Can't know yet, so wrap the goto in a compound statement
3592 * so we can patch it later, and add it to a 'look at this later'
3595 Statements
*a
= new Statements();
3599 s
= new CompoundStatement(loc
, a
);
3600 sc
->fes
->gotos
.push(s
); // 'look at this later' list
3603 if (label
->statement
&& label
->statement
->tf
!= sc
->tf
)
3604 error("cannot goto in or out of finally block");
3608 int GotoStatement::fallOffEnd()
3613 void GotoStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3615 buf
->writestring("goto ");
3616 buf
->writestring(ident
->toChars());
3617 buf
->writebyte(';');
3621 /******************************** LabelStatement ***************************/
3623 LabelStatement::LabelStatement(Loc loc
, Identifier
*ident
, Statement
*statement
)
3626 this->ident
= ident
;
3627 this->statement
= statement
;
3629 this->lblock
= NULL
;
3630 this->isReturnLabel
= 0;
3633 Statement
*LabelStatement::syntaxCopy()
3635 LabelStatement
*s
= new LabelStatement(loc
, ident
, statement
->syntaxCopy());
3639 Statement
*LabelStatement::semantic(Scope
*sc
)
3641 FuncDeclaration
*fd
= sc
->parent
->isFuncDeclaration();
3643 //printf("LabelStatement::semantic()\n");
3644 ls
= fd
->searchLabel(ident
);
3646 error("Label '%s' already defined", ls
->toChars());
3648 ls
->statement
= this;
3651 sc
->scopesym
= sc
->enclosing
->scopesym
;
3652 sc
->callSuper
|= CSXlabel
;
3655 statement
= statement
->semantic(sc
);
3660 Statements
*LabelStatement::flatten(Scope
*sc
)
3662 Statements
*a
= NULL
;
3666 a
= statement
->flatten(sc
);
3671 a
->push(new ExpStatement(loc
, NULL
));
3673 Statement
*s
= (Statement
*)a
->data
[0];
3675 s
= new LabelStatement(loc
, ident
, s
);
3684 int LabelStatement::usesEH()
3686 return statement
? statement
->usesEH() : FALSE
;
3689 int LabelStatement::fallOffEnd()
3691 return statement
? statement
->fallOffEnd() : TRUE
;
3694 int LabelStatement::comeFrom()
3696 //printf("LabelStatement::comeFrom()\n");
3700 void LabelStatement::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
3702 buf
->writestring(ident
->toChars());
3703 buf
->writebyte(':');
3706 statement
->toCBuffer(buf
, hgs
);
3710 /******************************** LabelDsymbol ***************************/
3712 LabelDsymbol::LabelDsymbol(Identifier
*ident
)
3721 LabelDsymbol
*LabelDsymbol::isLabel() // is this a LabelDsymbol()?