Fixed semi-colon parsing in C-style for loops
[delight/core.git] / dmd / statement.c
blob77ca2e8730030350631b3e220f161737dc35a8a2
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2007 by Digital Mars
4 // All Rights Reserved
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
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <assert.h>
21 #include "mem.h"
23 #include "statement.h"
24 #include "expression.h"
25 #include "cond.h"
26 #include "init.h"
27 #include "staticassert.h"
28 #include "mtype.h"
29 #include "scope.h"
30 #include "declaration.h"
31 #include "aggregate.h"
32 #include "id.h"
33 #include "hdrgen.h"
34 #include "parse.h"
36 /******************************** Statement ***************************/
38 Statement::Statement(Loc loc)
39 : loc(loc)
41 #ifdef _DH
42 // If this is an in{} contract scope statement (skip for determining
43 // inlineStatus of a function body for header content)
44 incontract = 0;
45 #endif
48 Statement *Statement::syntaxCopy()
50 assert(0);
51 return NULL;
54 void Statement::print()
56 fprintf(stdmsg, "%s\n", toChars());
57 fflush(stdmsg);
60 char *Statement::toChars()
61 { OutBuffer *buf;
62 HdrGenState hgs;
64 buf = new OutBuffer();
65 toCBuffer(buf, &hgs);
66 return buf->toChars();
69 void Statement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
71 buf->printf("Statement::toCBuffer()");
72 buf->writenl();
75 Statement *Statement::semantic(Scope *sc)
77 return this;
80 // Same as semantic(), but do create a new scope
82 Statement *Statement::semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue)
83 { Scope *scd;
84 Statement *s;
86 scd = sc->push();
87 if (sbreak)
88 scd->sbreak = sbreak;
89 if (scontinue)
90 scd->scontinue = scontinue;
91 s = semantic(scd);
92 scd->pop();
93 return s;
96 void Statement::error(const char *format, ...)
98 va_list ap;
99 va_start(ap, format);
100 ::verror(loc, format, ap);
101 va_end( ap );
104 int Statement::hasBreak()
106 //printf("Statement::hasBreak()\n");
107 return FALSE;
110 int Statement::hasContinue()
112 return FALSE;
115 // TRUE if statement uses exception handling
117 int Statement::usesEH()
119 return FALSE;
122 // TRUE if statement may fall off the end without a throw or return
124 int Statement::fallOffEnd()
126 return TRUE;
129 // TRUE if statement 'comes from' somewhere else, like a goto
131 int Statement::comeFrom()
133 //printf("Statement::comeFrom()\n");
134 return FALSE;
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
140 * a Statement.
141 * Output:
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");
150 //print();
151 *sentry = NULL;
152 *sexception = NULL;
153 *sfinally = NULL;
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)
164 return NULL;
168 /******************************** ExpStatement ***************************/
170 ExpStatement::ExpStatement(Loc loc, Expression *exp)
171 : Statement(loc)
173 this->exp = exp;
176 Statement *ExpStatement::syntaxCopy()
178 Expression *e = exp ? exp->syntaxCopy() : NULL;
179 ExpStatement *es = new ExpStatement(loc, e);
180 return es;
183 void ExpStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
185 if (exp)
186 exp->toCBuffer(buf, hgs);
187 buf->writeByte(';');
188 if (!hgs->FLinit.init)
189 buf->writenl();
192 Statement *ExpStatement::semantic(Scope *sc)
194 if (exp)
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);
203 return this;
206 int ExpStatement::fallOffEnd()
208 if (exp)
210 if (exp->op == TOKassert)
211 { AssertExp *a = (AssertExp *)exp;
213 if (a->e1->isBool(FALSE)) // if it's an assert(0)
214 return FALSE;
216 else if (exp->op == TOKhalt)
217 return FALSE;
219 return TRUE;
222 /******************************** CompileStatement ***************************/
224 CompileStatement::CompileStatement(Loc loc, Expression *exp)
225 : Statement(loc)
227 this->exp = exp;
230 Statement *CompileStatement::syntaxCopy()
232 Expression *e = exp->syntaxCopy();
233 CompileStatement *es = new CompileStatement(loc, e);
234 return es;
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)
243 buf->writenl();
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());
254 return this;
256 StringExp *se = (StringExp *)exp;
257 se = se->toUTF8(sc);
258 Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
259 p.loc = loc;
260 p.nextToken();
262 Statements *statements = new Statements();
263 while (p.token.value != TOKeof)
265 Statement *s = p.parseStatement(PSsemi | PScurlyscope);
266 statements->push(s);
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());
289 return ds;
292 void DeclarationStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally)
294 //printf("DeclarationStatement::scopeCode()\n");
295 //print();
297 *sentry = NULL;
298 *sexception = NULL;
299 *sfinally = NULL;
301 if (exp)
303 if (exp->op == TOKdeclaration)
305 DeclarationExp *de = (DeclarationExp *)(exp);
306 VarDeclaration *v = de->declaration->isVarDeclaration();
307 if (v)
308 { Expression *e;
310 e = v->callAutoDtor();
311 if (e)
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));
339 } else {
340 // For everything else, call a getter in the _externals module
341 Expression *getter = new DotIdExp(loc, externals, arg->ident);
342 args->push(getter);
346 return args;
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++) {
360 Dsymbol *s;
362 s = (Dsymbol *)mainClass->members->data[i];
364 CtorDeclaration *thisCtor = s->isCtorDeclaration();
365 if (thisCtor) {
366 if (ctor) {
367 error("Multiple constructors for Main class!");
368 return NULL;
369 } else {
370 ctor = thisCtor;
374 FuncDeclaration *thisMethod = s->isFuncDeclaration();
375 if (thisMethod && thisMethod->ident == Id::main) {
376 if (mainDecl) {
377 error("Multiple main methods for Main class!");
378 return NULL;
379 } else {
380 mainDecl = thisMethod;
385 if (mainDecl == NULL) {
386 error("No main method in Main class!");
387 return NULL;
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,
414 new DotIdExp(loc,
415 new IdentifierExp(loc, Id::externals),
416 Id::SystemExit),
417 new IdentifierExp(loc, Id::result)));
418 Catch *c = new Catch(loc, new TypeIdentifier(loc, Id::SystemExit), Id::result, handler);
419 catches->push(c);
420 Statement *body = new TryCatchStatement(loc, runMain, catches);
421 return body->semantic(sc);
424 /******************************** CompoundStatement ***************************/
426 CompoundStatement::CompoundStatement(Loc loc, Statements *s)
427 : Statement(loc)
429 statements = s;
432 CompoundStatement::CompoundStatement(Loc loc, Statement *s1, Statement *s2)
433 : Statement(loc)
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];
447 if (s)
448 s = s->syntaxCopy();
449 a->data[i] = s;
451 CompoundStatement *cs = new CompoundStatement(loc, a);
452 return cs;
456 Statement *CompoundStatement::semantic(Scope *sc)
457 { Statement *s;
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];
464 if (s)
465 { Statements *a = s->flatten(sc);
467 if (a)
469 statements->remove(i);
470 statements->insert(i, a);
471 continue;
473 s = s->semantic(sc);
474 statements->data[i] = s;
475 if (s)
477 Statement *sentry;
478 Statement *sexception;
479 Statement *sfinally;
481 s->scopeCode(&sentry, &sexception, &sfinally);
482 if (sentry)
484 sentry = sentry->semantic(sc);
485 statements->data[i] = sentry;
487 if (sexception)
489 if (i + 1 == statements->dim && !sfinally)
491 #if 1
492 sexception = sexception->semantic(sc);
493 #else
494 statements->push(sexception);
495 if (sfinally)
496 // Assume sexception does not throw
497 statements->push(sfinally);
498 #endif
500 else
502 /* Rewrite:
503 * s; s1; s2;
504 * As:
505 * s;
506 * try { s1; s2; }
507 * catch (Object __o)
508 * { sexception; throw __o; }
510 Statement *body;
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);
520 static int num;
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);
530 catches->push(ctch);
531 s = new TryCatchStatement(0, body, catches);
533 if (sfinally)
534 s = new TryFinallyStatement(0, s, sfinally);
535 s = s->semantic(sc);
536 statements->setDim(i + 1);
537 statements->push(s);
538 break;
541 else if (sfinally)
543 if (0 && i + 1 == statements->dim)
545 statements->push(sfinally);
547 else
549 /* Rewrite:
550 * s; s1; s2;
551 * As:
552 * s; try { s1; s2; } finally { sfinally; }
554 Statement *body;
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);
563 s = s->semantic(sc);
564 statements->setDim(i + 1);
565 statements->push(s);
566 break;
571 i++;
573 if (statements->dim == 1)
574 return s;
575 return this;
578 Statements *CompoundStatement::flatten(Scope *sc)
580 return statements;
583 ReturnStatement *CompoundStatement::isReturnStatement()
584 { int i;
585 ReturnStatement *rs = NULL;
587 for (i = 0; i < statements->dim; i++)
588 { Statement *s;
590 s = (Statement *) statements->data[i];
591 if (s)
593 rs = s->isReturnStatement();
594 if (rs)
595 break;
598 return rs;
601 void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
602 { int i;
604 for (i = 0; i < statements->dim; i++)
605 { Statement *s;
607 s = (Statement *) statements->data[i];
608 if (s)
609 s->toCBuffer(buf, hgs);
613 int CompoundStatement::usesEH()
615 for (int i = 0; i < statements->dim; i++)
616 { Statement *s;
618 s = (Statement *) statements->data[i];
619 if (s && s->usesEH())
620 return TRUE;
622 return FALSE;
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];
632 if (!s)
633 continue;
635 if (!falloff && global.params.warnings && !s->comeFrom())
637 fprintf(stdmsg, "warning - ");
638 s->error("statement is not reachable");
640 falloff = s->fallOffEnd();
642 return falloff;
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];
652 if (!s)
653 continue;
655 comefrom |= s->comeFrom();
657 return comefrom;
661 /**************************** UnrolledLoopStatement ***************************/
663 UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s)
664 : Statement(loc)
666 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];
675 if (s)
676 s = s->syntaxCopy();
677 a->data[i] = s;
679 UnrolledLoopStatement *cs = new UnrolledLoopStatement(loc, a);
680 return cs;
684 Statement *UnrolledLoopStatement::semantic(Scope *sc)
686 //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc);
688 sc->noctor++;
689 Scope *scd = sc->push();
690 scd->sbreak = this;
691 scd->scontinue = this;
693 for (size_t i = 0; i < statements->dim; i++)
695 Statement *s = (Statement *) statements->data[i];
696 if (s)
698 s = s->semantic(scd);
699 statements->data[i] = s;
703 scd->pop();
704 sc->noctor--;
705 return this;
708 void UnrolledLoopStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
710 buf->writestring("unrolled {");
711 buf->writenl();
713 for (size_t i = 0; i < statements->dim; i++)
714 { Statement *s;
716 s = (Statement *) statements->data[i];
717 if (s)
718 s->toCBuffer(buf, hgs);
721 buf->writeByte('}');
722 buf->writenl();
725 int UnrolledLoopStatement::hasBreak()
727 return TRUE;
730 int UnrolledLoopStatement::hasContinue()
732 return TRUE;
735 int UnrolledLoopStatement::usesEH()
737 for (size_t i = 0; i < statements->dim; i++)
738 { Statement *s;
740 s = (Statement *) statements->data[i];
741 if (s && s->usesEH())
742 return TRUE;
744 return FALSE;
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];
753 if (s)
754 s->fallOffEnd();
756 return TRUE;
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];
767 if (!s)
768 continue;
770 comefrom |= s->comeFrom();
772 return comefrom;
776 /******************************** ScopeStatement ***************************/
778 ScopeStatement::ScopeStatement(Loc loc, Statement *s)
779 : Statement(loc)
781 this->statement = s;
784 Statement *ScopeStatement::syntaxCopy()
786 Statement *s;
788 s = statement ? statement->syntaxCopy() : NULL;
789 s = new ScopeStatement(loc, s);
790 return s;
794 Statement *ScopeStatement::semantic(Scope *sc)
795 { ScopeDsymbol *sym;
797 //printf("ScopeStatement::semantic(sc = %p)\n", sc);
798 if (statement)
799 { Statements *a;
801 sym = new ScopeDsymbol();
802 sym->parent = sc->scopesym;
803 sc = sc->push(sym);
805 a = statement->flatten(sc);
806 if (a)
808 statement = new CompoundStatement(loc, a);
811 statement = statement->semantic(sc);
812 if (statement)
814 Statement *sentry;
815 Statement *sexception;
816 Statement *sfinally;
818 statement->scopeCode(&sentry, &sexception, &sfinally);
819 if (sfinally)
821 //printf("adding sfinally\n");
822 statement = new CompoundStatement(loc, statement, sfinally);
826 sc->pop();
828 return this;
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)
860 buf->writeByte('{');
861 buf->writenl();
863 if (statement)
864 statement->toCBuffer(buf, hgs);
866 buf->writeByte('}');
867 buf->writenl();
870 /******************************** WhileStatement ***************************/
872 WhileStatement::WhileStatement(Loc loc, Expression *c, Statement *b)
873 : Statement(loc)
875 condition = c;
876 body = b;
879 Statement *WhileStatement::syntaxCopy()
881 WhileStatement *s = new WhileStatement(loc, condition->syntaxCopy(), body ? body->syntaxCopy() : NULL);
882 return s;
886 Statement *WhileStatement::semantic(Scope *sc)
888 #if 0
889 if (condition->op == TOKmatch)
891 /* Rewrite while (condition) body as:
892 * if (condition)
893 * do
894 * body
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);
909 #endif
911 condition = condition->semantic(sc);
912 condition = resolveProperties(sc, condition);
913 condition = condition->optimize(WANTvalue);
914 condition = condition->checkToBoolean();
916 sc->noctor++;
918 Scope *scd = sc->push();
919 scd->sbreak = this;
920 scd->scontinue = this;
921 if (body)
922 body = body->semantic(scd);
923 scd->pop();
925 sc->noctor--;
927 return this;
930 int WhileStatement::hasBreak()
932 return TRUE;
935 int WhileStatement::hasContinue()
937 return TRUE;
940 int WhileStatement::usesEH()
942 return body ? body->usesEH() : 0;
945 int WhileStatement::fallOffEnd()
947 if (body)
948 body->fallOffEnd();
949 return TRUE;
952 int WhileStatement::comeFrom()
954 if (body)
955 return body->comeFrom();
956 return FALSE;
959 void WhileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
961 buf->writestring("while (");
962 condition->toCBuffer(buf, hgs);
963 buf->writebyte(')');
964 buf->writenl();
965 if (body)
966 body->toCBuffer(buf, hgs);
969 /******************************** DoStatement ***************************/
971 DoStatement::DoStatement(Loc loc, Statement *b, Expression *c)
972 : Statement(loc)
974 body = b;
975 condition = c;
978 Statement *DoStatement::syntaxCopy()
980 DoStatement *s = new DoStatement(loc, body ? body->syntaxCopy() : NULL, condition->syntaxCopy());
981 return s;
985 Statement *DoStatement::semantic(Scope *sc)
987 sc->noctor++;
988 if (body)
989 body = body->semanticScope(sc, this, this);
990 sc->noctor--;
991 condition = condition->semantic(sc);
992 condition = resolveProperties(sc, condition);
993 condition = condition->optimize(WANTvalue);
995 condition = condition->checkToBoolean();
997 return this;
1000 int DoStatement::hasBreak()
1002 return TRUE;
1005 int DoStatement::hasContinue()
1007 return TRUE;
1010 int DoStatement::usesEH()
1012 return body ? body->usesEH() : 0;
1015 int DoStatement::fallOffEnd()
1017 if (body)
1018 body->fallOffEnd();
1019 return TRUE;
1022 int DoStatement::comeFrom()
1024 if (body)
1025 return body->comeFrom();
1026 return FALSE;
1029 void DoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1031 buf->writestring("do");
1032 buf->writenl();
1033 if (body)
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)
1043 : Statement(loc)
1045 this->init = init;
1046 this->condition = condition;
1047 this->increment = increment;
1048 this->body = body;
1051 Statement *ForStatement::syntaxCopy()
1053 Statement *i = NULL;
1054 if (init)
1055 i = init->syntaxCopy();
1056 Expression *c = NULL;
1057 if (condition)
1058 c = condition->syntaxCopy();
1059 Expression *inc = NULL;
1060 if (increment)
1061 inc = increment->syntaxCopy();
1062 ForStatement *s = new ForStatement(loc, i, c, inc, body->syntaxCopy());
1063 return s;
1066 Statement *ForStatement::semantic(Scope *sc)
1068 ScopeDsymbol *sym = new ScopeDsymbol();
1069 sym->parent = sc->scopesym;
1070 sc = sc->push(sym);
1071 if (init)
1072 init = init->semantic(sc);
1073 if (!condition)
1074 // Use a default value
1075 condition = new IntegerExp(loc, 1, Type::tboolean);
1076 sc->noctor++;
1077 condition = condition->semantic(sc);
1078 condition = resolveProperties(sc, condition);
1079 condition = condition->optimize(WANTvalue);
1080 condition = condition->checkToBoolean();
1081 if (increment)
1082 increment = increment->semantic(sc);
1084 sc->sbreak = this;
1085 sc->scontinue = this;
1086 body = body->semantic(sc);
1087 sc->noctor--;
1089 sc->pop();
1090 return this;
1093 void ForStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally)
1095 //printf("ForStatement::scopeCode()\n");
1096 //print();
1097 if (init)
1098 init->scopeCode(sentry, sexception, sfinally);
1099 else
1100 Statement::scopeCode(sentry, sexception, sfinally);
1103 int ForStatement::hasBreak()
1105 //printf("ForStatement::hasBreak()\n");
1106 return TRUE;
1109 int ForStatement::hasContinue()
1111 return TRUE;
1114 int ForStatement::usesEH()
1116 return (init && init->usesEH()) || body->usesEH();
1119 int ForStatement::fallOffEnd()
1121 if (body)
1122 body->fallOffEnd();
1123 return TRUE;
1126 int ForStatement::comeFrom()
1128 //printf("ForStatement::comeFrom()\n");
1129 if (body)
1130 { int result = body->comeFrom();
1131 //printf("result = %d\n", result);
1132 return result;
1134 return FALSE;
1137 void ForStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1139 buf->writestring("for (");
1140 if (init)
1142 hgs->FLinit.init++;
1143 hgs->FLinit.decl = 0;
1144 init->toCBuffer(buf, hgs);
1145 if (hgs->FLinit.decl > 0)
1146 buf->writebyte(';');
1147 hgs->FLinit.decl = 0;
1148 hgs->FLinit.init--;
1150 else
1151 buf->writebyte(';');
1152 if (condition)
1153 { buf->writebyte(' ');
1154 condition->toCBuffer(buf, hgs);
1156 buf->writebyte(';');
1157 if (increment)
1158 { buf->writebyte(' ');
1159 increment->toCBuffer(buf, hgs);
1161 buf->writebyte(')');
1162 buf->writenl();
1163 buf->writebyte('{');
1164 buf->writenl();
1165 body->toCBuffer(buf, hgs);
1166 buf->writebyte('}');
1167 buf->writenl();
1170 /******************************** ForeachStatement ***************************/
1172 ForeachStatement::ForeachStatement(Loc loc, enum TOK op, Arguments *arguments,
1173 Expression *aggr, Statement *body)
1174 : Statement(loc)
1176 this->op = op;
1177 this->arguments = arguments;
1178 this->aggr = aggr;
1179 this->body = body;
1181 this->key = NULL;
1182 this->value = NULL;
1184 this->func = NULL;
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);
1193 return s;
1196 Statement *ForeachStatement::semantic(Scope *sc)
1198 //printf("ForeachStatement::semantic() %p\n", this);
1199 ScopeDsymbol *sym;
1200 Statement *s = this;
1201 int dim = arguments->dim;
1202 int i;
1203 TypeAArray *taa = NULL;
1205 Type *tn = NULL;
1206 Type *tnv = NULL;
1208 func = sc->func;
1209 if (func->fes)
1210 func = func->fes->func;
1212 aggr = aggr->semantic(sc);
1213 aggr = resolveProperties(sc, aggr);
1214 if (!aggr->type)
1216 error("invalid foreach aggregate %s", aggr->toChars());
1217 return this;
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");
1228 return this;
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");
1238 return s;
1241 TypeTuple *tuple = (TypeTuple *)tab;
1242 Statements *statements = new Statements();
1243 //printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars());
1244 size_t n;
1245 TupleExp *te = NULL;
1246 if (aggr->op == TOKtuple) // expression tuple
1247 { te = (TupleExp *)aggr;
1248 n = te->exps->dim;
1250 else if (aggr->op == TOKtype) // type tuple
1252 n = Argument::dim(tuple->arguments);
1254 else
1255 assert(0);
1256 for (size_t j = 0; j < n; j++)
1257 { size_t k = (op == TOKforeach) ? j : n - 1 - j;
1258 Expression *e;
1259 Type *t;
1260 if (te)
1261 e = (Expression *)te->exps->data[k];
1262 else
1263 t = Argument::getNth(tuple->arguments, k)->type;
1264 Argument *arg = (Argument *)arguments->data[0];
1265 Statements *st = new Statements();
1267 if (dim == 2)
1268 { // Declare key
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
1286 // Declare value
1287 if (arg->storageClass & (STCout | STCref | STClazy))
1288 error("no storage class for value %s", arg->ident->toChars());
1289 Dsymbol *var;
1290 if (te)
1292 if (e->type->toBasetype()->ty == Tfunction &&
1293 e->op == TOKvar)
1294 { VarExp *ve = (VarExp *)e;
1295 var = new AliasDeclaration(loc, arg->ident, ve->var);
1297 else
1299 arg->type = e->type;
1300 Initializer *ie = new ExpInitializer(0, e);
1301 VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie);
1302 if (e->isConst())
1303 v->storage_class |= STCconst;
1304 #if V2
1305 else
1306 v->storage_class |= STCfinal;
1307 #endif
1308 var = v;
1311 else
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);
1326 return s;
1329 for (i = 0; i < dim; i++)
1330 { Argument *arg = (Argument *)arguments->data[i];
1331 if (!arg->type)
1333 error("cannot infer type for %s", arg->ident->toChars());
1334 return this;
1338 sym = new ScopeDsymbol();
1339 sym->parent = sc->scopesym;
1340 sc = sc->push(sym);
1342 sc->noctor++;
1344 switch (tab->ty)
1346 case Tarray:
1347 case Tsarray:
1348 if (dim < 1 || dim > 2)
1350 error("only one or two arguments for array foreach");
1351 break;
1354 /* Look for special case of parsing char types out of char type
1355 * array.
1357 tn = tab->nextOf()->toBasetype();
1358 if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
1359 { Argument *arg;
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");
1370 if (dim == 2)
1371 { arg = (Argument *)arguments->data[0];
1372 if (arg->storageClass & STCref)
1373 error("foreach: key cannot be ref");
1375 goto Lapply;
1379 for (i = 0; i < dim; i++)
1380 { // Declare args
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);
1387 #if 1
1388 DeclarationExp *de = new DeclarationExp(loc, var);
1389 de->semantic(sc);
1390 #else
1391 var->semantic(sc);
1392 if (!sc->insert(var))
1393 error("%s already defined", var->ident->toChars());
1394 #endif
1395 if (dim == 2 && i == 0)
1396 key = var;
1397 else
1398 value = var;
1401 sc->sbreak = this;
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());
1409 else
1410 error("foreach: %s is not an array of %s", tab->toChars(), value->type->toChars());
1413 if (key &&
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");
1425 break;
1427 case Taarray:
1428 taa = (TypeAArray *)tab;
1429 if (dim < 1 || dim > 2)
1431 error("only one or two arguments for associative array foreach");
1432 break;
1434 if (op == TOKforeach_reverse)
1436 error("no reverse iteration on associative arrays");
1438 goto Lapply;
1440 case Tclass:
1441 case Tstruct:
1442 case Tdelegate:
1443 Lapply:
1444 { FuncDeclaration *fdapply;
1445 Arguments *args;
1446 Expression *ec;
1447 Expression *e;
1448 FuncLiteralDeclaration *fld;
1449 Argument *a;
1450 Type *t;
1451 Expression *flde;
1452 Identifier *id;
1453 Type *tret;
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);
1462 v->noauto = 1;
1463 v->semantic(sc);
1464 if (!sc->insert(v))
1465 assert(0);
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)
1479 id = arg->ident;
1480 else
1481 { // Make a copy of the ref argument so it isn't
1482 // a reference.
1483 VarDeclaration *v;
1484 Initializer *ie;
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);
1496 args->push(a);
1498 t = new TypeFunction(args, Type::tint32, 0, LINKd);
1499 fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this);
1500 fld->fbody = body;
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
1511 cases.push(gs);
1512 s = new ReturnStatement(0, new IntegerExp(cases.dim + 1));
1513 cs->statements->data[0] = (void *)s;
1517 if (tab->ty == Taarray)
1519 // Check types
1520 Argument *arg = (Argument *)arguments->data[0];
1521 if (dim == 2)
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());
1532 /* Call:
1533 * _aaApply(aggr, keysize, flde)
1535 if (dim == 2)
1536 fdapply = FuncDeclaration::genCfunc(Type::tint32, "_aaApply2",
1537 Type::tvoid->arrayOf(), Type::tsize_t, flde->type); // flde->type is not generic
1538 else
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();
1543 exps->push(aggr);
1544 size_t keysize = taa->key->size();
1545 keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1);
1546 exps->push(new IntegerExp(0, keysize, Type::tsize_t));
1547 exps->push(flde);
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)
1553 /* Call:
1554 * _aApply(aggr, flde)
1556 static char fntab[9][3] =
1557 { "cc","cw","cd",
1558 "wc","cc","wd",
1559 "dc","dw","dd"
1561 char fdname[7+1+2+ sizeof(dim)*3 + 1];
1562 int flag;
1564 switch (tn->ty)
1566 case Tchar: flag = 0; break;
1567 case Twchar: flag = 3; break;
1568 case Tdchar: flag = 6; break;
1569 default: assert(0);
1571 switch (tnv->ty)
1573 case Tchar: flag += 0; break;
1574 case Twchar: flag += 1; break;
1575 case Tdchar: flag += 2; break;
1576 default: assert(0);
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());
1588 exps->push(aggr);
1589 exps->push(flde);
1590 e = new CallExp(loc, ec, exps);
1591 e->type = Type::tint32; // don't run semantic() on e
1593 else if (tab->ty == Tdelegate)
1595 /* Call:
1596 * aggr(flde)
1598 Expressions *exps = new Expressions();
1599 exps->push(flde);
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());
1605 else
1607 /* Call:
1608 * aggr.apply(flde)
1610 ec = new DotIdExp(loc, aggr,
1611 (op == TOKforeach_reverse) ? Id::applyReverse
1612 : Id::apply);
1613 Expressions *exps = new Expressions();
1614 exps->push(flde);
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());
1621 if (!cases.dim)
1622 // Easy case, a clean exit from the loop
1623 s = new ExpStatement(loc, e);
1624 else
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);
1632 a->push(s);
1634 // cases 2...
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);
1639 a->push(s);
1642 s = new CompoundStatement(loc, a);
1643 s = new SwitchStatement(loc, e, s);
1644 s = s->semantic(sc);
1646 break;
1649 default:
1650 error("foreach: %s is not an aggregate type", aggr->type->toChars());
1651 break;
1653 sc->noctor--;
1654 sc->pop();
1655 return s;
1658 int ForeachStatement::hasBreak()
1660 return TRUE;
1663 int ForeachStatement::hasContinue()
1665 return TRUE;
1668 int ForeachStatement::usesEH()
1670 return body->usesEH();
1673 int ForeachStatement::fallOffEnd()
1675 if (body)
1676 body->fallOffEnd();
1677 return TRUE;
1680 int ForeachStatement::comeFrom()
1682 if (body)
1683 return body->comeFrom();
1684 return FALSE;
1687 void ForeachStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1689 buf->writestring(Token::toChars(op));
1690 buf->writestring(" (");
1691 int i;
1692 for (int i = 0; i < arguments->dim; i++)
1694 Argument *a = (Argument *)arguments->data[i];
1695 if (i)
1696 buf->writestring(", ");
1697 if (a->storageClass & STCref)
1698 buf->writestring((global.params.Dversion == 1)
1699 ? (char*)"inout " : (char*)"ref ");
1700 if (a->type)
1701 a->type->toCBuffer(buf, a->ident, hgs);
1702 else
1703 buf->writestring(a->ident->toChars());
1705 buf->writestring("; ");
1706 aggr->toCBuffer(buf, hgs);
1707 buf->writebyte(')');
1708 buf->writenl();
1709 buf->writebyte('{');
1710 buf->writenl();
1711 if (body)
1712 body->toCBuffer(buf, hgs);
1713 buf->writebyte('}');
1714 buf->writenl();
1717 /******************************** IfStatement ***************************/
1719 IfStatement::IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody)
1720 : Statement(loc)
1722 this->arg = arg;
1723 this->condition = condition;
1724 this->ifbody = ifbody;
1725 this->elsebody = elsebody;
1726 this->match = NULL;
1729 Statement *IfStatement::syntaxCopy()
1731 Statement *i = NULL;
1732 if (ifbody)
1733 i = ifbody->syntaxCopy();
1735 Statement *e = NULL;
1736 if (elsebody)
1737 e = elsebody->syntaxCopy();
1739 Argument *a = arg ? arg->syntaxCopy() : NULL;
1740 IfStatement *s = new IfStatement(loc, a, condition->syntaxCopy(), i, e);
1741 return s;
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;
1757 unsigned cs1;
1759 Scope *scd;
1760 if (arg)
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);
1770 match->noauto = 1;
1771 match->semantic(scd);
1772 if (!scd->insert(match))
1773 assert(0);
1774 match->parent = sc->func;
1776 /* Generate:
1777 * (arg = condition)
1779 VarExp *v = new VarExp(0, match);
1780 condition = new AssignExp(loc, v, condition);
1781 condition = condition->semantic(scd);
1783 else
1784 scd = sc->push();
1785 ifbody = ifbody->semantic(scd);
1786 scd->pop();
1788 cs1 = sc->callSuper;
1789 sc->callSuper = cs0;
1790 if (elsebody)
1791 elsebody = elsebody->semanticScope(sc, NULL, NULL);
1792 sc->mergeCallSuper(loc, cs1);
1794 return this;
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())
1806 return TRUE;
1807 return FALSE;
1811 void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1813 buf->writestring("if (");
1814 if (arg)
1816 if (arg->type)
1817 arg->type->toCBuffer(buf, arg->ident, hgs);
1818 else
1819 buf->writestring(arg->ident->toChars());
1820 buf->writebyte(';');
1822 condition->toCBuffer(buf, hgs);
1823 buf->writebyte(')');
1824 buf->writenl();
1825 ifbody->toCBuffer(buf, hgs);
1826 if (elsebody)
1827 { buf->writestring("else");
1828 buf->writenl();
1829 elsebody->toCBuffer(buf, hgs);
1833 /******************************** ConditionalStatement ***************************/
1835 ConditionalStatement::ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody)
1836 : Statement(loc)
1838 this->condition = condition;
1839 this->ifbody = ifbody;
1840 this->elsebody = elsebody;
1843 Statement *ConditionalStatement::syntaxCopy()
1845 Statement *e = NULL;
1846 if (elsebody)
1847 e = elsebody->syntaxCopy();
1848 ConditionalStatement *s = new ConditionalStatement(loc,
1849 condition->syntaxCopy(), ifbody->syntaxCopy(), e);
1850 return s;
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);
1863 return ifbody;
1865 else
1867 if (elsebody)
1868 elsebody = elsebody->semantic(sc);
1869 return elsebody;
1873 Statements *ConditionalStatement::flatten(Scope *sc)
1875 Statement *s;
1877 if (condition->include(sc, NULL))
1878 s = ifbody;
1879 else
1880 s = elsebody;
1882 Statements *a = new Statements();
1883 a->push(s);
1884 return a;
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);
1895 buf->writenl();
1896 if (ifbody)
1897 ifbody->toCBuffer(buf, hgs);
1898 if (elsebody)
1900 buf->writestring("else");
1901 buf->writenl();
1902 elsebody->toCBuffer(buf, hgs);
1904 buf->writenl();
1908 /******************************** PragmaStatement ***************************/
1910 PragmaStatement::PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body)
1911 : Statement(loc)
1913 this->ident = ident;
1914 this->args = args;
1915 this->body = body;
1918 Statement *PragmaStatement::syntaxCopy()
1920 Statement *b = NULL;
1921 if (body)
1922 b = body->syntaxCopy();
1923 PragmaStatement *s = new PragmaStatement(loc,
1924 ident, Expression::arraySyntaxCopy(args), b);
1925 return s;
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)
1934 if (args)
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);
1947 else
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");
1957 else
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);
1971 name[se->len] = 0;
1972 printf("library %s\n", name);
1973 mem.free(name);
1977 else
1978 error("unrecognized pragma(%s)", ident->toChars());
1980 if (body)
1982 body = body->semantic(sc);
1984 return body;
1987 int PragmaStatement::usesEH()
1989 return body && body->usesEH();
1992 int PragmaStatement::fallOffEnd()
1994 if (body)
1995 return body->fallOffEnd();
1996 return TRUE;
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(')');
2009 if (body)
2011 buf->writenl();
2012 buf->writeByte('{');
2013 buf->writenl();
2015 body->toCBuffer(buf, hgs);
2017 buf->writeByte('}');
2018 buf->writenl();
2020 else
2022 buf->writeByte(';');
2023 buf->writenl();
2028 /******************************** LogStatement ***************************/
2030 LogStatement::LogStatement(Loc loc, int level, Expressions *args)
2031 : Statement(loc)
2033 this->level = level;
2034 this->args = args;
2037 Statement *LogStatement::semantic(Scope *sc)
2039 Expression *logger = new GetLoggerExp(loc);
2040 Type *type = NULL;
2042 for (Dsymbol *s = sc->parent; s; s = s->parent)
2044 ClassDeclaration *cd;
2045 StructDeclaration *sd;
2047 cd = s->isClassDeclaration();
2048 if (cd)
2050 type = cd->type;
2051 break;
2055 if (type == NULL) {
2056 // We're a top-level function. Generate log messages from the module
2057 args->shift(new StringExp(loc, strdup(sc->module->ident->string)));
2058 } else {
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)
2072 char *l;
2073 switch (level) {
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;
2078 default:
2079 error("Unknown log level %d", level);
2080 l = "log_UNKNOWN";
2082 buf->writestring(l);
2083 buf->writeByte('(');
2084 argsToCBuffer(buf, args, hgs);
2085 buf->writeByte(')');
2086 buf->writenl();
2089 /******************************** StaticAssertStatement ***************************/
2091 StaticAssertStatement::StaticAssertStatement(StaticAssert *sa)
2092 : Statement(sa->loc)
2094 this->sa = sa;
2097 Statement *StaticAssertStatement::syntaxCopy()
2099 StaticAssertStatement *s = new StaticAssertStatement((StaticAssert *)sa->syntaxCopy(NULL));
2100 return s;
2103 Statement *StaticAssertStatement::semantic(Scope *sc)
2105 sa->semantic2(sc);
2106 return NULL;
2109 void StaticAssertStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2111 sa->toCBuffer(buf, hgs);
2115 /******************************** SwitchStatement ***************************/
2117 SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b)
2118 : Statement(loc)
2120 condition = c;
2121 body = b;
2122 sdefault = NULL;
2123 cases = NULL;
2124 hasNoDefault = 0;
2127 Statement *SwitchStatement::syntaxCopy()
2129 SwitchStatement *s = new SwitchStatement(loc,
2130 condition->syntaxCopy(), body->syntaxCopy());
2131 return s;
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());
2148 else
2149 { condition = condition->integralPromotions(sc);
2150 condition->checkIntegral();
2152 condition = condition->optimize(WANTvalue);
2154 sc = sc->push();
2155 sc->sbreak = this;
2156 sc->sw = this;
2158 cases = new Array();
2159 sc->noctor++; // BUG: should use Scope::mergeCallSuper() for each case instead
2160 body = body->semantic(sc);
2161 sc->noctor--;
2163 // Resolve any goto case's with exp
2164 for (int i = 0; i < gotoCases.dim; i++)
2166 GotoCaseStatement *gcs = (GotoCaseStatement *)gotoCases.data[i];
2168 if (!gcs->exp)
2170 gcs->error("no case statement following goto case;");
2171 break;
2174 for (Scope *scx = sc; scx; scx = scx->enclosing)
2176 if (!scx->sw)
2177 continue;
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))
2184 gcs->cs = cs;
2185 goto Lfoundcase;
2189 gcs->error("case %s not found", gcs->exp->toChars());
2191 Lfoundcase:
2195 if (!sc->sw->sdefault)
2196 { hasNoDefault = 1;
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;
2206 Statement *s;
2208 if (global.params.useSwitchError)
2209 s = new SwitchErrorStatement(loc);
2210 else
2211 { Expression *e = new HaltExp(loc);
2212 s = new ExpStatement(loc, e);
2215 a->reserve(4);
2216 a->push(body);
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);
2221 body = cs;
2224 sc->pop();
2225 return this;
2228 int SwitchStatement::hasBreak()
2230 return TRUE;
2233 int SwitchStatement::usesEH()
2235 return body ? body->usesEH() : 0;
2238 int SwitchStatement::fallOffEnd()
2240 if (body)
2241 body->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(')');
2250 buf->writenl();
2251 if (body)
2253 if (!body->isScopeStatement())
2254 { buf->writebyte('{');
2255 buf->writenl();
2256 body->toCBuffer(buf, hgs);
2257 buf->writebyte('}');
2258 buf->writenl();
2260 else
2262 body->toCBuffer(buf, hgs);
2267 /******************************** CaseStatement ***************************/
2269 CaseStatement::CaseStatement(Loc loc, Expression *exp, Statement *s)
2270 : Statement(loc)
2272 this->exp = exp;
2273 this->statement = s;
2274 cblock = NULL;
2277 Statement *CaseStatement::syntaxCopy()
2279 CaseStatement *s = new CaseStatement(loc, exp->syntaxCopy(), statement->syntaxCopy());
2280 return s;
2283 Statement *CaseStatement::semantic(Scope *sc)
2284 { SwitchStatement *sw = sc->sw;
2286 //printf("CaseStatement::semantic() %s\n", toChars());
2287 exp = exp->semantic(sc);
2288 if (sw)
2289 { int i;
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());
2306 break;
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];
2317 if (!gcs->exp)
2319 gcs->cs = this;
2320 sw->gotoCases.remove(i); // remove from array
2324 else
2325 error("case not in switch statement");
2326 statement = statement->semantic(sc);
2327 return this;
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()
2350 return TRUE;
2353 void CaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2355 buf->writestring("case ");
2356 exp->toCBuffer(buf, hgs);
2357 buf->writebyte(':');
2358 buf->writenl();
2359 statement->toCBuffer(buf, hgs);
2362 /******************************** DefaultStatement ***************************/
2364 DefaultStatement::DefaultStatement(Loc loc, Statement *s)
2365 : Statement(loc)
2367 this->statement = s;
2368 #if IN_GCC
2369 cblock = NULL;
2370 #endif
2373 Statement *DefaultStatement::syntaxCopy()
2375 DefaultStatement *s = new DefaultStatement(loc, statement->syntaxCopy());
2376 return s;
2379 Statement *DefaultStatement::semantic(Scope *sc)
2381 if (sc->sw)
2383 if (sc->sw->sdefault)
2385 error("switch statement already has a default");
2387 sc->sw->sdefault = this;
2389 else
2390 error("default not in switch statement");
2391 statement = statement->semantic(sc);
2392 return this;
2395 int DefaultStatement::usesEH()
2397 return statement->usesEH();
2400 int DefaultStatement::fallOffEnd()
2402 return statement->fallOffEnd();
2405 int DefaultStatement::comeFrom()
2407 return TRUE;
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)
2419 : Statement(loc)
2421 sw = NULL;
2424 Statement *GotoDefaultStatement::syntaxCopy()
2426 GotoDefaultStatement *s = new GotoDefaultStatement(loc);
2427 return s;
2430 Statement *GotoDefaultStatement::semantic(Scope *sc)
2432 sw = sc->sw;
2433 if (!sw)
2434 error("goto default not in switch statement");
2435 return this;
2438 int GotoDefaultStatement::fallOffEnd()
2440 return FALSE;
2443 void GotoDefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2445 buf->writestring("goto default;\n");
2448 /******************************** GotoCaseStatement ***************************/
2450 GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp)
2451 : Statement(loc)
2453 cs = NULL;
2454 this->exp = exp;
2457 Statement *GotoCaseStatement::syntaxCopy()
2459 Expression *e = exp ? exp->syntaxCopy() : NULL;
2460 GotoCaseStatement *s = new GotoCaseStatement(loc, e);
2461 return s;
2464 Statement *GotoCaseStatement::semantic(Scope *sc)
2466 if (exp)
2467 exp = exp->semantic(sc);
2469 if (!sc->sw)
2470 error("goto case not in switch statement");
2471 else
2473 sc->sw->gotoCases.push(this);
2474 if (exp)
2476 exp = exp->implicitCastTo(sc, sc->sw->condition->type);
2477 exp = exp->optimize(WANTvalue);
2480 return this;
2483 int GotoCaseStatement::fallOffEnd()
2485 return FALSE;
2488 void GotoCaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2490 buf->writestring("goto case");
2491 if (exp)
2492 { buf->writebyte(' ');
2493 exp->toCBuffer(buf, hgs);
2495 buf->writebyte(';');
2496 buf->writenl();
2499 /******************************** SwitchErrorStatement ***************************/
2501 SwitchErrorStatement::SwitchErrorStatement(Loc loc)
2502 : Statement(loc)
2506 int SwitchErrorStatement::fallOffEnd()
2508 return FALSE;
2511 void SwitchErrorStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2513 buf->writestring("SwitchErrorStatement::toCBuffer()");
2514 buf->writenl();
2517 /******************************** ReturnStatement ***************************/
2519 ReturnStatement::ReturnStatement(Loc loc, Expression *exp)
2520 : Statement(loc)
2522 this->exp = exp;
2525 Statement *ReturnStatement::syntaxCopy()
2527 Expression *e = NULL;
2528 if (exp)
2529 e = exp->syntaxCopy();
2530 ReturnStatement *s = new ReturnStatement(loc, e);
2531 return s;
2534 Statement *ReturnStatement::semantic(Scope *sc)
2536 //printf("ReturnStatement::semantic() %s\n", toChars());
2538 FuncDeclaration *fd = sc->parent->isFuncDeclaration();
2539 Scope *scx = sc;
2540 int implicit0 = 0;
2542 if (sc->fes)
2544 // Find scope of function foreach is in
2545 for (; 1; scx = scx->enclosing)
2547 assert(scx);
2548 if (scx->func != fd)
2549 { fd = scx->func; // fd is now function enclosing foreach
2550 break;
2555 Type *tret = fd->type->nextOf();
2556 if (fd->tintro)
2557 tret = fd->tintro->nextOf();
2558 Type *tbret = NULL;
2560 if (tret)
2561 tbret = tret->toBasetype();
2563 // main() returns 0, even if it returns void
2564 if (!exp && (!tbret || tbret->ty == Tvoid) && fd->isMain())
2565 { implicit0 = 1;
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:
2577 // return this;
2578 if (exp && exp->op != TOKthis)
2579 error("cannot return expression from constructor");
2580 exp = new ThisExp(0);
2583 if (!exp)
2584 fd->nrvo_can = 0;
2586 if (exp)
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())
2599 fd->nrvo_can = 0;
2600 else if (fd->nrvo_var == NULL)
2601 { if (!v->isDataseg() && !v->isParameter() && v->toParent2() == fd)
2602 fd->nrvo_var = v;
2603 else
2604 fd->nrvo_can = 0;
2606 else if (fd->nrvo_var != v)
2607 fd->nrvo_can = 0;
2609 else
2610 fd->nrvo_can = 0;
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());
2623 else
2625 fd->type->next = exp->type;
2626 fd->type = fd->type->semantic(loc, sc);
2627 if (!fd->tintro)
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());
2646 else
2648 fd->type->next = Type::tvoid;
2649 fd->type = fd->type->semantic(loc, sc);
2650 if (!fd->tintro)
2651 { tret = Type::tvoid;
2652 tbret = tret;
2656 else if (tbret->ty != Tvoid) // if non-void return
2657 error("return expression expected");
2659 if (sc->fes)
2661 Statement *s;
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)
2677 Statement *s1;
2678 Statement *s2;
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);
2688 else
2690 VarExp *v;
2691 Statement *s1;
2692 Statement *s2;
2694 // Construct: return vresult;
2695 if (!fd->vresult)
2696 { VarDeclaration *v;
2698 v = new VarDeclaration(loc, tret, Id::result, NULL);
2699 v->noauto = 1;
2700 v->semantic(scx);
2701 if (!scx->insert(v))
2702 assert(0);
2703 v->parent = fd;
2704 fd->vresult = 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);
2719 return s;
2722 if (exp)
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);
2732 //exp->dump(0);
2733 //exp->print();
2734 exp->checkEscape();
2737 /* BUG: need to issue an error on:
2738 * this
2739 * { if (x) return;
2740 * super();
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;
2756 if (exp)
2757 { Statement *s;
2759 s = new ExpStatement(0, exp);
2760 return new CompoundStatement(loc, s, gs);
2762 return gs;
2765 if (exp && tbret->ty == Tvoid && !fd->isMain())
2766 { Statement *s;
2768 s = new ExpStatement(loc, exp);
2769 loc = 0;
2770 exp = NULL;
2771 return new CompoundStatement(loc, s, this);
2774 return this;
2777 int ReturnStatement::fallOffEnd()
2779 return FALSE;
2782 void ReturnStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2784 buf->printf("return ");
2785 if (exp)
2786 exp->toCBuffer(buf, hgs);
2787 buf->writeByte(';');
2788 buf->writenl();
2791 /******************************** BreakStatement ***************************/
2793 BreakStatement::BreakStatement(Loc loc, Identifier *ident)
2794 : Statement(loc)
2796 this->ident = ident;
2799 Statement *BreakStatement::syntaxCopy()
2801 BreakStatement *s = new BreakStatement(loc, ident);
2802 return s;
2805 Statement *BreakStatement::semantic(Scope *sc)
2807 // If:
2808 // break Identifier;
2809 if (ident)
2811 Scope *scx;
2812 FuncDeclaration *thisfunc = sc->func;
2814 for (scx = sc; scx; scx = scx->enclosing)
2816 LabelStatement *ls;
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
2827 * and 1 is break.
2829 Statement *s;
2830 sc->fes->cases.push(this);
2831 s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
2832 return s;
2834 break; // can't break to it
2837 ls = scx->slabel;
2838 if (ls && ls->ident == ident)
2840 Statement *s = ls->statement;
2842 if (!s->hasBreak())
2843 error("label '%s' has no break", ident->toChars());
2844 if (ls->tf != sc->tf)
2845 error("cannot break out of finally block");
2846 return this;
2849 error("enclosing label '%s' for break not found", ident->toChars());
2851 else if (!sc->sbreak)
2853 if (sc->fes)
2854 { Statement *s;
2856 // Replace break; with return 1;
2857 s = new ReturnStatement(0, new IntegerExp(1));
2858 return s;
2860 error("break is not inside a loop or switch");
2862 return this;
2865 int BreakStatement::fallOffEnd()
2867 return FALSE;
2870 void BreakStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2872 buf->writestring("break");
2873 if (ident)
2874 { buf->writebyte(' ');
2875 buf->writestring(ident->toChars());
2877 buf->writebyte(';');
2878 buf->writenl();
2881 /******************************** ContinueStatement ***************************/
2883 ContinueStatement::ContinueStatement(Loc loc, Identifier *ident)
2884 : Statement(loc)
2886 this->ident = ident;
2889 Statement *ContinueStatement::syntaxCopy()
2891 ContinueStatement *s = new ContinueStatement(loc, ident);
2892 return s;
2895 Statement *ContinueStatement::semantic(Scope *sc)
2897 //printf("ContinueStatement::semantic() %p\n", this);
2898 if (ident)
2900 Scope *scx;
2901 FuncDeclaration *thisfunc = sc->func;
2903 for (scx = sc; scx; scx = scx->enclosing)
2905 LabelStatement *ls;
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)
2913 ls = scx->slabel;
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
2926 * and 1 is break.
2928 Statement *s;
2929 sc->fes->cases.push(this);
2930 s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
2931 return s;
2933 break; // can't continue to it
2936 ls = scx->slabel;
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");
2945 return this;
2948 error("enclosing label '%s' for continue not found", ident->toChars());
2950 else if (!sc->scontinue)
2952 if (sc->fes)
2953 { Statement *s;
2955 // Replace continue; with return 0;
2956 s = new ReturnStatement(0, new IntegerExp(0));
2957 return s;
2959 error("continue is not inside a loop");
2961 return this;
2964 int ContinueStatement::fallOffEnd()
2966 return FALSE;
2969 void ContinueStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2971 buf->writestring("continue");
2972 if (ident)
2973 { buf->writebyte(' ');
2974 buf->writestring(ident->toChars());
2976 buf->writebyte(';');
2977 buf->writenl();
2980 /******************************** SynchronizedStatement ***************************/
2982 SynchronizedStatement::SynchronizedStatement(Loc loc, Expression *exp, Statement *body)
2983 : Statement(loc)
2985 this->exp = exp;
2986 this->body = body;
2987 this->esync = NULL;
2990 SynchronizedStatement::SynchronizedStatement(Loc loc, elem *esync, Statement *body)
2991 : Statement(loc)
2993 this->exp = NULL;
2994 this->body = 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);
3002 return s;
3005 Statement *SynchronizedStatement::semantic(Scope *sc)
3007 if (exp)
3008 { ClassDeclaration *cd;
3010 exp = exp->semantic(sc);
3011 exp = resolveProperties(sc, exp);
3012 cd = exp->type->isClassHandle();
3013 if (!cd)
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);
3023 if (body)
3024 body = body->semantic(sc);
3025 return this;
3028 int SynchronizedStatement::hasBreak()
3030 return FALSE; //TRUE;
3033 int SynchronizedStatement::hasContinue()
3035 return FALSE; //TRUE;
3038 int SynchronizedStatement::usesEH()
3040 return TRUE;
3043 int SynchronizedStatement::fallOffEnd()
3045 return body ? body->fallOffEnd() : TRUE;
3048 void SynchronizedStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3050 buf->writestring("synchronized");
3051 if (exp)
3052 { buf->writebyte('(');
3053 exp->toCBuffer(buf, hgs);
3054 buf->writebyte(')');
3056 if (body)
3058 buf->writebyte(' ');
3059 body->toCBuffer(buf, hgs);
3063 /******************************** WithStatement ***************************/
3065 WithStatement::WithStatement(Loc loc, Expression *exp, Statement *body)
3066 : Statement(loc)
3068 this->exp = exp;
3069 this->body = body;
3070 wthis = NULL;
3073 Statement *WithStatement::syntaxCopy()
3075 WithStatement *s = new WithStatement(loc, exp->syntaxCopy(), body ? body->syntaxCopy() : NULL);
3076 return s;
3079 Statement *WithStatement::semantic(Scope *sc)
3080 { ScopeDsymbol *sym;
3081 Initializer *init;
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;
3089 sym = es->sds;
3091 else if (exp->op == TOKtype)
3092 { TypeExp *es = (TypeExp *)exp;
3094 sym = es->type->toDsymbol(sc)->isScopeDsymbol();
3095 if (!sym)
3096 { error("%s has no members", es->toChars());
3097 body = body->semantic(sc);
3098 return this;
3101 else
3102 { Type *t = exp->type;
3104 assert(t);
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;
3124 else
3125 { error("with expressions must be class objects, not '%s'", exp->type->toChars());
3126 return NULL;
3129 sc = sc->push(sym);
3131 if (body)
3132 body = body->semantic(sc);
3134 sc->pop();
3136 return this;
3139 void WithStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3141 buf->writestring("with (");
3142 exp->toCBuffer(buf, hgs);
3143 buf->writestring(")\n");
3144 if (body)
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)
3161 : Statement(loc)
3163 this->body = body;
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++)
3172 { Catch *c;
3174 c = (Catch *)catches->data[i];
3175 c = c->syntaxCopy();
3176 a->data[i] = c;
3178 TryCatchStatement *s = new TryCatchStatement(loc, body->syntaxCopy(), a);
3179 return s;
3182 Statement *TryCatchStatement::semantic(Scope *sc)
3184 body = body->semanticScope(sc, NULL /*this*/, NULL);
3186 for (int i = 0; i < catches->dim; i++)
3187 { Catch *c;
3189 c = (Catch *)catches->data[i];
3190 c->semantic(sc);
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);
3202 return this;
3205 int TryCatchStatement::hasBreak()
3207 return FALSE; //TRUE;
3210 int TryCatchStatement::usesEH()
3212 return TRUE;
3215 int TryCatchStatement::fallOffEnd()
3217 int result = FALSE;
3219 if (body)
3220 result = body->fallOffEnd();
3221 for (int i = 0; i < catches->dim; i++)
3222 { Catch *c;
3224 c = (Catch *)catches->data[i];
3225 if (c->handler)
3226 result |= c->handler->fallOffEnd();
3228 return result;
3231 void TryCatchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3233 buf->writestring("try");
3234 buf->writenl();
3235 if (body)
3236 body->toCBuffer(buf, hgs);
3237 int i;
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());
3250 this->loc = loc;
3251 this->type = t;
3252 this->ident = id;
3253 this->handler = handler;
3254 var = NULL;
3257 Catch *Catch::syntaxCopy()
3259 Catch *c = new Catch(loc,
3260 (type ? type->syntaxCopy() : NULL),
3261 ident,
3262 (handler ? handler->syntaxCopy() : NULL));
3263 return c;
3266 void Catch::semantic(Scope *sc)
3267 { ScopeDsymbol *sym;
3269 //printf("Catch::semantic(%s)\n", ident->toChars());
3271 #ifndef IN_GCC
3272 if (sc->tf)
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");
3282 #endif
3284 sym = new ScopeDsymbol();
3285 sym->parent = sc->scopesym;
3286 sc = sc->push(sym);
3288 if (!type)
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());
3293 else if (ident)
3295 var = new VarDeclaration(loc, type, ident, NULL);
3296 var->parent = sc->parent;
3297 sc->insert(var);
3299 handler = handler->semantic(sc);
3301 sc->pop();
3304 void Catch::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3306 buf->writestring("catch");
3307 if (type)
3308 { buf->writebyte('(');
3309 type->toCBuffer(buf, ident, hgs);
3310 buf->writebyte(')');
3312 buf->writenl();
3313 buf->writebyte('{');
3314 buf->writenl();
3315 handler->toCBuffer(buf, hgs);
3316 buf->writebyte('}');
3317 buf->writenl();
3320 /****************************** TryFinallyStatement ***************************/
3322 TryFinallyStatement::TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody)
3323 : Statement(loc)
3325 this->body = body;
3326 this->finalbody = finalbody;
3329 Statement *TryFinallyStatement::syntaxCopy()
3331 TryFinallyStatement *s = new TryFinallyStatement(loc,
3332 body->syntaxCopy(), finalbody->syntaxCopy());
3333 return s;
3336 Statement *TryFinallyStatement::semantic(Scope *sc)
3338 //printf("TryFinallyStatement::semantic()\n");
3339 body = body->semantic(sc);
3340 sc = sc->push();
3341 sc->tf = this;
3342 sc->sbreak = NULL;
3343 sc->scontinue = NULL; // no break or continue out of finally block
3344 finalbody = finalbody->semantic(sc);
3345 sc->pop();
3346 return this;
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('}');
3356 buf->writenl();
3359 int TryFinallyStatement::hasBreak()
3361 return FALSE; //TRUE;
3364 int TryFinallyStatement::hasContinue()
3366 return FALSE; //TRUE;
3369 int TryFinallyStatement::usesEH()
3371 return TRUE;
3374 int TryFinallyStatement::fallOffEnd()
3375 { int result;
3377 result = body ? body->fallOffEnd() : TRUE;
3378 // if (finalbody)
3379 // result = finalbody->fallOffEnd();
3380 return result;
3383 /****************************** OnScopeStatement ***************************/
3385 OnScopeStatement::OnScopeStatement(Loc loc, TOK tok, Statement *statement)
3386 : Statement(loc)
3388 this->tok = tok;
3389 this->statement = statement;
3392 Statement *OnScopeStatement::syntaxCopy()
3394 OnScopeStatement *s = new OnScopeStatement(loc,
3395 tok, statement->syntaxCopy());
3396 return s;
3399 Statement *OnScopeStatement::semantic(Scope *sc)
3401 /* semantic is called on results of scopeCode() */
3402 return this;
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");
3420 //print();
3421 *sentry = NULL;
3422 *sexception = NULL;
3423 *sfinally = NULL;
3424 switch (tok)
3426 case TOKon_scope_exit:
3427 *sfinally = statement;
3428 break;
3430 case TOKon_scope_failure:
3431 *sexception = statement;
3432 break;
3434 case TOKon_scope_success:
3436 /* Create:
3437 * sentry: int x = 0;
3438 * sexception: x = 1;
3439 * sfinally: if (!x) statement;
3441 static int num;
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);
3458 break;
3461 default:
3462 assert(0);
3466 /******************************** ThrowStatement ***************************/
3468 ThrowStatement::ThrowStatement(Loc loc, Expression *exp)
3469 : Statement(loc)
3471 this->exp = exp;
3474 Statement *ThrowStatement::syntaxCopy()
3476 ThrowStatement *s = new ThrowStatement(loc, exp->syntaxCopy());
3477 return s;
3480 Statement *ThrowStatement::semantic(Scope *sc)
3482 //printf("ThrowStatement::semantic()\n");
3484 FuncDeclaration *fd = sc->parent->isFuncDeclaration();
3485 fd->hasReturnExp |= 2;
3487 if (sc->incontract)
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());
3493 return this;
3496 int ThrowStatement::fallOffEnd()
3498 return FALSE;
3501 void ThrowStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3503 buf->printf("throw ");
3504 exp->toCBuffer(buf, hgs);
3505 buf->writeByte(';');
3506 buf->writenl();
3509 /******************************** VolatileStatement **************************/
3511 VolatileStatement::VolatileStatement(Loc loc, Statement *statement)
3512 : Statement(loc)
3514 this->statement = statement;
3517 Statement *VolatileStatement::syntaxCopy()
3519 VolatileStatement *s = new VolatileStatement(loc,
3520 statement ? statement->syntaxCopy() : NULL);
3521 return s;
3524 Statement *VolatileStatement::semantic(Scope *sc)
3526 statement = statement ? statement->semantic(sc) : NULL;
3527 return this;
3530 Statements *VolatileStatement::flatten(Scope *sc)
3532 Statements *a;
3534 a = statement ? statement->flatten(sc) : NULL;
3535 if (a)
3536 { for (int i = 0; i < a->dim; i++)
3537 { Statement *s = (Statement *)a->data[i];
3539 s = new VolatileStatement(loc, s);
3540 a->data[i] = s;
3544 return a;
3547 int VolatileStatement::fallOffEnd()
3549 return statement ? statement->fallOffEnd() : TRUE;
3552 void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3554 buf->writestring("volatile");
3555 if (statement)
3556 { if (statement->isScopeStatement())
3557 buf->writenl();
3558 else
3559 buf->writebyte(' ');
3560 statement->toCBuffer(buf, hgs);
3565 /******************************** GotoStatement ***************************/
3567 GotoStatement::GotoStatement(Loc loc, Identifier *ident)
3568 : Statement(loc)
3570 this->ident = ident;
3571 this->label = NULL;
3572 this->tf = NULL;
3575 Statement *GotoStatement::syntaxCopy()
3577 GotoStatement *s = new GotoStatement(loc, ident);
3578 return s;
3581 Statement *GotoStatement::semantic(Scope *sc)
3582 { FuncDeclaration *fd = sc->parent->isFuncDeclaration();
3584 //printf("GotoStatement::semantic()\n");
3585 tf = sc->tf;
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'
3593 * list.
3595 Statements *a = new Statements();
3596 Statement *s;
3598 a->push(this);
3599 s = new CompoundStatement(loc, a);
3600 sc->fes->gotos.push(s); // 'look at this later' list
3601 return s;
3603 if (label->statement && label->statement->tf != sc->tf)
3604 error("cannot goto in or out of finally block");
3605 return this;
3608 int GotoStatement::fallOffEnd()
3610 return FALSE;
3613 void GotoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3615 buf->writestring("goto ");
3616 buf->writestring(ident->toChars());
3617 buf->writebyte(';');
3618 buf->writenl();
3621 /******************************** LabelStatement ***************************/
3623 LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement)
3624 : Statement(loc)
3626 this->ident = ident;
3627 this->statement = statement;
3628 this->tf = NULL;
3629 this->lblock = NULL;
3630 this->isReturnLabel = 0;
3633 Statement *LabelStatement::syntaxCopy()
3635 LabelStatement *s = new LabelStatement(loc, ident, statement->syntaxCopy());
3636 return s;
3639 Statement *LabelStatement::semantic(Scope *sc)
3640 { LabelDsymbol *ls;
3641 FuncDeclaration *fd = sc->parent->isFuncDeclaration();
3643 //printf("LabelStatement::semantic()\n");
3644 ls = fd->searchLabel(ident);
3645 if (ls->statement)
3646 error("Label '%s' already defined", ls->toChars());
3647 else
3648 ls->statement = this;
3649 tf = sc->tf;
3650 sc = sc->push();
3651 sc->scopesym = sc->enclosing->scopesym;
3652 sc->callSuper |= CSXlabel;
3653 sc->slabel = this;
3654 if (statement)
3655 statement = statement->semantic(sc);
3656 sc->pop();
3657 return this;
3660 Statements *LabelStatement::flatten(Scope *sc)
3662 Statements *a = NULL;
3664 if (statement)
3666 a = statement->flatten(sc);
3667 if (a)
3669 if (!a->dim)
3671 a->push(new ExpStatement(loc, NULL));
3673 Statement *s = (Statement *)a->data[0];
3675 s = new LabelStatement(loc, ident, s);
3676 a->data[0] = s;
3680 return a;
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");
3697 return TRUE;
3700 void LabelStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3702 buf->writestring(ident->toChars());
3703 buf->writebyte(':');
3704 buf->writenl();
3705 if (statement)
3706 statement->toCBuffer(buf, hgs);
3710 /******************************** LabelDsymbol ***************************/
3712 LabelDsymbol::LabelDsymbol(Identifier *ident)
3713 : Dsymbol(ident)
3715 statement = NULL;
3716 #if IN_GCC
3717 asmLabelNum = 0;
3718 #endif
3721 LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()?
3723 return this;