Don't include dynamic arrays in non-null checks
[delight/core.git] / dmd2 / statement.c
blob3d04673ae4eaac5dab91e65565b1ea07407bfeb4
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 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"
35 #include "template.h"
37 /******************************** Statement ***************************/
39 Statement::Statement(Loc loc)
40 : loc(loc)
42 #ifdef _DH
43 // If this is an in{} contract scope statement (skip for determining
44 // inlineStatus of a function body for header content)
45 incontract = 0;
46 #endif
49 Statement *Statement::syntaxCopy()
51 assert(0);
52 return NULL;
55 void Statement::print()
57 fprintf(stdmsg, "%s\n", toChars());
58 fflush(stdmsg);
61 char *Statement::toChars()
62 { OutBuffer *buf;
63 HdrGenState hgs;
65 buf = new OutBuffer();
66 toCBuffer(buf, &hgs);
67 return buf->toChars();
70 void Statement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
72 buf->printf("Statement::toCBuffer()");
73 buf->writenl();
76 Statement *Statement::semantic(Scope *sc)
78 return this;
81 // Same as semantic(), but do create a new scope
83 Statement *Statement::semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue)
84 { Scope *scd;
85 Statement *s;
87 scd = sc->push();
88 if (sbreak)
89 scd->sbreak = sbreak;
90 if (scontinue)
91 scd->scontinue = scontinue;
92 s = semantic(scd);
93 scd->pop();
94 return s;
97 void Statement::error(const char *format, ...)
99 va_list ap;
100 va_start(ap, format);
101 ::verror(loc, format, ap);
102 va_end( ap );
105 int Statement::hasBreak()
107 //printf("Statement::hasBreak()\n");
108 return FALSE;
111 int Statement::hasContinue()
113 return FALSE;
116 // TRUE if statement uses exception handling
118 int Statement::usesEH()
120 return FALSE;
123 /* Only valid after semantic analysis
125 int Statement::blockExit()
127 printf("Statement::blockExit(%p)\n", this);
128 printf("%s\n", toChars());
129 assert(0);
130 return BEany;
133 // TRUE if statement may fall off the end without a throw or return
135 int Statement::fallOffEnd()
137 return TRUE;
140 // TRUE if statement 'comes from' somewhere else, like a goto
142 int Statement::comeFrom()
144 //printf("Statement::comeFrom()\n");
145 return FALSE;
148 /****************************************
149 * If this statement has code that needs to run in a finally clause
150 * at the end of the current scope, return that code in the form of
151 * a Statement.
152 * Output:
153 * *sentry code executed upon entry to the scope
154 * *sexception code executed upon exit from the scope via exception
155 * *sfinally code executed in finally block
158 void Statement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
160 //printf("Statement::scopeCode()\n");
161 //print();
162 *sentry = NULL;
163 *sexception = NULL;
164 *sfinally = NULL;
167 /*********************************
168 * Flatten out the scope by presenting the statement
169 * as an array of statements.
170 * Returns NULL if no flattening necessary.
173 Statements *Statement::flatten(Scope *sc)
175 return NULL;
179 /******************************** ExpStatement ***************************/
181 ExpStatement::ExpStatement(Loc loc, Expression *exp)
182 : Statement(loc)
184 this->exp = exp;
187 Statement *ExpStatement::syntaxCopy()
189 Expression *e = exp ? exp->syntaxCopy() : NULL;
190 ExpStatement *es = new ExpStatement(loc, e);
191 return es;
194 void ExpStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
196 if (exp)
197 exp->toCBuffer(buf, hgs);
198 buf->writeByte(';');
199 if (!hgs->FLinit.init)
200 buf->writenl();
203 Statement *ExpStatement::semantic(Scope *sc)
205 if (exp)
207 //printf("ExpStatement::semantic() %s\n", exp->toChars());
208 exp = exp->semantic(sc);
209 exp = resolveProperties(sc, exp);
210 exp->checkSideEffect(0);
211 exp = exp->optimize(0);
212 //exp = exp->optimize(isDeclarationStatement() ? WANTvalue : 0);
214 return this;
217 int ExpStatement::blockExit()
218 { int result = BEfallthru;
220 if (exp)
222 if (exp->op == TOKhalt)
223 return BEhalt;
224 if (exp->op == TOKassert)
225 { AssertExp *a = (AssertExp *)exp;
227 if (a->e1->isBool(FALSE)) // if it's an assert(0)
228 return BEhalt;
230 if (exp->canThrow())
231 result |= BEthrow;
233 return result;
236 int ExpStatement::fallOffEnd()
238 if (exp)
240 if (exp->op == TOKassert)
241 { AssertExp *a = (AssertExp *)exp;
243 if (a->e1->isBool(FALSE)) // if it's an assert(0)
244 return FALSE;
246 else if (exp->op == TOKhalt)
247 return FALSE;
249 return TRUE;
252 /******************************** CompileStatement ***************************/
254 CompileStatement::CompileStatement(Loc loc, Expression *exp)
255 : Statement(loc)
257 this->exp = exp;
260 Statement *CompileStatement::syntaxCopy()
262 Expression *e = exp->syntaxCopy();
263 CompileStatement *es = new CompileStatement(loc, e);
264 return es;
267 void CompileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
269 buf->writestring("mixin(");
270 exp->toCBuffer(buf, hgs);
271 buf->writestring(");");
272 if (!hgs->FLinit.init)
273 buf->writenl();
276 Statement *CompileStatement::semantic(Scope *sc)
278 //printf("CompileStatement::semantic() %s\n", exp->toChars());
279 exp = exp->semantic(sc);
280 exp = resolveProperties(sc, exp);
281 exp = exp->optimize(WANTvalue | WANTinterpret);
282 if (exp->op != TOKstring)
283 { error("argument to mixin must be a string, not (%s)", exp->toChars());
284 return this;
286 StringExp *se = (StringExp *)exp;
287 se = se->toUTF8(sc);
288 Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
289 p.loc = loc;
290 p.nextToken();
292 Statements *statements = new Statements();
293 while (p.token.value != TOKeof)
295 Statement *s = p.parseStatement(PSsemi | PScurlyscope);
296 statements->push(s);
299 Statement *s = new CompoundStatement(loc, statements);
300 return s->semantic(sc);
304 /******************************** DeclarationStatement ***************************/
306 DeclarationStatement::DeclarationStatement(Loc loc, Dsymbol *declaration)
307 : ExpStatement(loc, new DeclarationExp(loc, declaration))
311 DeclarationStatement::DeclarationStatement(Loc loc, Expression *exp)
312 : ExpStatement(loc, exp)
316 Statement *DeclarationStatement::syntaxCopy()
318 DeclarationStatement *ds = new DeclarationStatement(loc, exp->syntaxCopy());
319 return ds;
322 void DeclarationStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
324 //printf("DeclarationStatement::scopeCode()\n");
325 //print();
327 *sentry = NULL;
328 *sexception = NULL;
329 *sfinally = NULL;
331 if (exp)
333 if (exp->op == TOKdeclaration)
335 DeclarationExp *de = (DeclarationExp *)(exp);
336 VarDeclaration *v = de->declaration->isVarDeclaration();
337 if (v)
338 { Expression *e;
340 e = v->callAutoDtor(sc);
341 if (e)
343 //printf("dtor is: "); e->print();
344 *sfinally = new ExpStatement(loc, e);
351 void DeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
353 exp->toCBuffer(buf, hgs);
357 /******************************** CompoundStatement ***************************/
359 CompoundStatement::CompoundStatement(Loc loc, Statements *s)
360 : Statement(loc)
362 statements = s;
365 CompoundStatement::CompoundStatement(Loc loc, Statement *s1, Statement *s2)
366 : Statement(loc)
368 statements = new Statements();
369 statements->reserve(2);
370 statements->push(s1);
371 statements->push(s2);
374 Statement *CompoundStatement::syntaxCopy()
376 Statements *a = new Statements();
377 a->setDim(statements->dim);
378 for (size_t i = 0; i < statements->dim; i++)
379 { Statement *s = (Statement *)statements->data[i];
380 if (s)
381 s = s->syntaxCopy();
382 a->data[i] = s;
384 CompoundStatement *cs = new CompoundStatement(loc, a);
385 return cs;
389 Statement *CompoundStatement::semantic(Scope *sc)
390 { Statement *s;
392 //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", this, sc);
394 for (size_t i = 0; i < statements->dim; )
396 s = (Statement *) statements->data[i];
397 if (s)
398 { Statements *a = s->flatten(sc);
400 if (a)
402 statements->remove(i);
403 statements->insert(i, a);
404 continue;
406 s = s->semantic(sc);
407 statements->data[i] = s;
408 if (s)
410 Statement *sentry;
411 Statement *sexception;
412 Statement *sfinally;
414 s->scopeCode(sc, &sentry, &sexception, &sfinally);
415 if (sentry)
417 sentry = sentry->semantic(sc);
418 statements->data[i] = sentry;
420 if (sexception)
422 if (i + 1 == statements->dim && !sfinally)
424 #if 1
425 sexception = sexception->semantic(sc);
426 #else
427 statements->push(sexception);
428 if (sfinally)
429 // Assume sexception does not throw
430 statements->push(sfinally);
431 #endif
433 else
435 /* Rewrite:
436 * s; s1; s2;
437 * As:
438 * s;
439 * try { s1; s2; }
440 * catch (Object __o)
441 * { sexception; throw __o; }
443 Statement *body;
444 Statements *a = new Statements();
446 for (int j = i + 1; j < statements->dim; j++)
448 a->push(statements->data[j]);
450 body = new CompoundStatement(0, a);
451 body = new ScopeStatement(0, body);
453 Identifier *id = Lexer::uniqueId("__o");
455 Statement *handler = new ThrowStatement(0, new IdentifierExp(0, id));
456 handler = new CompoundStatement(0, sexception, handler);
458 Array *catches = new Array();
459 Catch *ctch = new Catch(0, NULL, id, handler);
460 catches->push(ctch);
461 s = new TryCatchStatement(0, body, catches);
463 if (sfinally)
464 s = new TryFinallyStatement(0, s, sfinally);
465 s = s->semantic(sc);
466 statements->setDim(i + 1);
467 statements->push(s);
468 break;
471 else if (sfinally)
473 if (0 && i + 1 == statements->dim)
475 statements->push(sfinally);
477 else
479 /* Rewrite:
480 * s; s1; s2;
481 * As:
482 * s; try { s1; s2; } finally { sfinally; }
484 Statement *body;
485 Statements *a = new Statements();
487 for (int j = i + 1; j < statements->dim; j++)
489 a->push(statements->data[j]);
491 body = new CompoundStatement(0, a);
492 s = new TryFinallyStatement(0, body, sfinally);
493 s = s->semantic(sc);
494 statements->setDim(i + 1);
495 statements->push(s);
496 break;
501 i++;
503 if (statements->dim == 1)
504 return s;
505 return this;
508 Statements *CompoundStatement::flatten(Scope *sc)
510 return statements;
513 ReturnStatement *CompoundStatement::isReturnStatement()
514 { int i;
515 ReturnStatement *rs = NULL;
517 for (i = 0; i < statements->dim; i++)
518 { Statement *s;
520 s = (Statement *) statements->data[i];
521 if (s)
523 rs = s->isReturnStatement();
524 if (rs)
525 break;
528 return rs;
531 void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
532 { int i;
534 for (i = 0; i < statements->dim; i++)
535 { Statement *s;
537 s = (Statement *) statements->data[i];
538 if (s)
539 s->toCBuffer(buf, hgs);
543 int CompoundStatement::usesEH()
545 for (int i = 0; i < statements->dim; i++)
546 { Statement *s;
548 s = (Statement *) statements->data[i];
549 if (s && s->usesEH())
550 return TRUE;
552 return FALSE;
555 int CompoundStatement::blockExit()
557 //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim);
558 int result = BEfallthru;
559 for (size_t i = 0; i < statements->dim; i++)
560 { Statement *s = (Statement *) statements->data[i];
561 if (s)
563 //printf("result = x%x\n", result);
564 //printf("%s\n", s->toChars());
565 if (!(result & BEfallthru) && !s->comeFrom())
567 if (global.params.warnings)
568 { fprintf(stdmsg, "warning - ");
569 s->error("statement is not reachable");
573 result &= ~BEfallthru;
574 result |= s->blockExit();
577 return result;
580 int CompoundStatement::fallOffEnd()
581 { int falloff = TRUE;
583 //printf("CompoundStatement::fallOffEnd()\n");
584 for (int i = 0; i < statements->dim; i++)
585 { Statement *s = (Statement *)statements->data[i];
587 if (!s)
588 continue;
590 #if 0
591 if (!falloff && global.params.warnings && !s->comeFrom())
593 fprintf(stdmsg, "warning - ");
594 s->error("statement is not reachable");
596 #endif
597 falloff = s->fallOffEnd();
599 return falloff;
602 int CompoundStatement::comeFrom()
603 { int comefrom = FALSE;
605 //printf("CompoundStatement::comeFrom()\n");
606 for (int i = 0; i < statements->dim; i++)
607 { Statement *s = (Statement *)statements->data[i];
609 if (!s)
610 continue;
612 comefrom |= s->comeFrom();
614 return comefrom;
618 /**************************** UnrolledLoopStatement ***************************/
620 UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s)
621 : Statement(loc)
623 statements = s;
626 Statement *UnrolledLoopStatement::syntaxCopy()
628 Statements *a = new Statements();
629 a->setDim(statements->dim);
630 for (size_t i = 0; i < statements->dim; i++)
631 { Statement *s = (Statement *)statements->data[i];
632 if (s)
633 s = s->syntaxCopy();
634 a->data[i] = s;
636 UnrolledLoopStatement *cs = new UnrolledLoopStatement(loc, a);
637 return cs;
641 Statement *UnrolledLoopStatement::semantic(Scope *sc)
643 //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc);
645 sc->noctor++;
646 Scope *scd = sc->push();
647 scd->sbreak = this;
648 scd->scontinue = this;
650 for (size_t i = 0; i < statements->dim; i++)
652 Statement *s = (Statement *) statements->data[i];
653 if (s)
655 s = s->semantic(scd);
656 statements->data[i] = s;
660 scd->pop();
661 sc->noctor--;
662 return this;
665 void UnrolledLoopStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
667 buf->writestring("unrolled {");
668 buf->writenl();
670 for (size_t i = 0; i < statements->dim; i++)
671 { Statement *s;
673 s = (Statement *) statements->data[i];
674 if (s)
675 s->toCBuffer(buf, hgs);
678 buf->writeByte('}');
679 buf->writenl();
682 int UnrolledLoopStatement::hasBreak()
684 return TRUE;
687 int UnrolledLoopStatement::hasContinue()
689 return TRUE;
692 int UnrolledLoopStatement::usesEH()
694 for (size_t i = 0; i < statements->dim; i++)
695 { Statement *s = (Statement *) statements->data[i];
696 if (s && s->usesEH())
697 return TRUE;
699 return FALSE;
702 int UnrolledLoopStatement::blockExit()
704 int result = BEfallthru;
705 for (size_t i = 0; i < statements->dim; i++)
706 { Statement *s = (Statement *) statements->data[i];
707 if (s)
709 int r = s->blockExit();
710 result |= r & ~(BEbreak | BEcontinue);
713 return result;
716 int UnrolledLoopStatement::fallOffEnd()
718 //printf("UnrolledLoopStatement::fallOffEnd()\n");
719 for (size_t i = 0; i < statements->dim; i++)
720 { Statement *s = (Statement *)statements->data[i];
722 if (s)
723 s->fallOffEnd();
725 return TRUE;
728 int UnrolledLoopStatement::comeFrom()
729 { int comefrom = FALSE;
731 //printf("UnrolledLoopStatement::comeFrom()\n");
732 for (size_t i = 0; i < statements->dim; i++)
733 { Statement *s = (Statement *)statements->data[i];
735 if (!s)
736 continue;
738 comefrom |= s->comeFrom();
740 return comefrom;
744 /******************************** ScopeStatement ***************************/
746 ScopeStatement::ScopeStatement(Loc loc, Statement *s)
747 : Statement(loc)
749 this->statement = s;
752 Statement *ScopeStatement::syntaxCopy()
754 Statement *s;
756 s = statement ? statement->syntaxCopy() : NULL;
757 s = new ScopeStatement(loc, s);
758 return s;
762 Statement *ScopeStatement::semantic(Scope *sc)
763 { ScopeDsymbol *sym;
765 //printf("ScopeStatement::semantic(sc = %p)\n", sc);
766 if (statement)
767 { Statements *a;
769 sym = new ScopeDsymbol();
770 sym->parent = sc->scopesym;
771 sc = sc->push(sym);
773 a = statement->flatten(sc);
774 if (a)
776 statement = new CompoundStatement(loc, a);
779 statement = statement->semantic(sc);
780 if (statement)
782 Statement *sentry;
783 Statement *sexception;
784 Statement *sfinally;
786 statement->scopeCode(sc, &sentry, &sexception, &sfinally);
787 if (sfinally)
789 //printf("adding sfinally\n");
790 statement = new CompoundStatement(loc, statement, sfinally);
794 sc->pop();
796 return this;
799 int ScopeStatement::hasBreak()
801 //printf("ScopeStatement::hasBreak() %s\n", toChars());
802 return statement ? statement->hasBreak() : FALSE;
805 int ScopeStatement::hasContinue()
807 return statement ? statement->hasContinue() : FALSE;
810 int ScopeStatement::usesEH()
812 return statement ? statement->usesEH() : FALSE;
815 int ScopeStatement::blockExit()
817 //printf("ScopeStatement::blockExit(%p)\n", statement);
818 return statement ? statement->blockExit() : BEfallthru;
821 int ScopeStatement::fallOffEnd()
823 return statement ? statement->fallOffEnd() : TRUE;
826 int ScopeStatement::comeFrom()
828 //printf("ScopeStatement::comeFrom()\n");
829 return statement ? statement->comeFrom() : FALSE;
832 void ScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
834 buf->writeByte('{');
835 buf->writenl();
837 if (statement)
838 statement->toCBuffer(buf, hgs);
840 buf->writeByte('}');
841 buf->writenl();
844 /******************************** WhileStatement ***************************/
846 WhileStatement::WhileStatement(Loc loc, Expression *c, Statement *b)
847 : Statement(loc)
849 condition = c;
850 body = b;
853 Statement *WhileStatement::syntaxCopy()
855 WhileStatement *s = new WhileStatement(loc, condition->syntaxCopy(), body ? body->syntaxCopy() : NULL);
856 return s;
860 Statement *WhileStatement::semantic(Scope *sc)
862 #if 0
863 if (condition->op == TOKmatch)
865 /* Rewrite while (condition) body as:
866 * if (condition)
867 * do
868 * body
869 * while ((_match = _match.opNext), _match);
872 Expression *ew = new IdentifierExp(0, Id::_match);
873 ew = new DotIdExp(0, ew, Id::next);
874 ew = new AssignExp(0, new IdentifierExp(0, Id::_match), ew);
875 ////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0));
876 Expression *ev = new IdentifierExp(0, Id::_match);
877 //ev = new CastExp(0, ev, Type::tvoidptr);
878 ew = new CommaExp(0, ew, ev);
879 Statement *sw = new DoStatement(loc, body, ew);
880 Statement *si = new IfStatement(loc, condition, sw, NULL);
881 return si->semantic(sc);
883 #endif
885 condition = condition->semantic(sc);
886 condition = resolveProperties(sc, condition);
887 condition = condition->optimize(WANTvalue);
888 condition = condition->checkToBoolean();
890 sc->noctor++;
892 Scope *scd = sc->push();
893 scd->sbreak = this;
894 scd->scontinue = this;
895 if (body)
896 body = body->semantic(scd);
897 scd->pop();
899 sc->noctor--;
901 return this;
904 int WhileStatement::hasBreak()
906 return TRUE;
909 int WhileStatement::hasContinue()
911 return TRUE;
914 int WhileStatement::usesEH()
916 return body ? body->usesEH() : 0;
919 int WhileStatement::blockExit()
921 //printf("WhileStatement::blockExit(%p)\n", this);
923 int result = BEnone;
924 if (condition->canThrow())
925 result |= BEthrow;
926 if (body)
927 { result |= body->blockExit();
928 if (result & BEbreak)
929 result |= BEfallthru;
930 result &= ~(BEbreak | BEcontinue);
932 else
933 result |= BEfallthru;
934 return result;
937 int WhileStatement::fallOffEnd()
939 if (body)
940 body->fallOffEnd();
941 return TRUE;
944 int WhileStatement::comeFrom()
946 if (body)
947 return body->comeFrom();
948 return FALSE;
951 void WhileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
953 buf->writestring("while (");
954 condition->toCBuffer(buf, hgs);
955 buf->writebyte(')');
956 buf->writenl();
957 if (body)
958 body->toCBuffer(buf, hgs);
961 /******************************** DoStatement ***************************/
963 DoStatement::DoStatement(Loc loc, Statement *b, Expression *c)
964 : Statement(loc)
966 body = b;
967 condition = c;
970 Statement *DoStatement::syntaxCopy()
972 DoStatement *s = new DoStatement(loc, body ? body->syntaxCopy() : NULL, condition->syntaxCopy());
973 return s;
977 Statement *DoStatement::semantic(Scope *sc)
979 sc->noctor++;
980 if (body)
981 body = body->semanticScope(sc, this, this);
982 sc->noctor--;
983 condition = condition->semantic(sc);
984 condition = resolveProperties(sc, condition);
985 condition = condition->optimize(WANTvalue);
987 condition = condition->checkToBoolean();
989 return this;
992 int DoStatement::hasBreak()
994 return TRUE;
997 int DoStatement::hasContinue()
999 return TRUE;
1002 int DoStatement::usesEH()
1004 return body ? body->usesEH() : 0;
1007 int DoStatement::blockExit()
1008 { int result;
1010 if (body)
1011 { result = body->blockExit();
1012 if (result & BEbreak)
1014 if (result == BEbreak)
1015 return BEfallthru;
1016 result |= BEfallthru;
1018 if (result & BEcontinue)
1019 result |= BEfallthru;
1020 result &= ~(BEbreak | BEcontinue);
1022 else
1023 result = BEfallthru;
1024 if (result & BEfallthru && condition->canThrow())
1025 result |= BEthrow;
1026 return result;
1029 int DoStatement::fallOffEnd()
1031 if (body)
1032 body->fallOffEnd();
1033 return TRUE;
1036 int DoStatement::comeFrom()
1038 if (body)
1039 return body->comeFrom();
1040 return FALSE;
1043 void DoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1045 buf->writestring("do");
1046 buf->writenl();
1047 if (body)
1048 body->toCBuffer(buf, hgs);
1049 buf->writestring("while (");
1050 condition->toCBuffer(buf, hgs);
1051 buf->writebyte(')');
1054 /******************************** ForStatement ***************************/
1056 ForStatement::ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body)
1057 : Statement(loc)
1059 this->init = init;
1060 this->condition = condition;
1061 this->increment = increment;
1062 this->body = body;
1065 Statement *ForStatement::syntaxCopy()
1067 Statement *i = NULL;
1068 if (init)
1069 i = init->syntaxCopy();
1070 Expression *c = NULL;
1071 if (condition)
1072 c = condition->syntaxCopy();
1073 Expression *inc = NULL;
1074 if (increment)
1075 inc = increment->syntaxCopy();
1076 ForStatement *s = new ForStatement(loc, i, c, inc, body->syntaxCopy());
1077 return s;
1080 Statement *ForStatement::semantic(Scope *sc)
1082 ScopeDsymbol *sym = new ScopeDsymbol();
1083 sym->parent = sc->scopesym;
1084 sc = sc->push(sym);
1085 if (init)
1086 init = init->semantic(sc);
1087 sc->noctor++;
1088 if (condition)
1090 condition = condition->semantic(sc);
1091 condition = resolveProperties(sc, condition);
1092 condition = condition->optimize(WANTvalue);
1093 condition = condition->checkToBoolean();
1095 if (increment)
1096 increment = increment->semantic(sc);
1098 sc->sbreak = this;
1099 sc->scontinue = this;
1100 body = body->semantic(sc);
1101 sc->noctor--;
1103 sc->pop();
1104 return this;
1107 void ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
1109 //printf("ForStatement::scopeCode()\n");
1110 //print();
1111 if (init)
1112 init->scopeCode(sc, sentry, sexception, sfinally);
1113 else
1114 Statement::scopeCode(sc, sentry, sexception, sfinally);
1117 int ForStatement::hasBreak()
1119 //printf("ForStatement::hasBreak()\n");
1120 return TRUE;
1123 int ForStatement::hasContinue()
1125 return TRUE;
1128 int ForStatement::usesEH()
1130 return (init && init->usesEH()) || body->usesEH();
1133 int ForStatement::blockExit()
1134 { int result = BEfallthru;
1136 if (init)
1137 { result = init->blockExit();
1138 if (!(result & BEfallthru))
1139 return result;
1141 if (condition)
1142 { if (condition->canThrow())
1143 result |= BEthrow;
1145 else
1146 result &= ~BEfallthru; // the body must do the exiting
1147 if (body)
1148 { int r = body->blockExit();
1149 if (r & BEbreak)
1150 result |= BEfallthru;
1151 result |= r & ~(BEbreak | BEcontinue);
1153 if (increment && increment->canThrow())
1154 result |= BEthrow;
1155 return result;
1158 int ForStatement::fallOffEnd()
1160 if (body)
1161 body->fallOffEnd();
1162 return TRUE;
1165 int ForStatement::comeFrom()
1167 //printf("ForStatement::comeFrom()\n");
1168 if (body)
1169 { int result = body->comeFrom();
1170 //printf("result = %d\n", result);
1171 return result;
1173 return FALSE;
1176 void ForStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1178 buf->writestring("for (");
1179 if (init)
1181 hgs->FLinit.init++;
1182 hgs->FLinit.decl = 0;
1183 init->toCBuffer(buf, hgs);
1184 if (hgs->FLinit.decl > 0)
1185 buf->writebyte(';');
1186 hgs->FLinit.decl = 0;
1187 hgs->FLinit.init--;
1189 else
1190 buf->writebyte(';');
1191 if (condition)
1192 { buf->writebyte(' ');
1193 condition->toCBuffer(buf, hgs);
1195 buf->writebyte(';');
1196 if (increment)
1197 { buf->writebyte(' ');
1198 increment->toCBuffer(buf, hgs);
1200 buf->writebyte(')');
1201 buf->writenl();
1202 buf->writebyte('{');
1203 buf->writenl();
1204 body->toCBuffer(buf, hgs);
1205 buf->writebyte('}');
1206 buf->writenl();
1209 /******************************** ForeachStatement ***************************/
1211 ForeachStatement::ForeachStatement(Loc loc, enum TOK op, Arguments *arguments,
1212 Expression *aggr, Statement *body)
1213 : Statement(loc)
1215 this->op = op;
1216 this->arguments = arguments;
1217 this->aggr = aggr;
1218 this->body = body;
1220 this->key = NULL;
1221 this->value = NULL;
1223 this->func = NULL;
1226 Statement *ForeachStatement::syntaxCopy()
1228 Arguments *args = Argument::arraySyntaxCopy(arguments);
1229 Expression *exp = aggr->syntaxCopy();
1230 ForeachStatement *s = new ForeachStatement(loc, op, args, exp,
1231 body ? body->syntaxCopy() : NULL);
1232 return s;
1235 Statement *ForeachStatement::semantic(Scope *sc)
1237 //printf("ForeachStatement::semantic() %p\n", this);
1238 ScopeDsymbol *sym;
1239 Statement *s = this;
1240 int dim = arguments->dim;
1241 int i;
1242 TypeAArray *taa = NULL;
1244 Type *tn = NULL;
1245 Type *tnv = NULL;
1247 func = sc->func;
1248 if (func->fes)
1249 func = func->fes->func;
1251 aggr = aggr->semantic(sc);
1252 aggr = resolveProperties(sc, aggr);
1253 aggr = aggr->optimize(WANTvalue);
1254 if (!aggr->type)
1256 error("invalid foreach aggregate %s", aggr->toChars());
1257 return this;
1260 inferApplyArgTypes(op, arguments, aggr);
1262 /* Check for inference errors
1264 if (dim != arguments->dim)
1266 //printf("dim = %d, arguments->dim = %d\n", dim, arguments->dim);
1267 error("cannot uniquely infer foreach argument types");
1268 return this;
1271 Type *tab = aggr->type->toBasetype();
1273 if (tab->ty == Ttuple) // don't generate new scope for tuple loops
1275 if (dim < 1 || dim > 2)
1277 error("only one (value) or two (key,value) arguments for tuple foreach");
1278 return s;
1281 TypeTuple *tuple = (TypeTuple *)tab;
1282 Statements *statements = new Statements();
1283 //printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars());
1284 size_t n;
1285 TupleExp *te = NULL;
1286 if (aggr->op == TOKtuple) // expression tuple
1287 { te = (TupleExp *)aggr;
1288 n = te->exps->dim;
1290 else if (aggr->op == TOKtype) // type tuple
1292 n = Argument::dim(tuple->arguments);
1294 else
1295 assert(0);
1296 for (size_t j = 0; j < n; j++)
1297 { size_t k = (op == TOKforeach) ? j : n - 1 - j;
1298 Expression *e;
1299 Type *t;
1300 if (te)
1301 e = (Expression *)te->exps->data[k];
1302 else
1303 t = Argument::getNth(tuple->arguments, k)->type;
1304 Argument *arg = (Argument *)arguments->data[0];
1305 Statements *st = new Statements();
1307 if (dim == 2)
1308 { // Declare key
1309 if (arg->storageClass & (STCout | STCref | STClazy))
1310 error("no storage class for key %s", arg->ident->toChars());
1311 TY keyty = arg->type->ty;
1312 if ((keyty != Tint32 && keyty != Tuns32) &&
1313 (! global.params.isX86_64 ||
1314 (keyty != Tint64 && keyty != Tuns64))
1317 error("foreach: key type must be int or uint, not %s", arg->type->toChars());
1319 Initializer *ie = new ExpInitializer(0, new IntegerExp(k));
1320 VarDeclaration *var = new VarDeclaration(loc, arg->type, arg->ident, ie);
1321 var->storage_class |= STCmanifest;
1322 DeclarationExp *de = new DeclarationExp(loc, var);
1323 st->push(new ExpStatement(loc, de));
1324 arg = (Argument *)arguments->data[1]; // value
1326 // Declare value
1327 if (arg->storageClass & (STCout | STCref | STClazy))
1328 error("no storage class for value %s", arg->ident->toChars());
1329 Dsymbol *var;
1330 if (te)
1331 { Type *tb = e->type->toBasetype();
1332 if ((tb->ty == Tfunction || tb->ty == Tsarray) && e->op == TOKvar)
1333 { VarExp *ve = (VarExp *)e;
1334 var = new AliasDeclaration(loc, arg->ident, ve->var);
1336 else
1338 arg->type = e->type;
1339 Initializer *ie = new ExpInitializer(0, e);
1340 VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie);
1341 if (e->isConst())
1342 v->storage_class |= STCconst;
1343 var = v;
1346 else
1348 var = new AliasDeclaration(loc, arg->ident, t);
1350 DeclarationExp *de = new DeclarationExp(loc, var);
1351 st->push(new ExpStatement(loc, de));
1353 st->push(body->syntaxCopy());
1354 s = new CompoundStatement(loc, st);
1355 s = new ScopeStatement(loc, s);
1356 statements->push(s);
1359 s = new UnrolledLoopStatement(loc, statements);
1360 s = s->semantic(sc);
1361 return s;
1364 for (i = 0; i < dim; i++)
1365 { Argument *arg = (Argument *)arguments->data[i];
1366 if (!arg->type)
1368 error("cannot infer type for %s", arg->ident->toChars());
1369 return this;
1373 sym = new ScopeDsymbol();
1374 sym->parent = sc->scopesym;
1375 sc = sc->push(sym);
1377 sc->noctor++;
1379 switch (tab->ty)
1381 case Tarray:
1382 case Tsarray:
1383 if (dim < 1 || dim > 2)
1385 error("only one or two arguments for array foreach");
1386 break;
1389 /* Look for special case of parsing char types out of char type
1390 * array.
1392 tn = tab->nextOf()->toBasetype();
1393 if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
1394 { Argument *arg;
1396 i = (dim == 1) ? 0 : 1; // index of value
1397 arg = (Argument *)arguments->data[i];
1398 arg->type = arg->type->semantic(loc, sc);
1399 tnv = arg->type->toBasetype();
1400 if (tnv->ty != tn->ty &&
1401 (tnv->ty == Tchar || tnv->ty == Twchar || tnv->ty == Tdchar))
1403 if (arg->storageClass & STCref)
1404 error("foreach: value of UTF conversion cannot be ref");
1405 if (dim == 2)
1406 { arg = (Argument *)arguments->data[0];
1407 if (arg->storageClass & STCref)
1408 error("foreach: key cannot be ref");
1410 goto Lapply;
1414 for (i = 0; i < dim; i++)
1415 { // Declare args
1416 Argument *arg = (Argument *)arguments->data[i];
1417 VarDeclaration *var;
1419 var = new VarDeclaration(loc, arg->type, arg->ident, NULL);
1420 var->storage_class |= STCforeach;
1421 var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant);
1422 if (dim == 2 && i == 0)
1423 { key = var;
1424 //var->storage_class |= STCfinal;
1426 else
1427 { //if (!(arg->storageClass & STCref))
1428 //var->storage_class |= STCfinal;
1429 value = var;
1431 #if 1
1432 DeclarationExp *de = new DeclarationExp(loc, var);
1433 de->semantic(sc);
1434 #else
1435 var->semantic(sc);
1436 if (!sc->insert(var))
1437 error("%s already defined", var->ident->toChars());
1438 #endif
1441 sc->sbreak = this;
1442 sc->scontinue = this;
1443 body = body->semantic(sc);
1445 if (tab->nextOf()->implicitConvTo(value->type) < MATCHconst)
1447 if (aggr->op == TOKstring)
1448 aggr = aggr->implicitCastTo(sc, value->type->arrayOf());
1449 else
1450 error("foreach: %s is not an array of %s",
1451 tab->toChars(), value->type->toChars());
1454 if (key &&
1455 ((key->type->ty != Tint32 && key->type->ty != Tuns32) &&
1456 (! global.params.isX86_64 ||
1457 (key->type->ty != Tint64 && key->type->ty != Tuns64))
1461 error("foreach: key type must be int or uint, not %s", key->type->toChars());
1464 if (key && key->storage_class & (STCout | STCref))
1465 error("foreach: key cannot be out or ref");
1466 break;
1468 case Taarray:
1469 taa = (TypeAArray *)tab;
1470 if (dim < 1 || dim > 2)
1472 error("only one or two arguments for associative array foreach");
1473 break;
1475 if (op == TOKforeach_reverse)
1477 error("no reverse iteration on associative arrays");
1479 goto Lapply;
1481 case Tclass:
1482 case Tstruct:
1483 case Tdelegate:
1484 Lapply:
1485 { FuncDeclaration *fdapply;
1486 Arguments *args;
1487 Expression *ec;
1488 Expression *e;
1489 FuncLiteralDeclaration *fld;
1490 Argument *a;
1491 Type *t;
1492 Expression *flde;
1493 Identifier *id;
1494 Type *tret;
1496 tret = func->type->nextOf();
1498 // Need a variable to hold value from any return statements in body.
1499 if (!sc->func->vresult && tret && tret != Type::tvoid)
1500 { VarDeclaration *v;
1502 v = new VarDeclaration(loc, tret, Id::result, NULL);
1503 v->noauto = 1;
1504 v->semantic(sc);
1505 if (!sc->insert(v))
1506 assert(0);
1507 v->parent = sc->func;
1508 sc->func->vresult = v;
1511 /* Turn body into the function literal:
1512 * int delegate(ref T arg) { body }
1514 args = new Arguments();
1515 for (i = 0; i < dim; i++)
1516 { Argument *arg = (Argument *)arguments->data[i];
1518 arg->type = arg->type->semantic(loc, sc);
1519 if (arg->storageClass & STCref)
1520 id = arg->ident;
1521 else
1522 { // Make a copy of the ref argument so it isn't
1523 // a reference.
1524 VarDeclaration *v;
1525 Initializer *ie;
1527 id = Lexer::uniqueId("__applyArg", i);
1529 ie = new ExpInitializer(0, new IdentifierExp(0, id));
1530 v = new VarDeclaration(0, arg->type, arg->ident, ie);
1531 s = new DeclarationStatement(0, v);
1532 body = new CompoundStatement(loc, s, body);
1534 a = new Argument(STCref, arg->type, id, NULL);
1535 args->push(a);
1537 t = new TypeFunction(args, Type::tint32, 0, LINKd);
1538 fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this);
1539 fld->fbody = body;
1540 flde = new FuncExp(loc, fld);
1541 flde = flde->semantic(sc);
1542 fld->tookAddressOf = 0;
1544 // Resolve any forward referenced goto's
1545 for (int i = 0; i < gotos.dim; i++)
1546 { CompoundStatement *cs = (CompoundStatement *)gotos.data[i];
1547 GotoStatement *gs = (GotoStatement *)cs->statements->data[0];
1549 if (!gs->label->statement)
1550 { // 'Promote' it to this scope, and replace with a return
1551 cases.push(gs);
1552 s = new ReturnStatement(0, new IntegerExp(cases.dim + 1));
1553 cs->statements->data[0] = (void *)s;
1557 if (tab->ty == Taarray)
1559 // Check types
1560 Argument *arg = (Argument *)arguments->data[0];
1561 if (dim == 2)
1563 if (arg->storageClass & STCref)
1564 error("foreach: index cannot be ref");
1565 if (!arg->type->equals(taa->index))
1566 error("foreach: index must be type %s, not %s", taa->index->toChars(), arg->type->toChars());
1567 arg = (Argument *)arguments->data[1];
1569 if (!arg->type->equals(taa->nextOf()))
1570 error("foreach: value must be type %s, not %s", taa->nextOf()->toChars(), arg->type->toChars());
1572 /* Call:
1573 * _aaApply(aggr, keysize, flde)
1575 if (dim == 2)
1576 fdapply = FuncDeclaration::genCfunc(Type::tint32, "_aaApply2",
1577 Type::tvoid->arrayOf(), Type::tsize_t, flde->type); // flde->type is not generic
1578 else
1579 fdapply = FuncDeclaration::genCfunc(Type::tint32, "_aaApply",
1580 Type::tvoid->arrayOf(), Type::tsize_t, flde->type); // flde->type is not generic);
1581 ec = new VarExp(0, fdapply);
1582 Expressions *exps = new Expressions();
1583 exps->push(aggr);
1584 size_t keysize = taa->index->size();
1585 keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1);
1586 exps->push(new IntegerExp(0, keysize, Type::tsize_t));
1587 exps->push(flde);
1588 e = new CallExp(loc, ec, exps);
1589 e->type = Type::tint32; // don't run semantic() on e
1591 else if (tab->ty == Tarray || tab->ty == Tsarray)
1593 /* Call:
1594 * _aApply(aggr, flde)
1596 static char fntab[9][3] =
1597 { "cc","cw","cd",
1598 "wc","cc","wd",
1599 "dc","dw","dd"
1601 char fdname[7+1+2+ sizeof(dim)*3 + 1];
1602 int flag;
1604 switch (tn->ty)
1606 case Tchar: flag = 0; break;
1607 case Twchar: flag = 3; break;
1608 case Tdchar: flag = 6; break;
1609 default: assert(0);
1611 switch (tnv->ty)
1613 case Tchar: flag += 0; break;
1614 case Twchar: flag += 1; break;
1615 case Tdchar: flag += 2; break;
1616 default: assert(0);
1618 const char *r = (op == TOKforeach_reverse) ? "R" : "";
1619 int j = sprintf(fdname, "_aApply%s%.*s%d", r, 2, fntab[flag], dim);
1620 assert(j < sizeof(fdname));
1621 fdapply = FuncDeclaration::genCfunc(Type::tint32, fdname,
1622 Type::tvoid->arrayOf(), flde->type); // flde->type is not generic
1624 ec = new VarExp(0, fdapply);
1625 Expressions *exps = new Expressions();
1626 if (tab->ty == Tsarray)
1627 aggr = aggr->castTo(sc, tn->arrayOf());
1628 exps->push(aggr);
1629 exps->push(flde);
1630 e = new CallExp(loc, ec, exps);
1631 e->type = Type::tint32; // don't run semantic() on e
1633 else if (tab->ty == Tdelegate)
1635 /* Call:
1636 * aggr(flde)
1638 Expressions *exps = new Expressions();
1639 exps->push(flde);
1640 e = new CallExp(loc, aggr, exps);
1641 e = e->semantic(sc);
1642 if (e->type != Type::tint32)
1643 error("opApply() function for %s must return an int", tab->toChars());
1645 else
1647 /* Call:
1648 * aggr.apply(flde)
1650 ec = new DotIdExp(loc, aggr,
1651 (op == TOKforeach_reverse) ? Id::applyReverse
1652 : Id::apply);
1653 Expressions *exps = new Expressions();
1654 exps->push(flde);
1655 e = new CallExp(loc, ec, exps);
1656 e = e->semantic(sc);
1657 if (e->type != Type::tint32)
1658 error("opApply() function for %s must return an int", tab->toChars());
1661 if (!cases.dim)
1662 // Easy case, a clean exit from the loop
1663 s = new ExpStatement(loc, e);
1664 else
1665 { // Construct a switch statement around the return value
1666 // of the apply function.
1667 Statements *a = new Statements();
1669 // default: break; takes care of cases 0 and 1
1670 s = new BreakStatement(0, NULL);
1671 s = new DefaultStatement(0, s);
1672 a->push(s);
1674 // cases 2...
1675 for (int i = 0; i < cases.dim; i++)
1677 s = (Statement *)cases.data[i];
1678 s = new CaseStatement(0, new IntegerExp(i + 2), s);
1679 a->push(s);
1682 s = new CompoundStatement(loc, a);
1683 s = new SwitchStatement(loc, e, s);
1684 s = s->semantic(sc);
1686 break;
1689 default:
1690 error("foreach: %s is not an aggregate type", aggr->type->toChars());
1691 break;
1693 sc->noctor--;
1694 sc->pop();
1695 return s;
1698 int ForeachStatement::hasBreak()
1700 return TRUE;
1703 int ForeachStatement::hasContinue()
1705 return TRUE;
1708 int ForeachStatement::usesEH()
1710 return body->usesEH();
1713 int ForeachStatement::blockExit()
1714 { int result = BEfallthru;
1716 if (aggr->canThrow())
1717 result |= BEthrow;
1719 if (body)
1721 result |= body->blockExit() & ~(BEbreak | BEcontinue);
1723 return result;
1726 int ForeachStatement::fallOffEnd()
1728 if (body)
1729 body->fallOffEnd();
1730 return TRUE;
1733 int ForeachStatement::comeFrom()
1735 if (body)
1736 return body->comeFrom();
1737 return FALSE;
1740 void ForeachStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1742 buf->writestring(Token::toChars(op));
1743 buf->writestring(" (");
1744 for (int i = 0; i < arguments->dim; i++)
1746 Argument *a = (Argument *)arguments->data[i];
1747 if (i)
1748 buf->writestring(", ");
1749 if (a->storageClass & STCref)
1750 buf->writestring((global.params.Dversion == 1)
1751 ? (char*)"inout " : (char*)"ref ");
1752 if (a->type)
1753 a->type->toCBuffer(buf, a->ident, hgs);
1754 else
1755 buf->writestring(a->ident->toChars());
1757 buf->writestring("; ");
1758 aggr->toCBuffer(buf, hgs);
1759 buf->writebyte(')');
1760 buf->writenl();
1761 buf->writebyte('{');
1762 buf->writenl();
1763 if (body)
1764 body->toCBuffer(buf, hgs);
1765 buf->writebyte('}');
1766 buf->writenl();
1769 /**************************** ForeachRangeStatement ***************************/
1771 ForeachRangeStatement::ForeachRangeStatement(Loc loc, enum TOK op, Argument *arg,
1772 Expression *lwr, Expression *upr, Statement *body)
1773 : Statement(loc)
1775 this->op = op;
1776 this->arg = arg;
1777 this->lwr = lwr;
1778 this->upr = upr;
1779 this->body = body;
1781 this->key = NULL;
1784 Statement *ForeachRangeStatement::syntaxCopy()
1786 ForeachRangeStatement *s = new ForeachRangeStatement(loc, op,
1787 arg->syntaxCopy(),
1788 lwr->syntaxCopy(),
1789 upr->syntaxCopy(),
1790 body ? body->syntaxCopy() : NULL);
1791 return s;
1794 Statement *ForeachRangeStatement::semantic(Scope *sc)
1796 //printf("ForeachRangeStatement::semantic() %p\n", this);
1797 ScopeDsymbol *sym;
1798 Statement *s = this;
1800 lwr = lwr->semantic(sc);
1801 lwr = resolveProperties(sc, lwr);
1802 lwr = lwr->optimize(WANTvalue);
1803 if (!lwr->type)
1805 error("invalid range lower bound %s", lwr->toChars());
1806 return this;
1809 upr = upr->semantic(sc);
1810 upr = resolveProperties(sc, upr);
1811 upr = upr->optimize(WANTvalue);
1812 if (!upr->type)
1814 error("invalid range upper bound %s", upr->toChars());
1815 return this;
1818 if (arg->type)
1820 lwr = lwr->implicitCastTo(sc, arg->type);
1821 upr = upr->implicitCastTo(sc, arg->type);
1823 else
1825 /* Must infer types from lwr and upr
1827 AddExp ea(loc, lwr, upr);
1828 ea.typeCombine(sc);
1829 arg->type = ea.type;
1830 lwr = ea.e1;
1831 upr = ea.e2;
1833 if (!arg->type->isscalar())
1834 error("%s is not a scalar type", arg->type->toChars());
1836 sym = new ScopeDsymbol();
1837 sym->parent = sc->scopesym;
1838 sc = sc->push(sym);
1840 sc->noctor++;
1842 key = new VarDeclaration(loc, arg->type, arg->ident, NULL);
1843 DeclarationExp *de = new DeclarationExp(loc, key);
1844 de->semantic(sc);
1846 if (key->storage_class)
1847 error("foreach range: key cannot have storage class");
1849 sc->sbreak = this;
1850 sc->scontinue = this;
1851 body = body->semantic(sc);
1853 sc->noctor--;
1854 sc->pop();
1855 return s;
1858 int ForeachRangeStatement::hasBreak()
1860 return TRUE;
1863 int ForeachRangeStatement::hasContinue()
1865 return TRUE;
1868 int ForeachRangeStatement::usesEH()
1870 return body->usesEH();
1873 int ForeachRangeStatement::blockExit()
1874 { int result = BEfallthru;
1876 if (lwr && lwr->canThrow())
1877 result |= BEthrow;
1878 else if (upr && upr->canThrow())
1879 result |= BEthrow;
1881 if (body)
1883 result |= body->blockExit() & ~(BEbreak | BEcontinue);
1885 return result;
1888 int ForeachRangeStatement::fallOffEnd()
1890 if (body)
1891 body->fallOffEnd();
1892 return TRUE;
1895 int ForeachRangeStatement::comeFrom()
1897 if (body)
1898 return body->comeFrom();
1899 return FALSE;
1902 void ForeachRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1904 buf->writestring(Token::toChars(op));
1905 buf->writestring(" (");
1907 if (arg->type)
1908 arg->type->toCBuffer(buf, arg->ident, hgs);
1909 else
1910 buf->writestring(arg->ident->toChars());
1912 buf->writestring("; ");
1913 lwr->toCBuffer(buf, hgs);
1914 buf->writestring(" .. ");
1915 upr->toCBuffer(buf, hgs);
1916 buf->writebyte(')');
1917 buf->writenl();
1918 buf->writebyte('{');
1919 buf->writenl();
1920 if (body)
1921 body->toCBuffer(buf, hgs);
1922 buf->writebyte('}');
1923 buf->writenl();
1926 /******************************** IfStatement ***************************/
1928 IfStatement::IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody)
1929 : Statement(loc)
1931 this->arg = arg;
1932 this->condition = condition;
1933 this->ifbody = ifbody;
1934 this->elsebody = elsebody;
1935 this->match = NULL;
1938 Statement *IfStatement::syntaxCopy()
1940 Statement *i = NULL;
1941 if (ifbody)
1942 i = ifbody->syntaxCopy();
1944 Statement *e = NULL;
1945 if (elsebody)
1946 e = elsebody->syntaxCopy();
1948 Argument *a = arg ? arg->syntaxCopy() : NULL;
1949 IfStatement *s = new IfStatement(loc, a, condition->syntaxCopy(), i, e);
1950 return s;
1953 Statement *IfStatement::semantic(Scope *sc)
1955 condition = condition->semantic(sc);
1956 condition = resolveProperties(sc, condition);
1957 condition = condition->checkToBoolean();
1959 // If we can short-circuit evaluate the if statement, don't do the
1960 // semantic analysis of the skipped code.
1961 // This feature allows a limited form of conditional compilation.
1962 condition = condition->optimize(WANTflags);
1964 // Evaluate at runtime
1965 unsigned cs0 = sc->callSuper;
1966 unsigned cs1;
1968 Scope *scd;
1969 if (arg)
1970 { /* Declare arg, which we will set to be the
1971 * result of condition.
1973 ScopeDsymbol *sym = new ScopeDsymbol();
1974 sym->parent = sc->scopesym;
1975 scd = sc->push(sym);
1977 Type *t = arg->type ? arg->type : condition->type;
1978 match = new VarDeclaration(loc, t, arg->ident, NULL);
1979 match->noauto = 1;
1980 match->semantic(scd);
1981 if (!scd->insert(match))
1982 assert(0);
1983 match->parent = sc->func;
1985 /* Generate:
1986 * (arg = condition)
1988 VarExp *v = new VarExp(0, match);
1989 condition = new AssignExp(loc, v, condition);
1990 condition = condition->semantic(scd);
1992 else
1993 scd = sc->push();
1994 ifbody = ifbody->semantic(scd);
1995 scd->pop();
1997 cs1 = sc->callSuper;
1998 sc->callSuper = cs0;
1999 if (elsebody)
2000 elsebody = elsebody->semanticScope(sc, NULL, NULL);
2001 sc->mergeCallSuper(loc, cs1);
2003 return this;
2006 int IfStatement::usesEH()
2008 return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH());
2011 int IfStatement::blockExit()
2013 //printf("IfStatement::blockExit(%p)\n", this);
2015 int result = BEnone;
2016 if (condition->canThrow())
2017 result |= BEthrow;
2018 if (ifbody)
2019 result |= ifbody->blockExit();
2020 else
2021 result |= BEfallthru;
2022 if (elsebody)
2023 result |= elsebody->blockExit();
2024 else
2025 result |= BEfallthru;
2026 //printf("IfStatement::blockExit(%p) = x%x\n", this, result);
2027 return result;
2030 int IfStatement::fallOffEnd()
2032 if (!ifbody || ifbody->fallOffEnd() ||
2033 !elsebody || elsebody->fallOffEnd())
2034 return TRUE;
2035 return FALSE;
2039 void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2041 buf->writestring("if (");
2042 if (arg)
2044 if (arg->type)
2045 arg->type->toCBuffer(buf, arg->ident, hgs);
2046 else
2047 buf->writestring(arg->ident->toChars());
2048 buf->writebyte(';');
2050 condition->toCBuffer(buf, hgs);
2051 buf->writebyte(')');
2052 buf->writenl();
2053 ifbody->toCBuffer(buf, hgs);
2054 if (elsebody)
2055 { buf->writestring("else");
2056 buf->writenl();
2057 elsebody->toCBuffer(buf, hgs);
2061 /******************************** ConditionalStatement ***************************/
2063 ConditionalStatement::ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody)
2064 : Statement(loc)
2066 this->condition = condition;
2067 this->ifbody = ifbody;
2068 this->elsebody = elsebody;
2071 Statement *ConditionalStatement::syntaxCopy()
2073 Statement *e = NULL;
2074 if (elsebody)
2075 e = elsebody->syntaxCopy();
2076 ConditionalStatement *s = new ConditionalStatement(loc,
2077 condition->syntaxCopy(), ifbody->syntaxCopy(), e);
2078 return s;
2081 Statement *ConditionalStatement::semantic(Scope *sc)
2083 //printf("ConditionalStatement::semantic()\n");
2085 // If we can short-circuit evaluate the if statement, don't do the
2086 // semantic analysis of the skipped code.
2087 // This feature allows a limited form of conditional compilation.
2088 if (condition->include(sc, NULL))
2090 ifbody = ifbody->semantic(sc);
2091 return ifbody;
2093 else
2095 if (elsebody)
2096 elsebody = elsebody->semantic(sc);
2097 return elsebody;
2101 Statements *ConditionalStatement::flatten(Scope *sc)
2103 Statement *s;
2105 if (condition->include(sc, NULL))
2106 s = ifbody;
2107 else
2108 s = elsebody;
2110 Statements *a = new Statements();
2111 a->push(s);
2112 return a;
2115 int ConditionalStatement::usesEH()
2117 return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH());
2120 void ConditionalStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2122 condition->toCBuffer(buf, hgs);
2123 buf->writenl();
2124 if (ifbody)
2125 ifbody->toCBuffer(buf, hgs);
2126 if (elsebody)
2128 buf->writestring("else");
2129 buf->writenl();
2130 elsebody->toCBuffer(buf, hgs);
2132 buf->writenl();
2136 /******************************** PragmaStatement ***************************/
2138 PragmaStatement::PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body)
2139 : Statement(loc)
2141 this->ident = ident;
2142 this->args = args;
2143 this->body = body;
2146 Statement *PragmaStatement::syntaxCopy()
2148 Statement *b = NULL;
2149 if (body)
2150 b = body->syntaxCopy();
2151 PragmaStatement *s = new PragmaStatement(loc,
2152 ident, Expression::arraySyntaxCopy(args), b);
2153 return s;
2156 Statement *PragmaStatement::semantic(Scope *sc)
2157 { // Should be merged with PragmaDeclaration
2158 //printf("PragmaStatement::semantic() %s\n", toChars());
2159 //printf("body = %p\n", body);
2160 if (ident == Id::msg)
2162 if (args)
2164 for (size_t i = 0; i < args->dim; i++)
2166 Expression *e = (Expression *)args->data[i];
2168 e = e->semantic(sc);
2169 e = e->optimize(WANTvalue | WANTinterpret);
2170 if (e->op == TOKstring)
2172 StringExp *se = (StringExp *)e;
2173 fprintf(stdmsg, "%.*s", (int)se->len, se->string);
2175 else
2176 error("string expected for message, not '%s'", e->toChars());
2178 fprintf(stdmsg, "\n");
2181 else if (ident == Id::lib)
2183 if (!args || args->dim != 1)
2184 error("string expected for library name");
2185 else
2187 Expression *e = (Expression *)args->data[0];
2189 e = e->semantic(sc);
2190 e = e->optimize(WANTvalue | WANTinterpret);
2191 args->data[0] = (void *)e;
2192 if (e->op != TOKstring)
2193 error("string expected for library name, not '%s'", e->toChars());
2194 else if (global.params.verbose)
2196 StringExp *se = (StringExp *)e;
2197 char *name = (char *)mem.malloc(se->len + 1);
2198 memcpy(name, se->string, se->len);
2199 name[se->len] = 0;
2200 printf("library %s\n", name);
2201 mem.free(name);
2205 else if (ident == Id::startaddress)
2207 if (!args || args->dim != 1)
2208 error("function name expected for start address");
2209 else
2211 Expression *e = (Expression *)args->data[0];
2212 e = e->semantic(sc);
2213 e = e->optimize(WANTvalue | WANTinterpret);
2214 args->data[0] = (void *)e;
2215 Dsymbol *sa = getDsymbol(e);
2216 if (!sa || !sa->isFuncDeclaration())
2217 error("function name expected for start address, not '%s'", e->toChars());
2218 if (body)
2220 body = body->semantic(sc);
2222 return this;
2225 else
2226 error("unrecognized pragma(%s)", ident->toChars());
2228 if (body)
2230 body = body->semantic(sc);
2232 return body;
2235 int PragmaStatement::usesEH()
2237 return body && body->usesEH();
2240 int PragmaStatement::blockExit()
2242 int result = BEfallthru;
2243 #if 0 // currently, no code is generated for Pragma's, so it's just fallthru
2244 if (arrayExpressionCanThrow(args))
2245 result |= BEthrow;
2246 if (body)
2247 result |= body->blockExit();
2248 #endif
2249 return result;
2252 int PragmaStatement::fallOffEnd()
2254 if (body)
2255 return body->fallOffEnd();
2256 return TRUE;
2259 void PragmaStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2261 buf->writestring("pragma (");
2262 buf->writestring(ident->toChars());
2263 if (args && args->dim)
2265 buf->writestring(", ");
2266 argsToCBuffer(buf, args, hgs);
2268 buf->writeByte(')');
2269 if (body)
2271 buf->writenl();
2272 buf->writeByte('{');
2273 buf->writenl();
2275 body->toCBuffer(buf, hgs);
2277 buf->writeByte('}');
2278 buf->writenl();
2280 else
2282 buf->writeByte(';');
2283 buf->writenl();
2288 /******************************** StaticAssertStatement ***************************/
2290 StaticAssertStatement::StaticAssertStatement(StaticAssert *sa)
2291 : Statement(sa->loc)
2293 this->sa = sa;
2296 Statement *StaticAssertStatement::syntaxCopy()
2298 StaticAssertStatement *s = new StaticAssertStatement((StaticAssert *)sa->syntaxCopy(NULL));
2299 return s;
2302 Statement *StaticAssertStatement::semantic(Scope *sc)
2304 sa->semantic2(sc);
2305 return NULL;
2308 void StaticAssertStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2310 sa->toCBuffer(buf, hgs);
2314 /******************************** SwitchStatement ***************************/
2316 SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b)
2317 : Statement(loc)
2319 condition = c;
2320 body = b;
2321 sdefault = NULL;
2322 tf = NULL;
2323 cases = NULL;
2324 hasNoDefault = 0;
2325 hasVars = 0;
2328 Statement *SwitchStatement::syntaxCopy()
2330 SwitchStatement *s = new SwitchStatement(loc,
2331 condition->syntaxCopy(), body->syntaxCopy());
2332 return s;
2335 Statement *SwitchStatement::semantic(Scope *sc)
2337 //printf("SwitchStatement::semantic(%p)\n", this);
2338 tf = sc->tf;
2339 assert(!cases); // ensure semantic() is only run once
2340 condition = condition->semantic(sc);
2341 condition = resolveProperties(sc, condition);
2342 if (condition->type->isString())
2344 // If it's not an array, cast it to one
2345 if (condition->type->ty != Tarray)
2347 condition = condition->implicitCastTo(sc, condition->type->nextOf()->arrayOf());
2349 condition->type = condition->type->constOf();
2351 else
2352 { condition = condition->integralPromotions(sc);
2353 condition->checkIntegral();
2355 condition = condition->optimize(WANTvalue);
2357 sc = sc->push();
2358 sc->sbreak = this;
2359 sc->sw = this;
2361 cases = new Array();
2362 sc->noctor++; // BUG: should use Scope::mergeCallSuper() for each case instead
2363 body = body->semantic(sc);
2364 sc->noctor--;
2366 // Resolve any goto case's with exp
2367 for (int i = 0; i < gotoCases.dim; i++)
2369 GotoCaseStatement *gcs = (GotoCaseStatement *)gotoCases.data[i];
2371 if (!gcs->exp)
2373 gcs->error("no case statement following goto case;");
2374 break;
2377 for (Scope *scx = sc; scx; scx = scx->enclosing)
2379 if (!scx->sw)
2380 continue;
2381 for (int j = 0; j < scx->sw->cases->dim; j++)
2383 CaseStatement *cs = (CaseStatement *)scx->sw->cases->data[j];
2385 if (cs->exp->equals(gcs->exp))
2387 gcs->cs = cs;
2388 goto Lfoundcase;
2392 gcs->error("case %s not found", gcs->exp->toChars());
2394 Lfoundcase:
2398 if (!sc->sw->sdefault)
2399 { hasNoDefault = 1;
2401 if (global.params.warnings)
2402 { fprintf(stdmsg, "warning - ");
2403 error("switch statement has no default");
2406 // Generate runtime error if the default is hit
2407 Statements *a = new Statements();
2408 CompoundStatement *cs;
2409 Statement *s;
2411 if (global.params.useSwitchError)
2412 s = new SwitchErrorStatement(loc);
2413 else
2414 { Expression *e = new HaltExp(loc);
2415 s = new ExpStatement(loc, e);
2418 a->reserve(4);
2419 a->push(body);
2420 a->push(new BreakStatement(loc, NULL));
2421 sc->sw->sdefault = new DefaultStatement(loc, s);
2422 a->push(sc->sw->sdefault);
2423 cs = new CompoundStatement(loc, a);
2424 body = cs;
2427 sc->pop();
2428 return this;
2431 int SwitchStatement::hasBreak()
2433 return TRUE;
2436 int SwitchStatement::usesEH()
2438 return body ? body->usesEH() : 0;
2441 int SwitchStatement::blockExit()
2442 { int result = BEnone;
2443 if (condition->canThrow())
2444 result |= BEthrow;
2446 if (body)
2447 { result |= body->blockExit();
2448 if (result & BEbreak)
2449 { result |= BEfallthru;
2450 result &= ~BEbreak;
2453 else
2454 result |= BEfallthru;
2456 return result;
2459 int SwitchStatement::fallOffEnd()
2461 if (body)
2462 body->fallOffEnd();
2463 return TRUE; // need to do this better
2466 void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2468 buf->writestring("switch (");
2469 condition->toCBuffer(buf, hgs);
2470 buf->writebyte(')');
2471 buf->writenl();
2472 if (body)
2474 if (!body->isScopeStatement())
2475 { buf->writebyte('{');
2476 buf->writenl();
2477 body->toCBuffer(buf, hgs);
2478 buf->writebyte('}');
2479 buf->writenl();
2481 else
2483 body->toCBuffer(buf, hgs);
2488 /******************************** CaseStatement ***************************/
2490 CaseStatement::CaseStatement(Loc loc, Expression *exp, Statement *s)
2491 : Statement(loc)
2493 this->exp = exp;
2494 this->statement = s;
2495 index = 0;
2496 cblock = NULL;
2499 Statement *CaseStatement::syntaxCopy()
2501 CaseStatement *s = new CaseStatement(loc, exp->syntaxCopy(), statement->syntaxCopy());
2502 return s;
2505 Statement *CaseStatement::semantic(Scope *sc)
2506 { SwitchStatement *sw = sc->sw;
2508 //printf("CaseStatement::semantic() %s\n", toChars());
2509 exp = exp->semantic(sc);
2510 if (sw)
2512 exp = exp->implicitCastTo(sc, sw->condition->type);
2513 exp = exp->optimize(WANTvalue | WANTinterpret);
2515 /* This is where variables are allowed as case expressions.
2517 if (exp->op == TOKvar)
2518 { VarExp *ve = (VarExp *)exp;
2519 VarDeclaration *v = ve->var->isVarDeclaration();
2520 Type *t = exp->type->toBasetype();
2521 if (v && (t->isintegral() || t->ty == Tclass))
2522 { /* Flag that we need to do special code generation
2523 * for this, i.e. generate a sequence of if-then-else
2525 sw->hasVars = 1;
2526 goto L1;
2530 if (exp->op != TOKstring && exp->op != TOKint64)
2532 error("case must be a string or an integral constant, not %s", exp->toChars());
2533 exp = new IntegerExp(0);
2537 for (int i = 0; i < sw->cases->dim; i++)
2539 CaseStatement *cs = (CaseStatement *)sw->cases->data[i];
2541 //printf("comparing '%s' with '%s'\n", exp->toChars(), cs->exp->toChars());
2542 if (cs->exp->equals(exp))
2543 { error("duplicate case %s in switch statement", exp->toChars());
2544 break;
2548 sw->cases->push(this);
2550 // Resolve any goto case's with no exp to this case statement
2551 for (int i = 0; i < sw->gotoCases.dim; i++)
2553 GotoCaseStatement *gcs = (GotoCaseStatement *)sw->gotoCases.data[i];
2555 if (!gcs->exp)
2557 gcs->cs = this;
2558 sw->gotoCases.remove(i); // remove from array
2562 if (sc->sw->tf != sc->tf)
2563 error("switch and case are in different finally blocks");
2565 else
2566 error("case not in switch statement");
2567 statement = statement->semantic(sc);
2568 return this;
2571 int CaseStatement::compare(Object *obj)
2573 // Sort cases so we can do an efficient lookup
2574 CaseStatement *cs2 = (CaseStatement *)(obj);
2576 return exp->compare(cs2->exp);
2579 int CaseStatement::usesEH()
2581 return statement->usesEH();
2584 int CaseStatement::blockExit()
2586 // Assume the worst
2587 return BEany;
2590 int CaseStatement::fallOffEnd()
2592 return statement->fallOffEnd();
2595 int CaseStatement::comeFrom()
2597 return TRUE;
2600 void CaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2602 buf->writestring("case ");
2603 exp->toCBuffer(buf, hgs);
2604 buf->writebyte(':');
2605 buf->writenl();
2606 statement->toCBuffer(buf, hgs);
2609 /******************************** DefaultStatement ***************************/
2611 DefaultStatement::DefaultStatement(Loc loc, Statement *s)
2612 : Statement(loc)
2614 this->statement = s;
2615 #if IN_GCC
2616 cblock = NULL;
2617 #endif
2620 Statement *DefaultStatement::syntaxCopy()
2622 DefaultStatement *s = new DefaultStatement(loc, statement->syntaxCopy());
2623 return s;
2626 Statement *DefaultStatement::semantic(Scope *sc)
2628 //printf("DefaultStatement::semantic()\n");
2629 if (sc->sw)
2631 if (sc->sw->sdefault)
2633 error("switch statement already has a default");
2635 sc->sw->sdefault = this;
2637 if (sc->sw->tf != sc->tf)
2638 error("switch and default are in different finally blocks");
2640 else
2641 error("default not in switch statement");
2642 statement = statement->semantic(sc);
2643 return this;
2646 int DefaultStatement::usesEH()
2648 return statement->usesEH();
2651 int DefaultStatement::blockExit()
2653 // Assume the worst
2654 return BEany;
2657 int DefaultStatement::fallOffEnd()
2659 return statement->fallOffEnd();
2662 int DefaultStatement::comeFrom()
2664 return TRUE;
2667 void DefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2669 buf->writestring("default:\n");
2670 statement->toCBuffer(buf, hgs);
2673 /******************************** GotoDefaultStatement ***************************/
2675 GotoDefaultStatement::GotoDefaultStatement(Loc loc)
2676 : Statement(loc)
2678 sw = NULL;
2681 Statement *GotoDefaultStatement::syntaxCopy()
2683 GotoDefaultStatement *s = new GotoDefaultStatement(loc);
2684 return s;
2687 Statement *GotoDefaultStatement::semantic(Scope *sc)
2689 sw = sc->sw;
2690 if (!sw)
2691 error("goto default not in switch statement");
2692 return this;
2695 int GotoDefaultStatement::blockExit()
2697 return BEgoto;
2700 int GotoDefaultStatement::fallOffEnd()
2702 return FALSE;
2705 void GotoDefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2707 buf->writestring("goto default;\n");
2710 /******************************** GotoCaseStatement ***************************/
2712 GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp)
2713 : Statement(loc)
2715 cs = NULL;
2716 this->exp = exp;
2719 Statement *GotoCaseStatement::syntaxCopy()
2721 Expression *e = exp ? exp->syntaxCopy() : NULL;
2722 GotoCaseStatement *s = new GotoCaseStatement(loc, e);
2723 return s;
2726 Statement *GotoCaseStatement::semantic(Scope *sc)
2728 if (exp)
2729 exp = exp->semantic(sc);
2731 if (!sc->sw)
2732 error("goto case not in switch statement");
2733 else
2735 sc->sw->gotoCases.push(this);
2736 if (exp)
2738 exp = exp->implicitCastTo(sc, sc->sw->condition->type);
2739 exp = exp->optimize(WANTvalue);
2742 return this;
2745 int GotoCaseStatement::blockExit()
2747 return BEgoto;
2750 int GotoCaseStatement::fallOffEnd()
2752 return FALSE;
2755 void GotoCaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2757 buf->writestring("goto case");
2758 if (exp)
2759 { buf->writebyte(' ');
2760 exp->toCBuffer(buf, hgs);
2762 buf->writebyte(';');
2763 buf->writenl();
2766 /******************************** SwitchErrorStatement ***************************/
2768 SwitchErrorStatement::SwitchErrorStatement(Loc loc)
2769 : Statement(loc)
2773 int SwitchErrorStatement::blockExit()
2775 return BEthrow;
2778 int SwitchErrorStatement::fallOffEnd()
2780 return FALSE;
2783 void SwitchErrorStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2785 buf->writestring("SwitchErrorStatement::toCBuffer()");
2786 buf->writenl();
2789 /******************************** ReturnStatement ***************************/
2791 ReturnStatement::ReturnStatement(Loc loc, Expression *exp)
2792 : Statement(loc)
2794 this->exp = exp;
2797 Statement *ReturnStatement::syntaxCopy()
2799 Expression *e = NULL;
2800 if (exp)
2801 e = exp->syntaxCopy();
2802 ReturnStatement *s = new ReturnStatement(loc, e);
2803 return s;
2806 Statement *ReturnStatement::semantic(Scope *sc)
2808 //printf("ReturnStatement::semantic() %s\n", toChars());
2810 FuncDeclaration *fd = sc->parent->isFuncDeclaration();
2811 Scope *scx = sc;
2812 int implicit0 = 0;
2814 if (sc->fes)
2816 // Find scope of function foreach is in
2817 for (; 1; scx = scx->enclosing)
2819 assert(scx);
2820 if (scx->func != fd)
2821 { fd = scx->func; // fd is now function enclosing foreach
2822 break;
2827 Type *tret = fd->type->nextOf();
2828 if (fd->tintro)
2829 tret = fd->tintro->nextOf();
2830 Type *tbret = NULL;
2832 if (tret)
2833 tbret = tret->toBasetype();
2835 // main() returns 0, even if it returns void
2836 if (!exp && (!tbret || tbret->ty == Tvoid) && fd->isMain())
2837 { implicit0 = 1;
2838 exp = new IntegerExp(0);
2841 if (sc->incontract || scx->incontract)
2842 error("return statements cannot be in contracts");
2843 if (sc->tf || scx->tf)
2844 error("return statements cannot be in finally, scope(exit) or scope(success) bodies");
2846 if (fd->isCtorDeclaration())
2848 // Constructors implicitly do:
2849 // return this;
2850 if (exp && exp->op != TOKthis)
2851 error("cannot return expression from constructor");
2852 exp = new ThisExp(0);
2855 if (!exp)
2856 fd->nrvo_can = 0;
2858 if (exp)
2860 fd->hasReturnExp |= 1;
2862 exp = exp->semantic(sc);
2863 exp = resolveProperties(sc, exp);
2864 exp = exp->optimize(WANTvalue);
2866 if (fd->nrvo_can && exp->op == TOKvar)
2867 { VarExp *ve = (VarExp *)exp;
2868 VarDeclaration *v = ve->var->isVarDeclaration();
2870 if (!v || v->isOut() || v->isRef())
2871 fd->nrvo_can = 0;
2872 else if (tbret->ty == Tstruct && ((TypeStruct *)tbret)->sym->dtor)
2873 // Struct being returned has destructors
2874 fd->nrvo_can = 0;
2875 else if (fd->nrvo_var == NULL)
2876 { if (!v->isDataseg() && !v->isParameter() && v->toParent2() == fd)
2877 { //printf("Setting nrvo to %s\n", v->toChars());
2878 fd->nrvo_var = v;
2880 else
2881 fd->nrvo_can = 0;
2883 else if (fd->nrvo_var != v)
2884 fd->nrvo_can = 0;
2886 else
2887 fd->nrvo_can = 0;
2889 if (fd->returnLabel && tbret->ty != Tvoid)
2892 else if (fd->inferRetType)
2894 if (fd->type->nextOf())
2896 if (!exp->type->equals(fd->type->nextOf()))
2897 error("mismatched function return type inference of %s and %s",
2898 exp->type->toChars(), fd->type->nextOf()->toChars());
2900 else
2902 ((TypeFunction *)fd->type)->next = exp->type;
2903 fd->type = fd->type->semantic(loc, sc);
2904 if (!fd->tintro)
2905 { tret = fd->type->nextOf();
2906 tbret = tret->toBasetype();
2910 else if (tbret->ty != Tvoid)
2912 exp = exp->implicitCastTo(sc, tret);
2915 else if (fd->inferRetType)
2917 if (fd->type->nextOf())
2919 if (fd->type->nextOf()->ty != Tvoid)
2920 error("mismatched function return type inference of void and %s",
2921 fd->type->nextOf()->toChars());
2923 else
2925 ((TypeFunction *)fd->type)->next = Type::tvoid;
2926 fd->type = fd->type->semantic(loc, sc);
2927 if (!fd->tintro)
2928 { tret = Type::tvoid;
2929 tbret = tret;
2933 else if (tbret->ty != Tvoid) // if non-void return
2934 error("return expression expected");
2936 if (sc->fes)
2938 Statement *s;
2940 if (exp && !implicit0)
2942 exp = exp->implicitCastTo(sc, tret);
2944 if (!exp || exp->op == TOKint64 || exp->op == TOKfloat64 ||
2945 exp->op == TOKimaginary80 || exp->op == TOKcomplex80 ||
2946 exp->op == TOKthis || exp->op == TOKsuper || exp->op == TOKnull ||
2947 exp->op == TOKstring)
2949 sc->fes->cases.push(this);
2950 s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
2952 else if (fd->type->nextOf()->toBasetype() == Type::tvoid)
2954 Statement *s1;
2955 Statement *s2;
2957 s = new ReturnStatement(0, NULL);
2958 sc->fes->cases.push(s);
2960 // Construct: { exp; return cases.dim + 1; }
2961 s1 = new ExpStatement(loc, exp);
2962 s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
2963 s = new CompoundStatement(loc, s1, s2);
2965 else
2967 VarExp *v;
2968 Statement *s1;
2969 Statement *s2;
2971 // Construct: return vresult;
2972 if (!fd->vresult)
2973 { VarDeclaration *v;
2975 v = new VarDeclaration(loc, tret, Id::result, NULL);
2976 v->noauto = 1;
2977 v->semantic(scx);
2978 if (!scx->insert(v))
2979 assert(0);
2980 v->parent = fd;
2981 fd->vresult = v;
2984 v = new VarExp(0, fd->vresult);
2985 s = new ReturnStatement(0, v);
2986 sc->fes->cases.push(s);
2988 // Construct: { vresult = exp; return cases.dim + 1; }
2989 v = new VarExp(0, fd->vresult);
2990 exp = new AssignExp(loc, v, exp);
2991 exp = exp->semantic(sc);
2992 s1 = new ExpStatement(loc, exp);
2993 s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
2994 s = new CompoundStatement(loc, s1, s2);
2996 return s;
2999 if (exp)
3001 if (fd->returnLabel && tbret->ty != Tvoid)
3003 assert(fd->vresult);
3004 VarExp *v = new VarExp(0, fd->vresult);
3006 exp = new AssignExp(loc, v, exp);
3007 exp = exp->semantic(sc);
3009 //exp->dump(0);
3010 //exp->print();
3011 exp->checkEscape();
3014 /* BUG: need to issue an error on:
3015 * this
3016 * { if (x) return;
3017 * super();
3021 if (sc->callSuper & CSXany_ctor &&
3022 !(sc->callSuper & (CSXthis_ctor | CSXsuper_ctor)))
3023 error("return without calling constructor");
3025 sc->callSuper |= CSXreturn;
3027 // See if all returns are instead to be replaced with a goto returnLabel;
3028 if (fd->returnLabel)
3030 GotoStatement *gs = new GotoStatement(loc, Id::returnLabel);
3032 gs->label = fd->returnLabel;
3033 if (exp)
3034 { Statement *s;
3036 s = new ExpStatement(0, exp);
3037 return new CompoundStatement(loc, s, gs);
3039 return gs;
3042 if (exp && tbret->ty == Tvoid && !fd->isMain())
3043 { Statement *s;
3045 s = new ExpStatement(loc, exp);
3046 loc = 0;
3047 exp = NULL;
3048 return new CompoundStatement(loc, s, this);
3051 return this;
3054 int ReturnStatement::blockExit()
3055 { int result = BEreturn;
3057 if (exp && exp->canThrow())
3058 result |= BEthrow;
3059 return result;
3062 int ReturnStatement::fallOffEnd()
3064 return FALSE;
3067 void ReturnStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3069 buf->printf("return ");
3070 if (exp)
3071 exp->toCBuffer(buf, hgs);
3072 buf->writeByte(';');
3073 buf->writenl();
3076 /******************************** BreakStatement ***************************/
3078 BreakStatement::BreakStatement(Loc loc, Identifier *ident)
3079 : Statement(loc)
3081 this->ident = ident;
3084 Statement *BreakStatement::syntaxCopy()
3086 BreakStatement *s = new BreakStatement(loc, ident);
3087 return s;
3090 Statement *BreakStatement::semantic(Scope *sc)
3092 //printf("BreakStatement::semantic()\n");
3093 // If:
3094 // break Identifier;
3095 if (ident)
3097 Scope *scx;
3098 FuncDeclaration *thisfunc = sc->func;
3100 for (scx = sc; scx; scx = scx->enclosing)
3102 LabelStatement *ls;
3104 if (scx->func != thisfunc) // if in enclosing function
3106 if (sc->fes) // if this is the body of a foreach
3108 /* Post this statement to the fes, and replace
3109 * it with a return value that caller will put into
3110 * a switch. Caller will figure out where the break
3111 * label actually is.
3112 * Case numbers start with 2, not 0, as 0 is continue
3113 * and 1 is break.
3115 Statement *s;
3116 sc->fes->cases.push(this);
3117 s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
3118 return s;
3120 break; // can't break to it
3123 ls = scx->slabel;
3124 if (ls && ls->ident == ident)
3126 Statement *s = ls->statement;
3128 if (!s->hasBreak())
3129 error("label '%s' has no break", ident->toChars());
3130 if (ls->tf != sc->tf)
3131 error("cannot break out of finally block");
3132 return this;
3135 error("enclosing label '%s' for break not found", ident->toChars());
3137 else if (!sc->sbreak)
3139 if (sc->fes)
3140 { Statement *s;
3142 // Replace break; with return 1;
3143 s = new ReturnStatement(0, new IntegerExp(1));
3144 return s;
3146 error("break is not inside a loop or switch");
3148 return this;
3151 int BreakStatement::blockExit()
3153 //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak);
3154 return ident ? BEgoto : BEbreak;
3157 int BreakStatement::fallOffEnd()
3159 return FALSE;
3162 void BreakStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3164 buf->writestring("break");
3165 if (ident)
3166 { buf->writebyte(' ');
3167 buf->writestring(ident->toChars());
3169 buf->writebyte(';');
3170 buf->writenl();
3173 /******************************** ContinueStatement ***************************/
3175 ContinueStatement::ContinueStatement(Loc loc, Identifier *ident)
3176 : Statement(loc)
3178 this->ident = ident;
3181 Statement *ContinueStatement::syntaxCopy()
3183 ContinueStatement *s = new ContinueStatement(loc, ident);
3184 return s;
3187 Statement *ContinueStatement::semantic(Scope *sc)
3189 //printf("ContinueStatement::semantic() %p\n", this);
3190 if (ident)
3192 Scope *scx;
3193 FuncDeclaration *thisfunc = sc->func;
3195 for (scx = sc; scx; scx = scx->enclosing)
3197 LabelStatement *ls;
3199 if (scx->func != thisfunc) // if in enclosing function
3201 if (sc->fes) // if this is the body of a foreach
3203 for (; scx; scx = scx->enclosing)
3205 ls = scx->slabel;
3206 if (ls && ls->ident == ident && ls->statement == sc->fes)
3208 // Replace continue ident; with return 0;
3209 return new ReturnStatement(0, new IntegerExp(0));
3213 /* Post this statement to the fes, and replace
3214 * it with a return value that caller will put into
3215 * a switch. Caller will figure out where the break
3216 * label actually is.
3217 * Case numbers start with 2, not 0, as 0 is continue
3218 * and 1 is break.
3220 Statement *s;
3221 sc->fes->cases.push(this);
3222 s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
3223 return s;
3225 break; // can't continue to it
3228 ls = scx->slabel;
3229 if (ls && ls->ident == ident)
3231 Statement *s = ls->statement;
3233 if (!s->hasContinue())
3234 error("label '%s' has no continue", ident->toChars());
3235 if (ls->tf != sc->tf)
3236 error("cannot continue out of finally block");
3237 return this;
3240 error("enclosing label '%s' for continue not found", ident->toChars());
3242 else if (!sc->scontinue)
3244 if (sc->fes)
3245 { Statement *s;
3247 // Replace continue; with return 0;
3248 s = new ReturnStatement(0, new IntegerExp(0));
3249 return s;
3251 error("continue is not inside a loop");
3253 return this;
3256 int ContinueStatement::blockExit()
3258 return ident ? BEgoto : BEcontinue;
3261 int ContinueStatement::fallOffEnd()
3263 return FALSE;
3266 void ContinueStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3268 buf->writestring("continue");
3269 if (ident)
3270 { buf->writebyte(' ');
3271 buf->writestring(ident->toChars());
3273 buf->writebyte(';');
3274 buf->writenl();
3277 /******************************** SynchronizedStatement ***************************/
3279 SynchronizedStatement::SynchronizedStatement(Loc loc, Expression *exp, Statement *body)
3280 : Statement(loc)
3282 this->exp = exp;
3283 this->body = body;
3284 this->esync = NULL;
3287 SynchronizedStatement::SynchronizedStatement(Loc loc, elem *esync, Statement *body)
3288 : Statement(loc)
3290 this->exp = NULL;
3291 this->body = body;
3292 this->esync = esync;
3295 Statement *SynchronizedStatement::syntaxCopy()
3297 Expression *e = exp ? exp->syntaxCopy() : NULL;
3298 SynchronizedStatement *s = new SynchronizedStatement(loc, e, body ? body->syntaxCopy() : NULL);
3299 return s;
3302 Statement *SynchronizedStatement::semantic(Scope *sc)
3304 if (exp)
3305 { ClassDeclaration *cd;
3307 exp = exp->semantic(sc);
3308 exp = resolveProperties(sc, exp);
3309 cd = exp->type->isClassHandle();
3310 if (!cd)
3311 error("can only synchronize on class objects, not '%s'", exp->type->toChars());
3312 else if (cd->isInterfaceDeclaration())
3313 { Type *t = new TypeIdentifier(0, Id::Object);
3315 t = t->semantic(0, sc);
3316 exp = new CastExp(loc, exp, t);
3317 exp = exp->semantic(sc);
3320 if (body)
3321 body = body->semantic(sc);
3322 return this;
3325 int SynchronizedStatement::hasBreak()
3327 return FALSE; //TRUE;
3330 int SynchronizedStatement::hasContinue()
3332 return FALSE; //TRUE;
3335 int SynchronizedStatement::usesEH()
3337 return TRUE;
3340 int SynchronizedStatement::blockExit()
3342 return body ? body->blockExit() : BEfallthru;
3345 int SynchronizedStatement::fallOffEnd()
3347 return body ? body->fallOffEnd() : TRUE;
3350 void SynchronizedStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3352 buf->writestring("synchronized");
3353 if (exp)
3354 { buf->writebyte('(');
3355 exp->toCBuffer(buf, hgs);
3356 buf->writebyte(')');
3358 if (body)
3360 buf->writebyte(' ');
3361 body->toCBuffer(buf, hgs);
3365 /******************************** WithStatement ***************************/
3367 WithStatement::WithStatement(Loc loc, Expression *exp, Statement *body)
3368 : Statement(loc)
3370 this->exp = exp;
3371 this->body = body;
3372 wthis = NULL;
3375 Statement *WithStatement::syntaxCopy()
3377 WithStatement *s = new WithStatement(loc, exp->syntaxCopy(), body ? body->syntaxCopy() : NULL);
3378 return s;
3381 Statement *WithStatement::semantic(Scope *sc)
3382 { ScopeDsymbol *sym;
3383 Initializer *init;
3385 //printf("WithStatement::semantic()\n");
3386 exp = exp->semantic(sc);
3387 exp = resolveProperties(sc, exp);
3388 if (exp->op == TOKimport)
3389 { ScopeExp *es = (ScopeExp *)exp;
3391 sym = es->sds;
3393 else if (exp->op == TOKtype)
3394 { TypeExp *es = (TypeExp *)exp;
3396 sym = es->type->toDsymbol(sc)->isScopeDsymbol();
3397 if (!sym)
3398 { error("%s has no members", es->toChars());
3399 body = body->semantic(sc);
3400 return this;
3403 else
3404 { Type *t = exp->type;
3406 assert(t);
3407 t = t->toBasetype();
3408 if (t->isClassHandle())
3410 init = new ExpInitializer(loc, exp);
3411 wthis = new VarDeclaration(loc, exp->type, Id::withSym, init);
3412 wthis->semantic(sc);
3414 sym = new WithScopeSymbol(this);
3415 sym->parent = sc->scopesym;
3417 else if (t->ty == Tstruct)
3419 Expression *e = exp->addressOf(sc);
3420 init = new ExpInitializer(loc, e);
3421 wthis = new VarDeclaration(loc, e->type, Id::withSym, init);
3422 wthis->semantic(sc);
3423 sym = new WithScopeSymbol(this);
3424 sym->parent = sc->scopesym;
3426 else
3427 { error("with expressions must be class objects, not '%s'", exp->type->toChars());
3428 return NULL;
3431 sc = sc->push(sym);
3433 if (body)
3434 body = body->semantic(sc);
3436 sc->pop();
3438 return this;
3441 void WithStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3443 buf->writestring("with (");
3444 exp->toCBuffer(buf, hgs);
3445 buf->writestring(")\n");
3446 if (body)
3447 body->toCBuffer(buf, hgs);
3450 int WithStatement::usesEH()
3452 return body ? body->usesEH() : 0;
3455 int WithStatement::blockExit()
3457 int result = BEnone;
3458 if (exp->canThrow())
3459 result = BEthrow;
3460 if (body)
3461 result |= body->blockExit();
3462 else
3463 result |= BEfallthru;
3464 return result;
3467 int WithStatement::fallOffEnd()
3469 return body ? body->fallOffEnd() : TRUE;
3472 /******************************** TryCatchStatement ***************************/
3474 TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Array *catches)
3475 : Statement(loc)
3477 this->body = body;
3478 this->catches = catches;
3481 Statement *TryCatchStatement::syntaxCopy()
3483 Array *a = new Array();
3484 a->setDim(catches->dim);
3485 for (int i = 0; i < a->dim; i++)
3486 { Catch *c;
3488 c = (Catch *)catches->data[i];
3489 c = c->syntaxCopy();
3490 a->data[i] = c;
3492 TryCatchStatement *s = new TryCatchStatement(loc, body->syntaxCopy(), a);
3493 return s;
3496 Statement *TryCatchStatement::semantic(Scope *sc)
3498 body = body->semanticScope(sc, NULL /*this*/, NULL);
3500 /* Even if body is NULL, still do semantic analysis on catches
3502 for (size_t i = 0; i < catches->dim; i++)
3503 { Catch *c = (Catch *)catches->data[i];
3504 c->semantic(sc);
3506 // Determine if current catch 'hides' any previous catches
3507 for (size_t j = 0; j < i; j++)
3508 { Catch *cj = (Catch *)catches->data[j];
3509 char *si = c->loc.toChars();
3510 char *sj = cj->loc.toChars();
3512 if (c->type->toBasetype()->implicitConvTo(cj->type->toBasetype()))
3513 error("catch at %s hides catch at %s", sj, si);
3517 if (!body)
3518 return NULL;
3520 return this;
3523 int TryCatchStatement::hasBreak()
3525 return FALSE; //TRUE;
3528 int TryCatchStatement::usesEH()
3530 return TRUE;
3533 int TryCatchStatement::blockExit()
3534 { int result;
3536 assert(body);
3537 result = body->blockExit();
3539 for (size_t i = 0; i < catches->dim; i++)
3541 Catch *c = (Catch *)catches->data[i];
3542 result |= c->blockExit();
3544 return result;
3547 int TryCatchStatement::fallOffEnd()
3549 int result = FALSE;
3551 if (body)
3552 result = body->fallOffEnd();
3553 for (int i = 0; i < catches->dim; i++)
3554 { Catch *c;
3556 c = (Catch *)catches->data[i];
3557 if (c->handler)
3558 result |= c->handler->fallOffEnd();
3560 return result;
3563 void TryCatchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3565 buf->writestring("try");
3566 buf->writenl();
3567 if (body)
3568 body->toCBuffer(buf, hgs);
3569 for (size_t i = 0; i < catches->dim; i++)
3571 Catch *c = (Catch *)catches->data[i];
3572 c->toCBuffer(buf, hgs);
3576 /******************************** Catch ***************************/
3578 Catch::Catch(Loc loc, Type *t, Identifier *id, Statement *handler)
3580 //printf("Catch(%s, loc = %s)\n", id->toChars(), loc.toChars());
3581 this->loc = loc;
3582 this->type = t;
3583 this->ident = id;
3584 this->handler = handler;
3585 var = NULL;
3588 Catch *Catch::syntaxCopy()
3590 Catch *c = new Catch(loc,
3591 (type ? type->syntaxCopy() : NULL),
3592 ident,
3593 (handler ? handler->syntaxCopy() : NULL));
3594 return c;
3597 void Catch::semantic(Scope *sc)
3598 { ScopeDsymbol *sym;
3600 //printf("Catch::semantic(%s)\n", ident->toChars());
3602 #ifndef IN_GCC
3603 if (sc->tf)
3605 /* This is because the _d_local_unwind() gets the stack munged
3606 * up on this. The workaround is to place any try-catches into
3607 * a separate function, and call that.
3608 * To fix, have the compiler automatically convert the finally
3609 * body into a nested function.
3611 error(loc, "cannot put catch statement inside finally block");
3613 #endif
3615 sym = new ScopeDsymbol();
3616 sym->parent = sc->scopesym;
3617 sc = sc->push(sym);
3619 if (!type)
3620 type = new TypeIdentifier(0, Id::Object);
3621 type = type->semantic(loc, sc);
3622 if (!type->toBasetype()->isClassHandle())
3623 error("can only catch class objects, not '%s'", type->toChars());
3624 else if (ident)
3626 var = new VarDeclaration(loc, type, ident, NULL);
3627 var->parent = sc->parent;
3628 sc->insert(var);
3630 handler = handler->semantic(sc);
3632 sc->pop();
3635 int Catch::blockExit()
3637 return handler ? handler->blockExit() : BEfallthru;
3640 void Catch::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3642 buf->writestring("catch");
3643 if (type)
3644 { buf->writebyte('(');
3645 type->toCBuffer(buf, ident, hgs);
3646 buf->writebyte(')');
3648 buf->writenl();
3649 buf->writebyte('{');
3650 buf->writenl();
3651 if (handler)
3652 handler->toCBuffer(buf, hgs);
3653 buf->writebyte('}');
3654 buf->writenl();
3657 /****************************** TryFinallyStatement ***************************/
3659 TryFinallyStatement::TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody)
3660 : Statement(loc)
3662 this->body = body;
3663 this->finalbody = finalbody;
3666 Statement *TryFinallyStatement::syntaxCopy()
3668 TryFinallyStatement *s = new TryFinallyStatement(loc,
3669 body->syntaxCopy(), finalbody->syntaxCopy());
3670 return s;
3673 Statement *TryFinallyStatement::semantic(Scope *sc)
3675 //printf("TryFinallyStatement::semantic()\n");
3676 body = body->semantic(sc);
3677 sc = sc->push();
3678 sc->tf = this;
3679 sc->sbreak = NULL;
3680 sc->scontinue = NULL; // no break or continue out of finally block
3681 finalbody = finalbody->semantic(sc);
3682 sc->pop();
3683 if (!body)
3684 return finalbody;
3685 if (!finalbody)
3686 return body;
3687 if (body->blockExit() == BEfallthru)
3688 { Statement *s = new CompoundStatement(loc, body, finalbody);
3689 return s;
3691 return this;
3694 void TryFinallyStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3696 buf->printf("try\n{\n");
3697 body->toCBuffer(buf, hgs);
3698 buf->printf("}\nfinally\n{\n");
3699 finalbody->toCBuffer(buf, hgs);
3700 buf->writeByte('}');
3701 buf->writenl();
3704 int TryFinallyStatement::hasBreak()
3706 return FALSE; //TRUE;
3709 int TryFinallyStatement::hasContinue()
3711 return FALSE; //TRUE;
3714 int TryFinallyStatement::usesEH()
3716 return TRUE;
3719 int TryFinallyStatement::blockExit()
3721 int result = body->blockExit();
3722 return result;
3725 int TryFinallyStatement::fallOffEnd()
3726 { int result;
3728 result = body->fallOffEnd();
3729 // if (finalbody)
3730 // result = finalbody->fallOffEnd();
3731 return result;
3734 /****************************** OnScopeStatement ***************************/
3736 OnScopeStatement::OnScopeStatement(Loc loc, TOK tok, Statement *statement)
3737 : Statement(loc)
3739 this->tok = tok;
3740 this->statement = statement;
3743 Statement *OnScopeStatement::syntaxCopy()
3745 OnScopeStatement *s = new OnScopeStatement(loc,
3746 tok, statement->syntaxCopy());
3747 return s;
3750 Statement *OnScopeStatement::semantic(Scope *sc)
3752 /* semantic is called on results of scopeCode() */
3753 return this;
3756 int OnScopeStatement::blockExit()
3757 { // At this point, this statement is just an empty placeholder
3758 return BEfallthru;
3761 void OnScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3763 buf->writestring(Token::toChars(tok));
3764 buf->writebyte(' ');
3765 statement->toCBuffer(buf, hgs);
3768 int OnScopeStatement::usesEH()
3770 return 1;
3773 void OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
3775 //printf("OnScopeStatement::scopeCode()\n");
3776 //print();
3777 *sentry = NULL;
3778 *sexception = NULL;
3779 *sfinally = NULL;
3780 switch (tok)
3782 case TOKon_scope_exit:
3783 *sfinally = statement;
3784 break;
3786 case TOKon_scope_failure:
3787 *sexception = statement;
3788 break;
3790 case TOKon_scope_success:
3792 /* Create:
3793 * sentry: int x = 0;
3794 * sexception: x = 1;
3795 * sfinally: if (!x) statement;
3797 Identifier *id = Lexer::uniqueId("__os");
3799 ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(0));
3800 VarDeclaration *v = new VarDeclaration(loc, Type::tint32, id, ie);
3801 *sentry = new DeclarationStatement(loc, v);
3803 Expression *e = new IntegerExp(1);
3804 e = new AssignExp(0, new VarExp(0, v), e);
3805 *sexception = new ExpStatement(0, e);
3807 e = new VarExp(0, v);
3808 e = new NotExp(0, e);
3809 *sfinally = new IfStatement(0, NULL, e, statement, NULL);
3811 break;
3814 default:
3815 assert(0);
3819 /******************************** ThrowStatement ***************************/
3821 ThrowStatement::ThrowStatement(Loc loc, Expression *exp)
3822 : Statement(loc)
3824 this->exp = exp;
3827 Statement *ThrowStatement::syntaxCopy()
3829 ThrowStatement *s = new ThrowStatement(loc, exp->syntaxCopy());
3830 return s;
3833 Statement *ThrowStatement::semantic(Scope *sc)
3835 //printf("ThrowStatement::semantic()\n");
3837 FuncDeclaration *fd = sc->parent->isFuncDeclaration();
3838 fd->hasReturnExp |= 2;
3840 if (sc->incontract)
3841 error("Throw statements cannot be in contracts");
3842 exp = exp->semantic(sc);
3843 exp = resolveProperties(sc, exp);
3844 if (!exp->type->toBasetype()->isClassHandle())
3845 error("can only throw class objects, not type %s", exp->type->toChars());
3846 return this;
3849 int ThrowStatement::blockExit()
3851 return BEthrow; // obviously
3854 int ThrowStatement::fallOffEnd()
3856 return FALSE;
3859 void ThrowStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3861 buf->printf("throw ");
3862 exp->toCBuffer(buf, hgs);
3863 buf->writeByte(';');
3864 buf->writenl();
3867 /******************************** VolatileStatement **************************/
3869 VolatileStatement::VolatileStatement(Loc loc, Statement *statement)
3870 : Statement(loc)
3872 this->statement = statement;
3875 Statement *VolatileStatement::syntaxCopy()
3877 VolatileStatement *s = new VolatileStatement(loc,
3878 statement ? statement->syntaxCopy() : NULL);
3879 return s;
3882 Statement *VolatileStatement::semantic(Scope *sc)
3884 if (statement)
3885 statement = statement->semantic(sc);
3886 return this;
3889 Statements *VolatileStatement::flatten(Scope *sc)
3891 Statements *a;
3893 a = statement ? statement->flatten(sc) : NULL;
3894 if (a)
3895 { for (int i = 0; i < a->dim; i++)
3896 { Statement *s = (Statement *)a->data[i];
3898 s = new VolatileStatement(loc, s);
3899 a->data[i] = s;
3903 return a;
3906 int VolatileStatement::blockExit()
3908 return statement ? statement->blockExit() : BEfallthru;
3911 int VolatileStatement::fallOffEnd()
3913 return statement ? statement->fallOffEnd() : TRUE;
3916 void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3918 buf->writestring("volatile");
3919 if (statement)
3920 { if (statement->isScopeStatement())
3921 buf->writenl();
3922 else
3923 buf->writebyte(' ');
3924 statement->toCBuffer(buf, hgs);
3929 /******************************** GotoStatement ***************************/
3931 GotoStatement::GotoStatement(Loc loc, Identifier *ident)
3932 : Statement(loc)
3934 this->ident = ident;
3935 this->label = NULL;
3936 this->tf = NULL;
3939 Statement *GotoStatement::syntaxCopy()
3941 GotoStatement *s = new GotoStatement(loc, ident);
3942 return s;
3945 Statement *GotoStatement::semantic(Scope *sc)
3946 { FuncDeclaration *fd = sc->parent->isFuncDeclaration();
3948 //printf("GotoStatement::semantic()\n");
3949 tf = sc->tf;
3950 label = fd->searchLabel(ident);
3951 if (!label->statement && sc->fes)
3953 /* Either the goto label is forward referenced or it
3954 * is in the function that the enclosing foreach is in.
3955 * Can't know yet, so wrap the goto in a compound statement
3956 * so we can patch it later, and add it to a 'look at this later'
3957 * list.
3959 Statements *a = new Statements();
3960 Statement *s;
3962 a->push(this);
3963 s = new CompoundStatement(loc, a);
3964 sc->fes->gotos.push(s); // 'look at this later' list
3965 return s;
3967 if (label->statement && label->statement->tf != sc->tf)
3968 error("cannot goto in or out of finally block");
3969 return this;
3972 int GotoStatement::blockExit()
3974 //printf("GotoStatement::blockExit(%p)\n", this);
3975 return BEgoto;
3978 int GotoStatement::fallOffEnd()
3980 return FALSE;
3983 void GotoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3985 buf->writestring("goto ");
3986 buf->writestring(ident->toChars());
3987 buf->writebyte(';');
3988 buf->writenl();
3991 /******************************** LabelStatement ***************************/
3993 LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement)
3994 : Statement(loc)
3996 this->ident = ident;
3997 this->statement = statement;
3998 this->tf = NULL;
3999 this->lblock = NULL;
4000 this->isReturnLabel = 0;
4003 Statement *LabelStatement::syntaxCopy()
4005 LabelStatement *s = new LabelStatement(loc, ident, statement->syntaxCopy());
4006 return s;
4009 Statement *LabelStatement::semantic(Scope *sc)
4010 { LabelDsymbol *ls;
4011 FuncDeclaration *fd = sc->parent->isFuncDeclaration();
4013 //printf("LabelStatement::semantic()\n");
4014 ls = fd->searchLabel(ident);
4015 if (ls->statement)
4016 error("Label '%s' already defined", ls->toChars());
4017 else
4018 ls->statement = this;
4019 tf = sc->tf;
4020 sc = sc->push();
4021 sc->scopesym = sc->enclosing->scopesym;
4022 sc->callSuper |= CSXlabel;
4023 sc->slabel = this;
4024 if (statement)
4025 statement = statement->semantic(sc);
4026 sc->pop();
4027 return this;
4030 Statements *LabelStatement::flatten(Scope *sc)
4032 Statements *a = NULL;
4034 if (statement)
4036 a = statement->flatten(sc);
4037 if (a)
4039 if (!a->dim)
4041 a->push(new ExpStatement(loc, NULL));
4043 Statement *s = (Statement *)a->data[0];
4045 s = new LabelStatement(loc, ident, s);
4046 a->data[0] = s;
4050 return a;
4054 int LabelStatement::usesEH()
4056 return statement ? statement->usesEH() : FALSE;
4059 int LabelStatement::blockExit()
4061 //printf("LabelStatement::blockExit(%p)\n", this);
4062 return statement ? statement->blockExit() : BEfallthru;
4065 int LabelStatement::fallOffEnd()
4067 return statement ? statement->fallOffEnd() : TRUE;
4070 int LabelStatement::comeFrom()
4072 //printf("LabelStatement::comeFrom()\n");
4073 return TRUE;
4076 void LabelStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4078 buf->writestring(ident->toChars());
4079 buf->writebyte(':');
4080 buf->writenl();
4081 if (statement)
4082 statement->toCBuffer(buf, hgs);
4086 /******************************** LabelDsymbol ***************************/
4088 LabelDsymbol::LabelDsymbol(Identifier *ident)
4089 : Dsymbol(ident)
4091 statement = NULL;
4092 #if IN_GCC
4093 asmLabelNum = 0;
4094 #endif
4097 LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()?
4099 return this;