Allow log_ statements outside of a class
[delight/core.git] / dmd / statement.c
blob4d362589ff23afd9b525094c9b6ae02b326baa34
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 *body = new CompoundStatement(loc, assignExt, s);
411 return body->semantic(sc);
414 /******************************** CompoundStatement ***************************/
416 CompoundStatement::CompoundStatement(Loc loc, Statements *s)
417 : Statement(loc)
419 statements = s;
422 CompoundStatement::CompoundStatement(Loc loc, Statement *s1, Statement *s2)
423 : Statement(loc)
425 statements = new Statements();
426 statements->reserve(2);
427 statements->push(s1);
428 statements->push(s2);
431 Statement *CompoundStatement::syntaxCopy()
433 Statements *a = new Statements();
434 a->setDim(statements->dim);
435 for (size_t i = 0; i < statements->dim; i++)
436 { Statement *s = (Statement *)statements->data[i];
437 if (s)
438 s = s->syntaxCopy();
439 a->data[i] = s;
441 CompoundStatement *cs = new CompoundStatement(loc, a);
442 return cs;
446 Statement *CompoundStatement::semantic(Scope *sc)
447 { Statement *s;
449 //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", this, sc);
451 for (size_t i = 0; i < statements->dim; )
453 s = (Statement *) statements->data[i];
454 if (s)
455 { Statements *a = s->flatten(sc);
457 if (a)
459 statements->remove(i);
460 statements->insert(i, a);
461 continue;
463 s = s->semantic(sc);
464 statements->data[i] = s;
465 if (s)
467 Statement *sentry;
468 Statement *sexception;
469 Statement *sfinally;
471 s->scopeCode(&sentry, &sexception, &sfinally);
472 if (sentry)
474 sentry = sentry->semantic(sc);
475 statements->data[i] = sentry;
477 if (sexception)
479 if (i + 1 == statements->dim && !sfinally)
481 #if 1
482 sexception = sexception->semantic(sc);
483 #else
484 statements->push(sexception);
485 if (sfinally)
486 // Assume sexception does not throw
487 statements->push(sfinally);
488 #endif
490 else
492 /* Rewrite:
493 * s; s1; s2;
494 * As:
495 * s;
496 * try { s1; s2; }
497 * catch (Object __o)
498 * { sexception; throw __o; }
500 Statement *body;
501 Statements *a = new Statements();
503 for (int j = i + 1; j < statements->dim; j++)
505 a->push(statements->data[j]);
507 body = new CompoundStatement(0, a);
508 body = new ScopeStatement(0, body);
510 static int num;
511 char name[3 + sizeof(num) * 3 + 1];
512 sprintf(name, "__o%d", ++num);
513 Identifier *id = Lexer::idPool(name);
515 Statement *handler = new ThrowStatement(0, new IdentifierExp(0, id));
516 handler = new CompoundStatement(0, sexception, handler);
518 Array *catches = new Array();
519 Catch *ctch = new Catch(0, NULL, id, handler);
520 catches->push(ctch);
521 s = new TryCatchStatement(0, body, catches);
523 if (sfinally)
524 s = new TryFinallyStatement(0, s, sfinally);
525 s = s->semantic(sc);
526 statements->setDim(i + 1);
527 statements->push(s);
528 break;
531 else if (sfinally)
533 if (0 && i + 1 == statements->dim)
535 statements->push(sfinally);
537 else
539 /* Rewrite:
540 * s; s1; s2;
541 * As:
542 * s; try { s1; s2; } finally { sfinally; }
544 Statement *body;
545 Statements *a = new Statements();
547 for (int j = i + 1; j < statements->dim; j++)
549 a->push(statements->data[j]);
551 body = new CompoundStatement(0, a);
552 s = new TryFinallyStatement(0, body, sfinally);
553 s = s->semantic(sc);
554 statements->setDim(i + 1);
555 statements->push(s);
556 break;
561 i++;
563 if (statements->dim == 1)
564 return s;
565 return this;
568 Statements *CompoundStatement::flatten(Scope *sc)
570 return statements;
573 ReturnStatement *CompoundStatement::isReturnStatement()
574 { int i;
575 ReturnStatement *rs = NULL;
577 for (i = 0; i < statements->dim; i++)
578 { Statement *s;
580 s = (Statement *) statements->data[i];
581 if (s)
583 rs = s->isReturnStatement();
584 if (rs)
585 break;
588 return rs;
591 void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
592 { int i;
594 for (i = 0; i < statements->dim; i++)
595 { Statement *s;
597 s = (Statement *) statements->data[i];
598 if (s)
599 s->toCBuffer(buf, hgs);
603 int CompoundStatement::usesEH()
605 for (int i = 0; i < statements->dim; i++)
606 { Statement *s;
608 s = (Statement *) statements->data[i];
609 if (s && s->usesEH())
610 return TRUE;
612 return FALSE;
615 int CompoundStatement::fallOffEnd()
616 { int falloff = TRUE;
618 //printf("CompoundStatement::fallOffEnd() %s\n", toChars());
619 for (int i = 0; i < statements->dim; i++)
620 { Statement *s = (Statement *)statements->data[i];
622 if (!s)
623 continue;
625 if (!falloff && global.params.warnings && !s->comeFrom())
627 fprintf(stdmsg, "warning - ");
628 s->error("statement is not reachable");
630 falloff = s->fallOffEnd();
632 return falloff;
635 int CompoundStatement::comeFrom()
636 { int comefrom = FALSE;
638 //printf("CompoundStatement::comeFrom()\n");
639 for (int i = 0; i < statements->dim; i++)
640 { Statement *s = (Statement *)statements->data[i];
642 if (!s)
643 continue;
645 comefrom |= s->comeFrom();
647 return comefrom;
651 /**************************** UnrolledLoopStatement ***************************/
653 UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s)
654 : Statement(loc)
656 statements = s;
659 Statement *UnrolledLoopStatement::syntaxCopy()
661 Statements *a = new Statements();
662 a->setDim(statements->dim);
663 for (size_t i = 0; i < statements->dim; i++)
664 { Statement *s = (Statement *)statements->data[i];
665 if (s)
666 s = s->syntaxCopy();
667 a->data[i] = s;
669 UnrolledLoopStatement *cs = new UnrolledLoopStatement(loc, a);
670 return cs;
674 Statement *UnrolledLoopStatement::semantic(Scope *sc)
676 //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc);
678 sc->noctor++;
679 Scope *scd = sc->push();
680 scd->sbreak = this;
681 scd->scontinue = this;
683 for (size_t i = 0; i < statements->dim; i++)
685 Statement *s = (Statement *) statements->data[i];
686 if (s)
688 s = s->semantic(scd);
689 statements->data[i] = s;
693 scd->pop();
694 sc->noctor--;
695 return this;
698 void UnrolledLoopStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
700 buf->writestring("unrolled {");
701 buf->writenl();
703 for (size_t i = 0; i < statements->dim; i++)
704 { Statement *s;
706 s = (Statement *) statements->data[i];
707 if (s)
708 s->toCBuffer(buf, hgs);
711 buf->writeByte('}');
712 buf->writenl();
715 int UnrolledLoopStatement::hasBreak()
717 return TRUE;
720 int UnrolledLoopStatement::hasContinue()
722 return TRUE;
725 int UnrolledLoopStatement::usesEH()
727 for (size_t i = 0; i < statements->dim; i++)
728 { Statement *s;
730 s = (Statement *) statements->data[i];
731 if (s && s->usesEH())
732 return TRUE;
734 return FALSE;
737 int UnrolledLoopStatement::fallOffEnd()
739 //printf("UnrolledLoopStatement::fallOffEnd()\n");
740 for (size_t i = 0; i < statements->dim; i++)
741 { Statement *s = (Statement *)statements->data[i];
743 if (s)
744 s->fallOffEnd();
746 return TRUE;
750 int UnrolledLoopStatement::comeFrom()
751 { int comefrom = FALSE;
753 //printf("UnrolledLoopStatement::comeFrom()\n");
754 for (size_t i = 0; i < statements->dim; i++)
755 { Statement *s = (Statement *)statements->data[i];
757 if (!s)
758 continue;
760 comefrom |= s->comeFrom();
762 return comefrom;
766 /******************************** ScopeStatement ***************************/
768 ScopeStatement::ScopeStatement(Loc loc, Statement *s)
769 : Statement(loc)
771 this->statement = s;
774 Statement *ScopeStatement::syntaxCopy()
776 Statement *s;
778 s = statement ? statement->syntaxCopy() : NULL;
779 s = new ScopeStatement(loc, s);
780 return s;
784 Statement *ScopeStatement::semantic(Scope *sc)
785 { ScopeDsymbol *sym;
787 //printf("ScopeStatement::semantic(sc = %p)\n", sc);
788 if (statement)
789 { Statements *a;
791 sym = new ScopeDsymbol();
792 sym->parent = sc->scopesym;
793 sc = sc->push(sym);
795 a = statement->flatten(sc);
796 if (a)
798 statement = new CompoundStatement(loc, a);
801 statement = statement->semantic(sc);
802 if (statement)
804 Statement *sentry;
805 Statement *sexception;
806 Statement *sfinally;
808 statement->scopeCode(&sentry, &sexception, &sfinally);
809 if (sfinally)
811 //printf("adding sfinally\n");
812 statement = new CompoundStatement(loc, statement, sfinally);
816 sc->pop();
818 return this;
821 int ScopeStatement::hasBreak()
823 //printf("ScopeStatement::hasBreak() %s\n", toChars());
824 return statement ? statement->hasBreak() : FALSE;
827 int ScopeStatement::hasContinue()
829 return statement ? statement->hasContinue() : FALSE;
832 int ScopeStatement::usesEH()
834 return statement ? statement->usesEH() : FALSE;
837 int ScopeStatement::fallOffEnd()
839 return statement ? statement->fallOffEnd() : TRUE;
842 int ScopeStatement::comeFrom()
844 //printf("ScopeStatement::comeFrom()\n");
845 return statement ? statement->comeFrom() : FALSE;
848 void ScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
850 buf->writeByte('{');
851 buf->writenl();
853 if (statement)
854 statement->toCBuffer(buf, hgs);
856 buf->writeByte('}');
857 buf->writenl();
860 /******************************** WhileStatement ***************************/
862 WhileStatement::WhileStatement(Loc loc, Expression *c, Statement *b)
863 : Statement(loc)
865 condition = c;
866 body = b;
869 Statement *WhileStatement::syntaxCopy()
871 WhileStatement *s = new WhileStatement(loc, condition->syntaxCopy(), body ? body->syntaxCopy() : NULL);
872 return s;
876 Statement *WhileStatement::semantic(Scope *sc)
878 #if 0
879 if (condition->op == TOKmatch)
881 /* Rewrite while (condition) body as:
882 * if (condition)
883 * do
884 * body
885 * while ((_match = _match.opNext), _match);
888 Expression *ew = new IdentifierExp(0, Id::_match);
889 ew = new DotIdExp(0, ew, Id::next);
890 ew = new AssignExp(0, new IdentifierExp(0, Id::_match), ew);
891 ////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0));
892 Expression *ev = new IdentifierExp(0, Id::_match);
893 //ev = new CastExp(0, ev, Type::tvoidptr);
894 ew = new CommaExp(0, ew, ev);
895 Statement *sw = new DoStatement(loc, body, ew);
896 Statement *si = new IfStatement(loc, condition, sw, NULL);
897 return si->semantic(sc);
899 #endif
901 condition = condition->semantic(sc);
902 condition = resolveProperties(sc, condition);
903 condition = condition->optimize(WANTvalue);
904 condition = condition->checkToBoolean();
906 sc->noctor++;
908 Scope *scd = sc->push();
909 scd->sbreak = this;
910 scd->scontinue = this;
911 if (body)
912 body = body->semantic(scd);
913 scd->pop();
915 sc->noctor--;
917 return this;
920 int WhileStatement::hasBreak()
922 return TRUE;
925 int WhileStatement::hasContinue()
927 return TRUE;
930 int WhileStatement::usesEH()
932 return body ? body->usesEH() : 0;
935 int WhileStatement::fallOffEnd()
937 if (body)
938 body->fallOffEnd();
939 return TRUE;
942 int WhileStatement::comeFrom()
944 if (body)
945 return body->comeFrom();
946 return FALSE;
949 void WhileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
951 buf->writestring("while (");
952 condition->toCBuffer(buf, hgs);
953 buf->writebyte(')');
954 buf->writenl();
955 if (body)
956 body->toCBuffer(buf, hgs);
959 /******************************** DoStatement ***************************/
961 DoStatement::DoStatement(Loc loc, Statement *b, Expression *c)
962 : Statement(loc)
964 body = b;
965 condition = c;
968 Statement *DoStatement::syntaxCopy()
970 DoStatement *s = new DoStatement(loc, body ? body->syntaxCopy() : NULL, condition->syntaxCopy());
971 return s;
975 Statement *DoStatement::semantic(Scope *sc)
977 sc->noctor++;
978 if (body)
979 body = body->semanticScope(sc, this, this);
980 sc->noctor--;
981 condition = condition->semantic(sc);
982 condition = resolveProperties(sc, condition);
983 condition = condition->optimize(WANTvalue);
985 condition = condition->checkToBoolean();
987 return this;
990 int DoStatement::hasBreak()
992 return TRUE;
995 int DoStatement::hasContinue()
997 return TRUE;
1000 int DoStatement::usesEH()
1002 return body ? body->usesEH() : 0;
1005 int DoStatement::fallOffEnd()
1007 if (body)
1008 body->fallOffEnd();
1009 return TRUE;
1012 int DoStatement::comeFrom()
1014 if (body)
1015 return body->comeFrom();
1016 return FALSE;
1019 void DoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1021 buf->writestring("do");
1022 buf->writenl();
1023 if (body)
1024 body->toCBuffer(buf, hgs);
1025 buf->writestring("while (");
1026 condition->toCBuffer(buf, hgs);
1027 buf->writebyte(')');
1030 /******************************** ForStatement ***************************/
1032 ForStatement::ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body)
1033 : Statement(loc)
1035 this->init = init;
1036 this->condition = condition;
1037 this->increment = increment;
1038 this->body = body;
1041 Statement *ForStatement::syntaxCopy()
1043 Statement *i = NULL;
1044 if (init)
1045 i = init->syntaxCopy();
1046 Expression *c = NULL;
1047 if (condition)
1048 c = condition->syntaxCopy();
1049 Expression *inc = NULL;
1050 if (increment)
1051 inc = increment->syntaxCopy();
1052 ForStatement *s = new ForStatement(loc, i, c, inc, body->syntaxCopy());
1053 return s;
1056 Statement *ForStatement::semantic(Scope *sc)
1058 ScopeDsymbol *sym = new ScopeDsymbol();
1059 sym->parent = sc->scopesym;
1060 sc = sc->push(sym);
1061 if (init)
1062 init = init->semantic(sc);
1063 if (!condition)
1064 // Use a default value
1065 condition = new IntegerExp(loc, 1, Type::tboolean);
1066 sc->noctor++;
1067 condition = condition->semantic(sc);
1068 condition = resolveProperties(sc, condition);
1069 condition = condition->optimize(WANTvalue);
1070 condition = condition->checkToBoolean();
1071 if (increment)
1072 increment = increment->semantic(sc);
1074 sc->sbreak = this;
1075 sc->scontinue = this;
1076 body = body->semantic(sc);
1077 sc->noctor--;
1079 sc->pop();
1080 return this;
1083 void ForStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally)
1085 //printf("ForStatement::scopeCode()\n");
1086 //print();
1087 if (init)
1088 init->scopeCode(sentry, sexception, sfinally);
1089 else
1090 Statement::scopeCode(sentry, sexception, sfinally);
1093 int ForStatement::hasBreak()
1095 //printf("ForStatement::hasBreak()\n");
1096 return TRUE;
1099 int ForStatement::hasContinue()
1101 return TRUE;
1104 int ForStatement::usesEH()
1106 return (init && init->usesEH()) || body->usesEH();
1109 int ForStatement::fallOffEnd()
1111 if (body)
1112 body->fallOffEnd();
1113 return TRUE;
1116 int ForStatement::comeFrom()
1118 //printf("ForStatement::comeFrom()\n");
1119 if (body)
1120 { int result = body->comeFrom();
1121 //printf("result = %d\n", result);
1122 return result;
1124 return FALSE;
1127 void ForStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1129 buf->writestring("for (");
1130 if (init)
1132 hgs->FLinit.init++;
1133 hgs->FLinit.decl = 0;
1134 init->toCBuffer(buf, hgs);
1135 if (hgs->FLinit.decl > 0)
1136 buf->writebyte(';');
1137 hgs->FLinit.decl = 0;
1138 hgs->FLinit.init--;
1140 else
1141 buf->writebyte(';');
1142 if (condition)
1143 { buf->writebyte(' ');
1144 condition->toCBuffer(buf, hgs);
1146 buf->writebyte(';');
1147 if (increment)
1148 { buf->writebyte(' ');
1149 increment->toCBuffer(buf, hgs);
1151 buf->writebyte(')');
1152 buf->writenl();
1153 buf->writebyte('{');
1154 buf->writenl();
1155 body->toCBuffer(buf, hgs);
1156 buf->writebyte('}');
1157 buf->writenl();
1160 /******************************** ForeachStatement ***************************/
1162 ForeachStatement::ForeachStatement(Loc loc, enum TOK op, Arguments *arguments,
1163 Expression *aggr, Statement *body)
1164 : Statement(loc)
1166 this->op = op;
1167 this->arguments = arguments;
1168 this->aggr = aggr;
1169 this->body = body;
1171 this->key = NULL;
1172 this->value = NULL;
1174 this->func = NULL;
1177 Statement *ForeachStatement::syntaxCopy()
1179 Arguments *args = Argument::arraySyntaxCopy(arguments);
1180 Expression *exp = aggr->syntaxCopy();
1181 ForeachStatement *s = new ForeachStatement(loc, op, args, exp,
1182 body ? body->syntaxCopy() : NULL);
1183 return s;
1186 Statement *ForeachStatement::semantic(Scope *sc)
1188 //printf("ForeachStatement::semantic() %p\n", this);
1189 ScopeDsymbol *sym;
1190 Statement *s = this;
1191 int dim = arguments->dim;
1192 int i;
1193 TypeAArray *taa = NULL;
1195 Type *tn = NULL;
1196 Type *tnv = NULL;
1198 func = sc->func;
1199 if (func->fes)
1200 func = func->fes->func;
1202 aggr = aggr->semantic(sc);
1203 aggr = resolveProperties(sc, aggr);
1204 if (!aggr->type)
1206 error("invalid foreach aggregate %s", aggr->toChars());
1207 return this;
1210 inferApplyArgTypes(op, arguments, aggr);
1212 /* Check for inference errors
1214 if (dim != arguments->dim)
1216 //printf("dim = %d, arguments->dim = %d\n", dim, arguments->dim);
1217 error("cannot uniquely infer foreach argument types");
1218 return this;
1221 Type *tab = aggr->type->toBasetype();
1223 if (tab->ty == Ttuple) // don't generate new scope for tuple loops
1225 if (dim < 1 || dim > 2)
1227 error("only one (value) or two (key,value) arguments for tuple foreach");
1228 return s;
1231 TypeTuple *tuple = (TypeTuple *)tab;
1232 Statements *statements = new Statements();
1233 //printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars());
1234 size_t n;
1235 TupleExp *te = NULL;
1236 if (aggr->op == TOKtuple) // expression tuple
1237 { te = (TupleExp *)aggr;
1238 n = te->exps->dim;
1240 else if (aggr->op == TOKtype) // type tuple
1242 n = Argument::dim(tuple->arguments);
1244 else
1245 assert(0);
1246 for (size_t j = 0; j < n; j++)
1247 { size_t k = (op == TOKforeach) ? j : n - 1 - j;
1248 Expression *e;
1249 Type *t;
1250 if (te)
1251 e = (Expression *)te->exps->data[k];
1252 else
1253 t = Argument::getNth(tuple->arguments, k)->type;
1254 Argument *arg = (Argument *)arguments->data[0];
1255 Statements *st = new Statements();
1257 if (dim == 2)
1258 { // Declare key
1259 if (arg->storageClass & (STCout | STCref | STClazy))
1260 error("no storage class for key %s", arg->ident->toChars());
1261 TY keyty = arg->type->ty;
1262 if ((keyty != Tint32 && keyty != Tuns32) &&
1263 (! global.params.isX86_64 ||
1264 (keyty != Tint64 && keyty != Tuns64))
1267 error("foreach: key type must be int or uint, not %s", arg->type->toChars());
1269 Initializer *ie = new ExpInitializer(0, new IntegerExp(k));
1270 VarDeclaration *var = new VarDeclaration(loc, arg->type, arg->ident, ie);
1271 var->storage_class |= STCconst;
1272 DeclarationExp *de = new DeclarationExp(loc, var);
1273 st->push(new ExpStatement(loc, de));
1274 arg = (Argument *)arguments->data[1]; // value
1276 // Declare value
1277 if (arg->storageClass & (STCout | STCref | STClazy))
1278 error("no storage class for value %s", arg->ident->toChars());
1279 Dsymbol *var;
1280 if (te)
1282 if (e->type->toBasetype()->ty == Tfunction &&
1283 e->op == TOKvar)
1284 { VarExp *ve = (VarExp *)e;
1285 var = new AliasDeclaration(loc, arg->ident, ve->var);
1287 else
1289 arg->type = e->type;
1290 Initializer *ie = new ExpInitializer(0, e);
1291 VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie);
1292 if (e->isConst())
1293 v->storage_class |= STCconst;
1294 #if V2
1295 else
1296 v->storage_class |= STCfinal;
1297 #endif
1298 var = v;
1301 else
1303 var = new AliasDeclaration(loc, arg->ident, t);
1305 DeclarationExp *de = new DeclarationExp(loc, var);
1306 st->push(new ExpStatement(loc, de));
1308 st->push(body->syntaxCopy());
1309 s = new CompoundStatement(loc, st);
1310 s = new ScopeStatement(loc, s);
1311 statements->push(s);
1314 s = new UnrolledLoopStatement(loc, statements);
1315 s = s->semantic(sc);
1316 return s;
1319 for (i = 0; i < dim; i++)
1320 { Argument *arg = (Argument *)arguments->data[i];
1321 if (!arg->type)
1323 error("cannot infer type for %s", arg->ident->toChars());
1324 return this;
1328 sym = new ScopeDsymbol();
1329 sym->parent = sc->scopesym;
1330 sc = sc->push(sym);
1332 sc->noctor++;
1334 switch (tab->ty)
1336 case Tarray:
1337 case Tsarray:
1338 if (dim < 1 || dim > 2)
1340 error("only one or two arguments for array foreach");
1341 break;
1344 /* Look for special case of parsing char types out of char type
1345 * array.
1347 tn = tab->nextOf()->toBasetype();
1348 if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
1349 { Argument *arg;
1351 i = (dim == 1) ? 0 : 1; // index of value
1352 arg = (Argument *)arguments->data[i];
1353 arg->type = arg->type->semantic(loc, sc);
1354 tnv = arg->type->toBasetype();
1355 if (tnv->ty != tn->ty &&
1356 (tnv->ty == Tchar || tnv->ty == Twchar || tnv->ty == Tdchar))
1358 if (arg->storageClass & STCref)
1359 error("foreach: value of UTF conversion cannot be ref");
1360 if (dim == 2)
1361 { arg = (Argument *)arguments->data[0];
1362 if (arg->storageClass & STCref)
1363 error("foreach: key cannot be ref");
1365 goto Lapply;
1369 for (i = 0; i < dim; i++)
1370 { // Declare args
1371 Argument *arg = (Argument *)arguments->data[i];
1372 VarDeclaration *var;
1374 var = new VarDeclaration(loc, arg->type, arg->ident, NULL);
1375 var->storage_class |= STCforeach;
1376 var->storage_class |= arg->storageClass & (STCin | STCout | STCref);
1377 #if 1
1378 DeclarationExp *de = new DeclarationExp(loc, var);
1379 de->semantic(sc);
1380 #else
1381 var->semantic(sc);
1382 if (!sc->insert(var))
1383 error("%s already defined", var->ident->toChars());
1384 #endif
1385 if (dim == 2 && i == 0)
1386 key = var;
1387 else
1388 value = var;
1391 sc->sbreak = this;
1392 sc->scontinue = this;
1393 body = body->semantic(sc);
1395 if (!value->type->equals(tab->next))
1397 if (aggr->op == TOKstring)
1398 aggr = aggr->implicitCastTo(sc, value->type->arrayOf());
1399 else
1400 error("foreach: %s is not an array of %s", tab->toChars(), value->type->toChars());
1403 if (key &&
1404 ((key->type->ty != Tint32 && key->type->ty != Tuns32) &&
1405 (! global.params.isX86_64 ||
1406 (key->type->ty != Tint64 && key->type->ty != Tuns64))
1410 error("foreach: key type must be int or uint, not %s", key->type->toChars());
1413 if (key && key->storage_class & (STCout | STCref))
1414 error("foreach: key cannot be out or ref");
1415 break;
1417 case Taarray:
1418 taa = (TypeAArray *)tab;
1419 if (dim < 1 || dim > 2)
1421 error("only one or two arguments for associative array foreach");
1422 break;
1424 if (op == TOKforeach_reverse)
1426 error("no reverse iteration on associative arrays");
1428 goto Lapply;
1430 case Tclass:
1431 case Tstruct:
1432 case Tdelegate:
1433 Lapply:
1434 { FuncDeclaration *fdapply;
1435 Arguments *args;
1436 Expression *ec;
1437 Expression *e;
1438 FuncLiteralDeclaration *fld;
1439 Argument *a;
1440 Type *t;
1441 Expression *flde;
1442 Identifier *id;
1443 Type *tret;
1445 tret = func->type->nextOf();
1447 // Need a variable to hold value from any return statements in body.
1448 if (!sc->func->vresult && tret && tret != Type::tvoid)
1449 { VarDeclaration *v;
1451 v = new VarDeclaration(loc, tret, Id::result, NULL);
1452 v->noauto = 1;
1453 v->semantic(sc);
1454 if (!sc->insert(v))
1455 assert(0);
1456 v->parent = sc->func;
1457 sc->func->vresult = v;
1460 /* Turn body into the function literal:
1461 * int delegate(ref T arg) { body }
1463 args = new Arguments();
1464 for (i = 0; i < dim; i++)
1465 { Argument *arg = (Argument *)arguments->data[i];
1467 arg->type = arg->type->semantic(loc, sc);
1468 if (arg->storageClass & STCref)
1469 id = arg->ident;
1470 else
1471 { // Make a copy of the ref argument so it isn't
1472 // a reference.
1473 VarDeclaration *v;
1474 Initializer *ie;
1475 char applyArg[10 + sizeof(i)*3 + 1];
1477 sprintf(applyArg, "__applyArg%d", i);
1478 id = Lexer::idPool(applyArg);
1480 ie = new ExpInitializer(0, new IdentifierExp(0, id));
1481 v = new VarDeclaration(0, arg->type, arg->ident, ie);
1482 s = new DeclarationStatement(0, v);
1483 body = new CompoundStatement(loc, s, body);
1485 a = new Argument(STCref, arg->type, id, NULL);
1486 args->push(a);
1488 t = new TypeFunction(args, Type::tint32, 0, LINKd);
1489 fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this);
1490 fld->fbody = body;
1491 flde = new FuncExp(loc, fld);
1492 flde = flde->semantic(sc);
1494 // Resolve any forward referenced goto's
1495 for (int i = 0; i < gotos.dim; i++)
1496 { CompoundStatement *cs = (CompoundStatement *)gotos.data[i];
1497 GotoStatement *gs = (GotoStatement *)cs->statements->data[0];
1499 if (!gs->label->statement)
1500 { // 'Promote' it to this scope, and replace with a return
1501 cases.push(gs);
1502 s = new ReturnStatement(0, new IntegerExp(cases.dim + 1));
1503 cs->statements->data[0] = (void *)s;
1507 if (tab->ty == Taarray)
1509 // Check types
1510 Argument *arg = (Argument *)arguments->data[0];
1511 if (dim == 2)
1513 if (arg->storageClass & STCref)
1514 error("foreach: index cannot be ref");
1515 if (!arg->type->equals(taa->index))
1516 error("foreach: index must be type %s, not %s", taa->index->toChars(), arg->type->toChars());
1517 arg = (Argument *)arguments->data[1];
1519 if (!arg->type->equals(taa->nextOf()))
1520 error("foreach: value must be type %s, not %s", taa->nextOf()->toChars(), arg->type->toChars());
1522 /* Call:
1523 * _aaApply(aggr, keysize, flde)
1525 if (dim == 2)
1526 fdapply = FuncDeclaration::genCfunc(Type::tint32, "_aaApply2",
1527 Type::tvoid->arrayOf(), Type::tsize_t, flde->type); // flde->type is not generic
1528 else
1529 fdapply = FuncDeclaration::genCfunc(Type::tint32, "_aaApply",
1530 Type::tvoid->arrayOf(), Type::tsize_t, flde->type); // flde->type is not generic);
1531 ec = new VarExp(0, fdapply);
1532 Expressions *exps = new Expressions();
1533 exps->push(aggr);
1534 size_t keysize = taa->key->size();
1535 keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1);
1536 exps->push(new IntegerExp(0, keysize, Type::tsize_t));
1537 exps->push(flde);
1538 e = new CallExp(loc, ec, exps);
1539 e->type = Type::tint32; // don't run semantic() on e
1541 else if (tab->ty == Tarray || tab->ty == Tsarray)
1543 /* Call:
1544 * _aApply(aggr, flde)
1546 static char fntab[9][3] =
1547 { "cc","cw","cd",
1548 "wc","cc","wd",
1549 "dc","dw","dd"
1551 char fdname[7+1+2+ sizeof(dim)*3 + 1];
1552 int flag;
1554 switch (tn->ty)
1556 case Tchar: flag = 0; break;
1557 case Twchar: flag = 3; break;
1558 case Tdchar: flag = 6; break;
1559 default: assert(0);
1561 switch (tnv->ty)
1563 case Tchar: flag += 0; break;
1564 case Twchar: flag += 1; break;
1565 case Tdchar: flag += 2; break;
1566 default: assert(0);
1568 const char *r = (op == TOKforeach_reverse) ? "R" : "";
1569 int j = sprintf(fdname, "_aApply%s%.*s%d", r, 2, fntab[flag], dim);
1570 assert(j < sizeof(fdname));
1571 fdapply = FuncDeclaration::genCfunc(Type::tint32, fdname,
1572 Type::tvoid->arrayOf(), flde->type); // flde->type is not generic
1574 ec = new VarExp(0, fdapply);
1575 Expressions *exps = new Expressions();
1576 if (tab->ty == Tsarray)
1577 aggr = aggr->castTo(sc, tn->arrayOf());
1578 exps->push(aggr);
1579 exps->push(flde);
1580 e = new CallExp(loc, ec, exps);
1581 e->type = Type::tint32; // don't run semantic() on e
1583 else if (tab->ty == Tdelegate)
1585 /* Call:
1586 * aggr(flde)
1588 Expressions *exps = new Expressions();
1589 exps->push(flde);
1590 e = new CallExp(loc, aggr, exps);
1591 e = e->semantic(sc);
1592 if (e->type != Type::tint32)
1593 error("opApply() function for %s must return an int", tab->toChars());
1595 else
1597 /* Call:
1598 * aggr.apply(flde)
1600 ec = new DotIdExp(loc, aggr,
1601 (op == TOKforeach_reverse) ? Id::applyReverse
1602 : Id::apply);
1603 Expressions *exps = new Expressions();
1604 exps->push(flde);
1605 e = new CallExp(loc, ec, exps);
1606 e = e->semantic(sc);
1607 if (e->type != Type::tint32)
1608 error("opApply() function for %s must return an int", tab->toChars());
1611 if (!cases.dim)
1612 // Easy case, a clean exit from the loop
1613 s = new ExpStatement(loc, e);
1614 else
1615 { // Construct a switch statement around the return value
1616 // of the apply function.
1617 Statements *a = new Statements();
1619 // default: break; takes care of cases 0 and 1
1620 s = new BreakStatement(0, NULL);
1621 s = new DefaultStatement(0, s);
1622 a->push(s);
1624 // cases 2...
1625 for (int i = 0; i < cases.dim; i++)
1627 s = (Statement *)cases.data[i];
1628 s = new CaseStatement(0, new IntegerExp(i + 2), s);
1629 a->push(s);
1632 s = new CompoundStatement(loc, a);
1633 s = new SwitchStatement(loc, e, s);
1634 s = s->semantic(sc);
1636 break;
1639 default:
1640 error("foreach: %s is not an aggregate type", aggr->type->toChars());
1641 break;
1643 sc->noctor--;
1644 sc->pop();
1645 return s;
1648 int ForeachStatement::hasBreak()
1650 return TRUE;
1653 int ForeachStatement::hasContinue()
1655 return TRUE;
1658 int ForeachStatement::usesEH()
1660 return body->usesEH();
1663 int ForeachStatement::fallOffEnd()
1665 if (body)
1666 body->fallOffEnd();
1667 return TRUE;
1670 int ForeachStatement::comeFrom()
1672 if (body)
1673 return body->comeFrom();
1674 return FALSE;
1677 void ForeachStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1679 buf->writestring(Token::toChars(op));
1680 buf->writestring(" (");
1681 int i;
1682 for (int i = 0; i < arguments->dim; i++)
1684 Argument *a = (Argument *)arguments->data[i];
1685 if (i)
1686 buf->writestring(", ");
1687 if (a->storageClass & STCref)
1688 buf->writestring((global.params.Dversion == 1)
1689 ? (char*)"inout " : (char*)"ref ");
1690 if (a->type)
1691 a->type->toCBuffer(buf, a->ident, hgs);
1692 else
1693 buf->writestring(a->ident->toChars());
1695 buf->writestring("; ");
1696 aggr->toCBuffer(buf, hgs);
1697 buf->writebyte(')');
1698 buf->writenl();
1699 buf->writebyte('{');
1700 buf->writenl();
1701 if (body)
1702 body->toCBuffer(buf, hgs);
1703 buf->writebyte('}');
1704 buf->writenl();
1707 /******************************** IfStatement ***************************/
1709 IfStatement::IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody)
1710 : Statement(loc)
1712 this->arg = arg;
1713 this->condition = condition;
1714 this->ifbody = ifbody;
1715 this->elsebody = elsebody;
1716 this->match = NULL;
1719 Statement *IfStatement::syntaxCopy()
1721 Statement *i = NULL;
1722 if (ifbody)
1723 i = ifbody->syntaxCopy();
1725 Statement *e = NULL;
1726 if (elsebody)
1727 e = elsebody->syntaxCopy();
1729 Argument *a = arg ? arg->syntaxCopy() : NULL;
1730 IfStatement *s = new IfStatement(loc, a, condition->syntaxCopy(), i, e);
1731 return s;
1734 Statement *IfStatement::semantic(Scope *sc)
1736 condition = condition->semantic(sc);
1737 condition = resolveProperties(sc, condition);
1738 condition = condition->checkToBoolean();
1740 // If we can short-circuit evaluate the if statement, don't do the
1741 // semantic analysis of the skipped code.
1742 // This feature allows a limited form of conditional compilation.
1743 condition = condition->optimize(WANTflags);
1745 // Evaluate at runtime
1746 unsigned cs0 = sc->callSuper;
1747 unsigned cs1;
1749 Scope *scd;
1750 if (arg)
1751 { /* Declare arg, which we will set to be the
1752 * result of condition.
1754 ScopeDsymbol *sym = new ScopeDsymbol();
1755 sym->parent = sc->scopesym;
1756 scd = sc->push(sym);
1758 Type *t = arg->type ? arg->type : condition->type;
1759 match = new VarDeclaration(loc, t, arg->ident, NULL);
1760 match->noauto = 1;
1761 match->semantic(scd);
1762 if (!scd->insert(match))
1763 assert(0);
1764 match->parent = sc->func;
1766 /* Generate:
1767 * (arg = condition)
1769 VarExp *v = new VarExp(0, match);
1770 condition = new AssignExp(loc, v, condition);
1771 condition = condition->semantic(scd);
1773 else
1774 scd = sc->push();
1775 ifbody = ifbody->semantic(scd);
1776 scd->pop();
1778 cs1 = sc->callSuper;
1779 sc->callSuper = cs0;
1780 if (elsebody)
1781 elsebody = elsebody->semanticScope(sc, NULL, NULL);
1782 sc->mergeCallSuper(loc, cs1);
1784 return this;
1787 int IfStatement::usesEH()
1789 return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH());
1792 int IfStatement::fallOffEnd()
1794 if (!ifbody || ifbody->fallOffEnd() ||
1795 !elsebody || elsebody->fallOffEnd())
1796 return TRUE;
1797 return FALSE;
1801 void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1803 buf->writestring("if (");
1804 if (arg)
1806 if (arg->type)
1807 arg->type->toCBuffer(buf, arg->ident, hgs);
1808 else
1809 buf->writestring(arg->ident->toChars());
1810 buf->writebyte(';');
1812 condition->toCBuffer(buf, hgs);
1813 buf->writebyte(')');
1814 buf->writenl();
1815 ifbody->toCBuffer(buf, hgs);
1816 if (elsebody)
1817 { buf->writestring("else");
1818 buf->writenl();
1819 elsebody->toCBuffer(buf, hgs);
1823 /******************************** ConditionalStatement ***************************/
1825 ConditionalStatement::ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody)
1826 : Statement(loc)
1828 this->condition = condition;
1829 this->ifbody = ifbody;
1830 this->elsebody = elsebody;
1833 Statement *ConditionalStatement::syntaxCopy()
1835 Statement *e = NULL;
1836 if (elsebody)
1837 e = elsebody->syntaxCopy();
1838 ConditionalStatement *s = new ConditionalStatement(loc,
1839 condition->syntaxCopy(), ifbody->syntaxCopy(), e);
1840 return s;
1843 Statement *ConditionalStatement::semantic(Scope *sc)
1845 //printf("ConditionalStatement::semantic()\n");
1847 // If we can short-circuit evaluate the if statement, don't do the
1848 // semantic analysis of the skipped code.
1849 // This feature allows a limited form of conditional compilation.
1850 if (condition->include(sc, NULL))
1852 ifbody = ifbody->semantic(sc);
1853 return ifbody;
1855 else
1857 if (elsebody)
1858 elsebody = elsebody->semantic(sc);
1859 return elsebody;
1863 Statements *ConditionalStatement::flatten(Scope *sc)
1865 Statement *s;
1867 if (condition->include(sc, NULL))
1868 s = ifbody;
1869 else
1870 s = elsebody;
1872 Statements *a = new Statements();
1873 a->push(s);
1874 return a;
1877 int ConditionalStatement::usesEH()
1879 return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH());
1882 void ConditionalStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1884 condition->toCBuffer(buf, hgs);
1885 buf->writenl();
1886 if (ifbody)
1887 ifbody->toCBuffer(buf, hgs);
1888 if (elsebody)
1890 buf->writestring("else");
1891 buf->writenl();
1892 elsebody->toCBuffer(buf, hgs);
1894 buf->writenl();
1898 /******************************** PragmaStatement ***************************/
1900 PragmaStatement::PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body)
1901 : Statement(loc)
1903 this->ident = ident;
1904 this->args = args;
1905 this->body = body;
1908 Statement *PragmaStatement::syntaxCopy()
1910 Statement *b = NULL;
1911 if (body)
1912 b = body->syntaxCopy();
1913 PragmaStatement *s = new PragmaStatement(loc,
1914 ident, Expression::arraySyntaxCopy(args), b);
1915 return s;
1918 Statement *PragmaStatement::semantic(Scope *sc)
1919 { // Should be merged with PragmaDeclaration
1920 //printf("PragmaStatement::semantic() %s\n", toChars());
1921 //printf("body = %p\n", body);
1922 if (ident == Id::msg)
1924 if (args)
1926 for (size_t i = 0; i < args->dim; i++)
1928 Expression *e = (Expression *)args->data[i];
1930 e = e->semantic(sc);
1931 e = e->optimize(WANTvalue | WANTinterpret);
1932 if (e->op == TOKstring)
1934 StringExp *se = (StringExp *)e;
1935 fprintf(stdmsg, "%.*s", (int)se->len, se->string);
1937 else
1938 error("string expected for message, not '%s'", e->toChars());
1940 fprintf(stdmsg, "\n");
1943 else if (ident == Id::lib)
1945 if (!args || args->dim != 1)
1946 error("string expected for library name");
1947 else
1949 Expression *e = (Expression *)args->data[0];
1951 e = e->semantic(sc);
1952 e = e->optimize(WANTvalue | WANTinterpret);
1953 args->data[0] = (void *)e;
1954 if (e->op != TOKstring)
1955 error("string expected for library name, not '%s'", e->toChars());
1956 else if (global.params.verbose)
1958 StringExp *se = (StringExp *)e;
1959 char *name = (char *)mem.malloc(se->len + 1);
1960 memcpy(name, se->string, se->len);
1961 name[se->len] = 0;
1962 printf("library %s\n", name);
1963 mem.free(name);
1967 else
1968 error("unrecognized pragma(%s)", ident->toChars());
1970 if (body)
1972 body = body->semantic(sc);
1974 return body;
1977 int PragmaStatement::usesEH()
1979 return body && body->usesEH();
1982 int PragmaStatement::fallOffEnd()
1984 if (body)
1985 return body->fallOffEnd();
1986 return TRUE;
1989 void PragmaStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1991 buf->writestring("pragma (");
1992 buf->writestring(ident->toChars());
1993 if (args && args->dim)
1995 buf->writestring(", ");
1996 argsToCBuffer(buf, args, hgs);
1998 buf->writeByte(')');
1999 if (body)
2001 buf->writenl();
2002 buf->writeByte('{');
2003 buf->writenl();
2005 body->toCBuffer(buf, hgs);
2007 buf->writeByte('}');
2008 buf->writenl();
2010 else
2012 buf->writeByte(';');
2013 buf->writenl();
2018 /******************************** LogStatement ***************************/
2020 LogStatement::LogStatement(Loc loc, int level, Expressions *args)
2021 : Statement(loc)
2023 this->level = level;
2024 this->args = args;
2027 Statement *LogStatement::semantic(Scope *sc)
2029 Expression *logger = new DotIdExp(loc, new GetLoggerExp(loc), Id::log);
2030 Type *type = NULL;
2032 for (Dsymbol *s = sc->parent; s; s = s->parent)
2034 ClassDeclaration *cd;
2035 StructDeclaration *sd;
2037 cd = s->isClassDeclaration();
2038 if (cd)
2040 type = cd->type;
2041 break;
2045 if (type == NULL) {
2046 // We're a top-level function. Generate log messages from the module
2047 args->shift(new StringExp(loc, strdup(sc->module->ident->string)));
2048 } else {
2049 args->shift(new DotIdExp(loc, new TypeExp(loc, type), Id::classinfo));
2052 args->shift(new IntegerExp(loc, level, Type::tint32));
2053 Expression *callLogger = new CallExp(loc, logger, args);
2055 Statement *s = new ExpStatement(loc, callLogger);
2057 return s->semantic(sc);
2060 void LogStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2062 char *l;
2063 switch (level) {
2064 case 10: l = "log_debug"; break;
2065 case 20: l = "log_info"; break;
2066 case 30: l = "log_warning"; break;
2067 case 40: l = "log_error"; break;
2068 default:
2069 error("Unknown log level %d", level);
2070 l = "log_UNKNOWN";
2072 buf->writestring(l);
2073 buf->writeByte('(');
2074 argsToCBuffer(buf, args, hgs);
2075 buf->writeByte(')');
2076 buf->writenl();
2079 /******************************** StaticAssertStatement ***************************/
2081 StaticAssertStatement::StaticAssertStatement(StaticAssert *sa)
2082 : Statement(sa->loc)
2084 this->sa = sa;
2087 Statement *StaticAssertStatement::syntaxCopy()
2089 StaticAssertStatement *s = new StaticAssertStatement((StaticAssert *)sa->syntaxCopy(NULL));
2090 return s;
2093 Statement *StaticAssertStatement::semantic(Scope *sc)
2095 sa->semantic2(sc);
2096 return NULL;
2099 void StaticAssertStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2101 sa->toCBuffer(buf, hgs);
2105 /******************************** SwitchStatement ***************************/
2107 SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b)
2108 : Statement(loc)
2110 condition = c;
2111 body = b;
2112 sdefault = NULL;
2113 cases = NULL;
2114 hasNoDefault = 0;
2117 Statement *SwitchStatement::syntaxCopy()
2119 SwitchStatement *s = new SwitchStatement(loc,
2120 condition->syntaxCopy(), body->syntaxCopy());
2121 return s;
2124 Statement *SwitchStatement::semantic(Scope *sc)
2126 //printf("SwitchStatement::semantic(%p)\n", this);
2127 assert(!cases); // ensure semantic() is only run once
2128 condition = condition->semantic(sc);
2129 condition = resolveProperties(sc, condition);
2130 if (condition->type->isString())
2132 // If it's not an array, cast it to one
2133 if (condition->type->ty != Tarray)
2135 condition = condition->implicitCastTo(sc, condition->type->nextOf()->arrayOf());
2138 else
2139 { condition = condition->integralPromotions(sc);
2140 condition->checkIntegral();
2142 condition = condition->optimize(WANTvalue);
2144 sc = sc->push();
2145 sc->sbreak = this;
2146 sc->sw = this;
2148 cases = new Array();
2149 sc->noctor++; // BUG: should use Scope::mergeCallSuper() for each case instead
2150 body = body->semantic(sc);
2151 sc->noctor--;
2153 // Resolve any goto case's with exp
2154 for (int i = 0; i < gotoCases.dim; i++)
2156 GotoCaseStatement *gcs = (GotoCaseStatement *)gotoCases.data[i];
2158 if (!gcs->exp)
2160 gcs->error("no case statement following goto case;");
2161 break;
2164 for (Scope *scx = sc; scx; scx = scx->enclosing)
2166 if (!scx->sw)
2167 continue;
2168 for (int j = 0; j < scx->sw->cases->dim; j++)
2170 CaseStatement *cs = (CaseStatement *)scx->sw->cases->data[j];
2172 if (cs->exp->equals(gcs->exp))
2174 gcs->cs = cs;
2175 goto Lfoundcase;
2179 gcs->error("case %s not found", gcs->exp->toChars());
2181 Lfoundcase:
2185 if (!sc->sw->sdefault)
2186 { hasNoDefault = 1;
2188 if (global.params.warnings)
2189 { fprintf(stdmsg, "warning - ");
2190 error("switch statement has no default");
2193 // Generate runtime error if the default is hit
2194 Statements *a = new Statements();
2195 CompoundStatement *cs;
2196 Statement *s;
2198 if (global.params.useSwitchError)
2199 s = new SwitchErrorStatement(loc);
2200 else
2201 { Expression *e = new HaltExp(loc);
2202 s = new ExpStatement(loc, e);
2205 a->reserve(4);
2206 a->push(body);
2207 a->push(new BreakStatement(loc, NULL));
2208 sc->sw->sdefault = new DefaultStatement(loc, s);
2209 a->push(sc->sw->sdefault);
2210 cs = new CompoundStatement(loc, a);
2211 body = cs;
2214 sc->pop();
2215 return this;
2218 int SwitchStatement::hasBreak()
2220 return TRUE;
2223 int SwitchStatement::usesEH()
2225 return body ? body->usesEH() : 0;
2228 int SwitchStatement::fallOffEnd()
2230 if (body)
2231 body->fallOffEnd();
2232 return TRUE; // need to do this better
2235 void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2237 buf->writestring("switch (");
2238 condition->toCBuffer(buf, hgs);
2239 buf->writebyte(')');
2240 buf->writenl();
2241 if (body)
2243 if (!body->isScopeStatement())
2244 { buf->writebyte('{');
2245 buf->writenl();
2246 body->toCBuffer(buf, hgs);
2247 buf->writebyte('}');
2248 buf->writenl();
2250 else
2252 body->toCBuffer(buf, hgs);
2257 /******************************** CaseStatement ***************************/
2259 CaseStatement::CaseStatement(Loc loc, Expression *exp, Statement *s)
2260 : Statement(loc)
2262 this->exp = exp;
2263 this->statement = s;
2264 cblock = NULL;
2267 Statement *CaseStatement::syntaxCopy()
2269 CaseStatement *s = new CaseStatement(loc, exp->syntaxCopy(), statement->syntaxCopy());
2270 return s;
2273 Statement *CaseStatement::semantic(Scope *sc)
2274 { SwitchStatement *sw = sc->sw;
2276 //printf("CaseStatement::semantic() %s\n", toChars());
2277 exp = exp->semantic(sc);
2278 if (sw)
2279 { int i;
2281 exp = exp->implicitCastTo(sc, sw->condition->type);
2282 exp = exp->optimize(WANTvalue | WANTinterpret);
2283 if (exp->op != TOKstring && exp->op != TOKint64)
2285 error("case must be a string or an integral constant, not %s", exp->toChars());
2286 exp = new IntegerExp(0);
2289 for (i = 0; i < sw->cases->dim; i++)
2291 CaseStatement *cs = (CaseStatement *)sw->cases->data[i];
2293 //printf("comparing '%s' with '%s'\n", exp->toChars(), cs->exp->toChars());
2294 if (cs->exp->equals(exp))
2295 { error("duplicate case %s in switch statement", exp->toChars());
2296 break;
2300 sw->cases->push(this);
2302 // Resolve any goto case's with no exp to this case statement
2303 for (i = 0; i < sw->gotoCases.dim; i++)
2305 GotoCaseStatement *gcs = (GotoCaseStatement *)sw->gotoCases.data[i];
2307 if (!gcs->exp)
2309 gcs->cs = this;
2310 sw->gotoCases.remove(i); // remove from array
2314 else
2315 error("case not in switch statement");
2316 statement = statement->semantic(sc);
2317 return this;
2320 int CaseStatement::compare(Object *obj)
2322 // Sort cases so we can do an efficient lookup
2323 CaseStatement *cs2 = (CaseStatement *)(obj);
2325 return exp->compare(cs2->exp);
2328 int CaseStatement::usesEH()
2330 return statement->usesEH();
2333 int CaseStatement::fallOffEnd()
2335 return statement->fallOffEnd();
2338 int CaseStatement::comeFrom()
2340 return TRUE;
2343 void CaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2345 buf->writestring("case ");
2346 exp->toCBuffer(buf, hgs);
2347 buf->writebyte(':');
2348 buf->writenl();
2349 statement->toCBuffer(buf, hgs);
2352 /******************************** DefaultStatement ***************************/
2354 DefaultStatement::DefaultStatement(Loc loc, Statement *s)
2355 : Statement(loc)
2357 this->statement = s;
2358 #if IN_GCC
2359 cblock = NULL;
2360 #endif
2363 Statement *DefaultStatement::syntaxCopy()
2365 DefaultStatement *s = new DefaultStatement(loc, statement->syntaxCopy());
2366 return s;
2369 Statement *DefaultStatement::semantic(Scope *sc)
2371 if (sc->sw)
2373 if (sc->sw->sdefault)
2375 error("switch statement already has a default");
2377 sc->sw->sdefault = this;
2379 else
2380 error("default not in switch statement");
2381 statement = statement->semantic(sc);
2382 return this;
2385 int DefaultStatement::usesEH()
2387 return statement->usesEH();
2390 int DefaultStatement::fallOffEnd()
2392 return statement->fallOffEnd();
2395 int DefaultStatement::comeFrom()
2397 return TRUE;
2400 void DefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2402 buf->writestring("default:\n");
2403 statement->toCBuffer(buf, hgs);
2406 /******************************** GotoDefaultStatement ***************************/
2408 GotoDefaultStatement::GotoDefaultStatement(Loc loc)
2409 : Statement(loc)
2411 sw = NULL;
2414 Statement *GotoDefaultStatement::syntaxCopy()
2416 GotoDefaultStatement *s = new GotoDefaultStatement(loc);
2417 return s;
2420 Statement *GotoDefaultStatement::semantic(Scope *sc)
2422 sw = sc->sw;
2423 if (!sw)
2424 error("goto default not in switch statement");
2425 return this;
2428 int GotoDefaultStatement::fallOffEnd()
2430 return FALSE;
2433 void GotoDefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2435 buf->writestring("goto default;\n");
2438 /******************************** GotoCaseStatement ***************************/
2440 GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp)
2441 : Statement(loc)
2443 cs = NULL;
2444 this->exp = exp;
2447 Statement *GotoCaseStatement::syntaxCopy()
2449 Expression *e = exp ? exp->syntaxCopy() : NULL;
2450 GotoCaseStatement *s = new GotoCaseStatement(loc, e);
2451 return s;
2454 Statement *GotoCaseStatement::semantic(Scope *sc)
2456 if (exp)
2457 exp = exp->semantic(sc);
2459 if (!sc->sw)
2460 error("goto case not in switch statement");
2461 else
2463 sc->sw->gotoCases.push(this);
2464 if (exp)
2466 exp = exp->implicitCastTo(sc, sc->sw->condition->type);
2467 exp = exp->optimize(WANTvalue);
2470 return this;
2473 int GotoCaseStatement::fallOffEnd()
2475 return FALSE;
2478 void GotoCaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2480 buf->writestring("goto case");
2481 if (exp)
2482 { buf->writebyte(' ');
2483 exp->toCBuffer(buf, hgs);
2485 buf->writebyte(';');
2486 buf->writenl();
2489 /******************************** SwitchErrorStatement ***************************/
2491 SwitchErrorStatement::SwitchErrorStatement(Loc loc)
2492 : Statement(loc)
2496 int SwitchErrorStatement::fallOffEnd()
2498 return FALSE;
2501 void SwitchErrorStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2503 buf->writestring("SwitchErrorStatement::toCBuffer()");
2504 buf->writenl();
2507 /******************************** ReturnStatement ***************************/
2509 ReturnStatement::ReturnStatement(Loc loc, Expression *exp)
2510 : Statement(loc)
2512 this->exp = exp;
2515 Statement *ReturnStatement::syntaxCopy()
2517 Expression *e = NULL;
2518 if (exp)
2519 e = exp->syntaxCopy();
2520 ReturnStatement *s = new ReturnStatement(loc, e);
2521 return s;
2524 Statement *ReturnStatement::semantic(Scope *sc)
2526 //printf("ReturnStatement::semantic() %s\n", toChars());
2528 FuncDeclaration *fd = sc->parent->isFuncDeclaration();
2529 Scope *scx = sc;
2530 int implicit0 = 0;
2532 if (sc->fes)
2534 // Find scope of function foreach is in
2535 for (; 1; scx = scx->enclosing)
2537 assert(scx);
2538 if (scx->func != fd)
2539 { fd = scx->func; // fd is now function enclosing foreach
2540 break;
2545 Type *tret = fd->type->nextOf();
2546 if (fd->tintro)
2547 tret = fd->tintro->nextOf();
2548 Type *tbret = NULL;
2550 if (tret)
2551 tbret = tret->toBasetype();
2553 // main() returns 0, even if it returns void
2554 if (!exp && (!tbret || tbret->ty == Tvoid) && fd->isMain())
2555 { implicit0 = 1;
2556 exp = new IntegerExp(0);
2559 if (sc->incontract || scx->incontract)
2560 error("return statements cannot be in contracts");
2561 if (sc->tf || scx->tf)
2562 error("return statements cannot be in finally, scope(exit) or scope(success) bodies");
2564 if (fd->isCtorDeclaration())
2566 // Constructors implicitly do:
2567 // return this;
2568 if (exp && exp->op != TOKthis)
2569 error("cannot return expression from constructor");
2570 exp = new ThisExp(0);
2573 if (!exp)
2574 fd->nrvo_can = 0;
2576 if (exp)
2578 fd->hasReturnExp |= 1;
2580 exp = exp->semantic(sc);
2581 exp = resolveProperties(sc, exp);
2582 exp = exp->optimize(WANTvalue);
2584 if (fd->nrvo_can && exp->op == TOKvar)
2585 { VarExp *ve = (VarExp *)exp;
2586 VarDeclaration *v = ve->var->isVarDeclaration();
2588 if (!v || v->isOut() || v->isRef())
2589 fd->nrvo_can = 0;
2590 else if (fd->nrvo_var == NULL)
2591 { if (!v->isDataseg() && !v->isParameter() && v->toParent2() == fd)
2592 fd->nrvo_var = v;
2593 else
2594 fd->nrvo_can = 0;
2596 else if (fd->nrvo_var != v)
2597 fd->nrvo_can = 0;
2599 else
2600 fd->nrvo_can = 0;
2602 if (fd->returnLabel && tbret->ty != Tvoid)
2605 else if (fd->inferRetType)
2607 if (fd->type->nextOf())
2609 if (!exp->type->equals(fd->type->nextOf()))
2610 error("mismatched function return type inference of %s and %s",
2611 exp->type->toChars(), fd->type->nextOf()->toChars());
2613 else
2615 fd->type->next = exp->type;
2616 fd->type = fd->type->semantic(loc, sc);
2617 if (!fd->tintro)
2618 { tret = fd->type->nextOf();
2619 tbret = tret->toBasetype();
2623 else if (tbret->ty != Tvoid)
2625 exp = exp->implicitCastTo(sc, tret);
2628 else if (fd->inferRetType)
2630 if (fd->type->nextOf())
2632 if (fd->type->nextOf()->ty != Tvoid)
2633 error("mismatched function return type inference of void and %s",
2634 fd->type->nextOf()->toChars());
2636 else
2638 fd->type->next = Type::tvoid;
2639 fd->type = fd->type->semantic(loc, sc);
2640 if (!fd->tintro)
2641 { tret = Type::tvoid;
2642 tbret = tret;
2646 else if (tbret->ty != Tvoid) // if non-void return
2647 error("return expression expected");
2649 if (sc->fes)
2651 Statement *s;
2653 if (exp && !implicit0)
2655 exp = exp->implicitCastTo(sc, tret);
2657 if (!exp || exp->op == TOKint64 || exp->op == TOKfloat64 ||
2658 exp->op == TOKimaginary80 || exp->op == TOKcomplex80 ||
2659 exp->op == TOKthis || exp->op == TOKsuper || exp->op == TOKnull ||
2660 exp->op == TOKstring)
2662 sc->fes->cases.push(this);
2663 s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
2665 else if (fd->type->nextOf()->toBasetype() == Type::tvoid)
2667 Statement *s1;
2668 Statement *s2;
2670 s = new ReturnStatement(0, NULL);
2671 sc->fes->cases.push(s);
2673 // Construct: { exp; return cases.dim + 1; }
2674 s1 = new ExpStatement(loc, exp);
2675 s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
2676 s = new CompoundStatement(loc, s1, s2);
2678 else
2680 VarExp *v;
2681 Statement *s1;
2682 Statement *s2;
2684 // Construct: return vresult;
2685 if (!fd->vresult)
2686 { VarDeclaration *v;
2688 v = new VarDeclaration(loc, tret, Id::result, NULL);
2689 v->noauto = 1;
2690 v->semantic(scx);
2691 if (!scx->insert(v))
2692 assert(0);
2693 v->parent = fd;
2694 fd->vresult = v;
2697 v = new VarExp(0, fd->vresult);
2698 s = new ReturnStatement(0, v);
2699 sc->fes->cases.push(s);
2701 // Construct: { vresult = exp; return cases.dim + 1; }
2702 v = new VarExp(0, fd->vresult);
2703 exp = new AssignExp(loc, v, exp);
2704 exp = exp->semantic(sc);
2705 s1 = new ExpStatement(loc, exp);
2706 s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
2707 s = new CompoundStatement(loc, s1, s2);
2709 return s;
2712 if (exp)
2714 if (fd->returnLabel && tbret->ty != Tvoid)
2716 assert(fd->vresult);
2717 VarExp *v = new VarExp(0, fd->vresult);
2719 exp = new AssignExp(loc, v, exp);
2720 exp = exp->semantic(sc);
2722 //exp->dump(0);
2723 //exp->print();
2724 exp->checkEscape();
2727 /* BUG: need to issue an error on:
2728 * this
2729 * { if (x) return;
2730 * super();
2734 if (sc->callSuper & CSXany_ctor &&
2735 !(sc->callSuper & (CSXthis_ctor | CSXsuper_ctor)))
2736 error("return without calling constructor");
2738 sc->callSuper |= CSXreturn;
2740 // See if all returns are instead to be replaced with a goto returnLabel;
2741 if (fd->returnLabel)
2743 GotoStatement *gs = new GotoStatement(loc, Id::returnLabel);
2745 gs->label = fd->returnLabel;
2746 if (exp)
2747 { Statement *s;
2749 s = new ExpStatement(0, exp);
2750 return new CompoundStatement(loc, s, gs);
2752 return gs;
2755 if (exp && tbret->ty == Tvoid && !fd->isMain())
2756 { Statement *s;
2758 s = new ExpStatement(loc, exp);
2759 loc = 0;
2760 exp = NULL;
2761 return new CompoundStatement(loc, s, this);
2764 return this;
2767 int ReturnStatement::fallOffEnd()
2769 return FALSE;
2772 void ReturnStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2774 buf->printf("return ");
2775 if (exp)
2776 exp->toCBuffer(buf, hgs);
2777 buf->writeByte(';');
2778 buf->writenl();
2781 /******************************** BreakStatement ***************************/
2783 BreakStatement::BreakStatement(Loc loc, Identifier *ident)
2784 : Statement(loc)
2786 this->ident = ident;
2789 Statement *BreakStatement::syntaxCopy()
2791 BreakStatement *s = new BreakStatement(loc, ident);
2792 return s;
2795 Statement *BreakStatement::semantic(Scope *sc)
2797 // If:
2798 // break Identifier;
2799 if (ident)
2801 Scope *scx;
2802 FuncDeclaration *thisfunc = sc->func;
2804 for (scx = sc; scx; scx = scx->enclosing)
2806 LabelStatement *ls;
2808 if (scx->func != thisfunc) // if in enclosing function
2810 if (sc->fes) // if this is the body of a foreach
2812 /* Post this statement to the fes, and replace
2813 * it with a return value that caller will put into
2814 * a switch. Caller will figure out where the break
2815 * label actually is.
2816 * Case numbers start with 2, not 0, as 0 is continue
2817 * and 1 is break.
2819 Statement *s;
2820 sc->fes->cases.push(this);
2821 s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
2822 return s;
2824 break; // can't break to it
2827 ls = scx->slabel;
2828 if (ls && ls->ident == ident)
2830 Statement *s = ls->statement;
2832 if (!s->hasBreak())
2833 error("label '%s' has no break", ident->toChars());
2834 if (ls->tf != sc->tf)
2835 error("cannot break out of finally block");
2836 return this;
2839 error("enclosing label '%s' for break not found", ident->toChars());
2841 else if (!sc->sbreak)
2843 if (sc->fes)
2844 { Statement *s;
2846 // Replace break; with return 1;
2847 s = new ReturnStatement(0, new IntegerExp(1));
2848 return s;
2850 error("break is not inside a loop or switch");
2852 return this;
2855 int BreakStatement::fallOffEnd()
2857 return FALSE;
2860 void BreakStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2862 buf->writestring("break");
2863 if (ident)
2864 { buf->writebyte(' ');
2865 buf->writestring(ident->toChars());
2867 buf->writebyte(';');
2868 buf->writenl();
2871 /******************************** ContinueStatement ***************************/
2873 ContinueStatement::ContinueStatement(Loc loc, Identifier *ident)
2874 : Statement(loc)
2876 this->ident = ident;
2879 Statement *ContinueStatement::syntaxCopy()
2881 ContinueStatement *s = new ContinueStatement(loc, ident);
2882 return s;
2885 Statement *ContinueStatement::semantic(Scope *sc)
2887 //printf("ContinueStatement::semantic() %p\n", this);
2888 if (ident)
2890 Scope *scx;
2891 FuncDeclaration *thisfunc = sc->func;
2893 for (scx = sc; scx; scx = scx->enclosing)
2895 LabelStatement *ls;
2897 if (scx->func != thisfunc) // if in enclosing function
2899 if (sc->fes) // if this is the body of a foreach
2901 for (; scx; scx = scx->enclosing)
2903 ls = scx->slabel;
2904 if (ls && ls->ident == ident && ls->statement == sc->fes)
2906 // Replace continue ident; with return 0;
2907 return new ReturnStatement(0, new IntegerExp(0));
2911 /* Post this statement to the fes, and replace
2912 * it with a return value that caller will put into
2913 * a switch. Caller will figure out where the break
2914 * label actually is.
2915 * Case numbers start with 2, not 0, as 0 is continue
2916 * and 1 is break.
2918 Statement *s;
2919 sc->fes->cases.push(this);
2920 s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
2921 return s;
2923 break; // can't continue to it
2926 ls = scx->slabel;
2927 if (ls && ls->ident == ident)
2929 Statement *s = ls->statement;
2931 if (!s->hasContinue())
2932 error("label '%s' has no continue", ident->toChars());
2933 if (ls->tf != sc->tf)
2934 error("cannot continue out of finally block");
2935 return this;
2938 error("enclosing label '%s' for continue not found", ident->toChars());
2940 else if (!sc->scontinue)
2942 if (sc->fes)
2943 { Statement *s;
2945 // Replace continue; with return 0;
2946 s = new ReturnStatement(0, new IntegerExp(0));
2947 return s;
2949 error("continue is not inside a loop");
2951 return this;
2954 int ContinueStatement::fallOffEnd()
2956 return FALSE;
2959 void ContinueStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2961 buf->writestring("continue");
2962 if (ident)
2963 { buf->writebyte(' ');
2964 buf->writestring(ident->toChars());
2966 buf->writebyte(';');
2967 buf->writenl();
2970 /******************************** SynchronizedStatement ***************************/
2972 SynchronizedStatement::SynchronizedStatement(Loc loc, Expression *exp, Statement *body)
2973 : Statement(loc)
2975 this->exp = exp;
2976 this->body = body;
2977 this->esync = NULL;
2980 SynchronizedStatement::SynchronizedStatement(Loc loc, elem *esync, Statement *body)
2981 : Statement(loc)
2983 this->exp = NULL;
2984 this->body = body;
2985 this->esync = esync;
2988 Statement *SynchronizedStatement::syntaxCopy()
2990 Expression *e = exp ? exp->syntaxCopy() : NULL;
2991 SynchronizedStatement *s = new SynchronizedStatement(loc, e, body ? body->syntaxCopy() : NULL);
2992 return s;
2995 Statement *SynchronizedStatement::semantic(Scope *sc)
2997 if (exp)
2998 { ClassDeclaration *cd;
3000 exp = exp->semantic(sc);
3001 exp = resolveProperties(sc, exp);
3002 cd = exp->type->isClassHandle();
3003 if (!cd)
3004 error("can only synchronize on class objects, not '%s'", exp->type->toChars());
3005 else if (cd->isInterfaceDeclaration())
3006 { Type *t = new TypeIdentifier(0, Id::Object);
3008 t = t->semantic(0, sc);
3009 exp = new CastExp(loc, exp, t);
3010 exp = exp->semantic(sc);
3013 if (body)
3014 body = body->semantic(sc);
3015 return this;
3018 int SynchronizedStatement::hasBreak()
3020 return FALSE; //TRUE;
3023 int SynchronizedStatement::hasContinue()
3025 return FALSE; //TRUE;
3028 int SynchronizedStatement::usesEH()
3030 return TRUE;
3033 int SynchronizedStatement::fallOffEnd()
3035 return body ? body->fallOffEnd() : TRUE;
3038 void SynchronizedStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3040 buf->writestring("synchronized");
3041 if (exp)
3042 { buf->writebyte('(');
3043 exp->toCBuffer(buf, hgs);
3044 buf->writebyte(')');
3046 if (body)
3048 buf->writebyte(' ');
3049 body->toCBuffer(buf, hgs);
3053 /******************************** WithStatement ***************************/
3055 WithStatement::WithStatement(Loc loc, Expression *exp, Statement *body)
3056 : Statement(loc)
3058 this->exp = exp;
3059 this->body = body;
3060 wthis = NULL;
3063 Statement *WithStatement::syntaxCopy()
3065 WithStatement *s = new WithStatement(loc, exp->syntaxCopy(), body ? body->syntaxCopy() : NULL);
3066 return s;
3069 Statement *WithStatement::semantic(Scope *sc)
3070 { ScopeDsymbol *sym;
3071 Initializer *init;
3073 //printf("WithStatement::semantic()\n");
3074 exp = exp->semantic(sc);
3075 exp = resolveProperties(sc, exp);
3076 if (exp->op == TOKimport)
3077 { ScopeExp *es = (ScopeExp *)exp;
3079 sym = es->sds;
3081 else if (exp->op == TOKtype)
3082 { TypeExp *es = (TypeExp *)exp;
3084 sym = es->type->toDsymbol(sc)->isScopeDsymbol();
3085 if (!sym)
3086 { error("%s has no members", es->toChars());
3087 body = body->semantic(sc);
3088 return this;
3091 else
3092 { Type *t = exp->type;
3094 assert(t);
3095 t = t->toBasetype();
3096 if (t->isClassHandle())
3098 init = new ExpInitializer(loc, exp);
3099 wthis = new VarDeclaration(loc, exp->type, Id::withSym, init);
3100 wthis->semantic(sc);
3102 sym = new WithScopeSymbol(this);
3103 sym->parent = sc->scopesym;
3105 else if (t->ty == Tstruct)
3107 Expression *e = exp->addressOf(sc);
3108 init = new ExpInitializer(loc, e);
3109 wthis = new VarDeclaration(loc, e->type, Id::withSym, init);
3110 wthis->semantic(sc);
3111 sym = new WithScopeSymbol(this);
3112 sym->parent = sc->scopesym;
3114 else
3115 { error("with expressions must be class objects, not '%s'", exp->type->toChars());
3116 return NULL;
3119 sc = sc->push(sym);
3121 if (body)
3122 body = body->semantic(sc);
3124 sc->pop();
3126 return this;
3129 void WithStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3131 buf->writestring("with (");
3132 exp->toCBuffer(buf, hgs);
3133 buf->writestring(")\n");
3134 if (body)
3135 body->toCBuffer(buf, hgs);
3138 int WithStatement::usesEH()
3140 return body ? body->usesEH() : 0;
3143 int WithStatement::fallOffEnd()
3145 return body ? body->fallOffEnd() : TRUE;
3148 /******************************** TryCatchStatement ***************************/
3150 TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Array *catches)
3151 : Statement(loc)
3153 this->body = body;
3154 this->catches = catches;
3157 Statement *TryCatchStatement::syntaxCopy()
3159 Array *a = new Array();
3160 a->setDim(catches->dim);
3161 for (int i = 0; i < a->dim; i++)
3162 { Catch *c;
3164 c = (Catch *)catches->data[i];
3165 c = c->syntaxCopy();
3166 a->data[i] = c;
3168 TryCatchStatement *s = new TryCatchStatement(loc, body->syntaxCopy(), a);
3169 return s;
3172 Statement *TryCatchStatement::semantic(Scope *sc)
3174 body = body->semanticScope(sc, NULL /*this*/, NULL);
3176 for (int i = 0; i < catches->dim; i++)
3177 { Catch *c;
3179 c = (Catch *)catches->data[i];
3180 c->semantic(sc);
3182 // Determine if current catch 'hides' any previous catches
3183 for (int j = 0; j < i; j++)
3184 { Catch *cj = (Catch *)catches->data[j];
3185 char *si = c->loc.toChars();
3186 char *sj = cj->loc.toChars();
3188 if (c->type->toBasetype()->implicitConvTo(cj->type->toBasetype()))
3189 error("catch at %s hides catch at %s", sj, si);
3192 return this;
3195 int TryCatchStatement::hasBreak()
3197 return FALSE; //TRUE;
3200 int TryCatchStatement::usesEH()
3202 return TRUE;
3205 int TryCatchStatement::fallOffEnd()
3207 int result = FALSE;
3209 if (body)
3210 result = body->fallOffEnd();
3211 for (int i = 0; i < catches->dim; i++)
3212 { Catch *c;
3214 c = (Catch *)catches->data[i];
3215 if (c->handler)
3216 result |= c->handler->fallOffEnd();
3218 return result;
3221 void TryCatchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3223 buf->writestring("try");
3224 buf->writenl();
3225 if (body)
3226 body->toCBuffer(buf, hgs);
3227 int i;
3228 for (i = 0; i < catches->dim; i++)
3230 Catch *c = (Catch *)catches->data[i];
3231 c->toCBuffer(buf, hgs);
3235 /******************************** Catch ***************************/
3237 Catch::Catch(Loc loc, Type *t, Identifier *id, Statement *handler)
3239 //printf("Catch(%s, loc = %s)\n", id->toChars(), loc.toChars());
3240 this->loc = loc;
3241 this->type = t;
3242 this->ident = id;
3243 this->handler = handler;
3244 var = NULL;
3247 Catch *Catch::syntaxCopy()
3249 Catch *c = new Catch(loc,
3250 (type ? type->syntaxCopy() : NULL),
3251 ident,
3252 (handler ? handler->syntaxCopy() : NULL));
3253 return c;
3256 void Catch::semantic(Scope *sc)
3257 { ScopeDsymbol *sym;
3259 //printf("Catch::semantic(%s)\n", ident->toChars());
3261 #ifndef IN_GCC
3262 if (sc->tf)
3264 /* This is because the _d_local_unwind() gets the stack munged
3265 * up on this. The workaround is to place any try-catches into
3266 * a separate function, and call that.
3267 * To fix, have the compiler automatically convert the finally
3268 * body into a nested function.
3270 error(loc, "cannot put catch statement inside finally block");
3272 #endif
3274 sym = new ScopeDsymbol();
3275 sym->parent = sc->scopesym;
3276 sc = sc->push(sym);
3278 if (!type)
3279 type = new TypeIdentifier(0, Id::Object);
3280 type = type->semantic(loc, sc);
3281 if (!type->toBasetype()->isClassHandle())
3282 error("can only catch class objects, not '%s'", type->toChars());
3283 else if (ident)
3285 var = new VarDeclaration(loc, type, ident, NULL);
3286 var->parent = sc->parent;
3287 sc->insert(var);
3289 handler = handler->semantic(sc);
3291 sc->pop();
3294 void Catch::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3296 buf->writestring("catch");
3297 if (type)
3298 { buf->writebyte('(');
3299 type->toCBuffer(buf, ident, hgs);
3300 buf->writebyte(')');
3302 buf->writenl();
3303 buf->writebyte('{');
3304 buf->writenl();
3305 handler->toCBuffer(buf, hgs);
3306 buf->writebyte('}');
3307 buf->writenl();
3310 /****************************** TryFinallyStatement ***************************/
3312 TryFinallyStatement::TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody)
3313 : Statement(loc)
3315 this->body = body;
3316 this->finalbody = finalbody;
3319 Statement *TryFinallyStatement::syntaxCopy()
3321 TryFinallyStatement *s = new TryFinallyStatement(loc,
3322 body->syntaxCopy(), finalbody->syntaxCopy());
3323 return s;
3326 Statement *TryFinallyStatement::semantic(Scope *sc)
3328 //printf("TryFinallyStatement::semantic()\n");
3329 body = body->semantic(sc);
3330 sc = sc->push();
3331 sc->tf = this;
3332 sc->sbreak = NULL;
3333 sc->scontinue = NULL; // no break or continue out of finally block
3334 finalbody = finalbody->semantic(sc);
3335 sc->pop();
3336 return this;
3339 void TryFinallyStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3341 buf->printf("try\n{\n");
3342 body->toCBuffer(buf, hgs);
3343 buf->printf("}\nfinally\n{\n");
3344 finalbody->toCBuffer(buf, hgs);
3345 buf->writeByte('}');
3346 buf->writenl();
3349 int TryFinallyStatement::hasBreak()
3351 return FALSE; //TRUE;
3354 int TryFinallyStatement::hasContinue()
3356 return FALSE; //TRUE;
3359 int TryFinallyStatement::usesEH()
3361 return TRUE;
3364 int TryFinallyStatement::fallOffEnd()
3365 { int result;
3367 result = body ? body->fallOffEnd() : TRUE;
3368 // if (finalbody)
3369 // result = finalbody->fallOffEnd();
3370 return result;
3373 /****************************** OnScopeStatement ***************************/
3375 OnScopeStatement::OnScopeStatement(Loc loc, TOK tok, Statement *statement)
3376 : Statement(loc)
3378 this->tok = tok;
3379 this->statement = statement;
3382 Statement *OnScopeStatement::syntaxCopy()
3384 OnScopeStatement *s = new OnScopeStatement(loc,
3385 tok, statement->syntaxCopy());
3386 return s;
3389 Statement *OnScopeStatement::semantic(Scope *sc)
3391 /* semantic is called on results of scopeCode() */
3392 return this;
3395 void OnScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3397 buf->writestring(Token::toChars(tok));
3398 buf->writebyte(' ');
3399 statement->toCBuffer(buf, hgs);
3402 int OnScopeStatement::usesEH()
3404 return (tok != TOKon_scope_success);
3407 void OnScopeStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally)
3409 //printf("OnScopeStatement::scopeCode()\n");
3410 //print();
3411 *sentry = NULL;
3412 *sexception = NULL;
3413 *sfinally = NULL;
3414 switch (tok)
3416 case TOKon_scope_exit:
3417 *sfinally = statement;
3418 break;
3420 case TOKon_scope_failure:
3421 *sexception = statement;
3422 break;
3424 case TOKon_scope_success:
3426 /* Create:
3427 * sentry: int x = 0;
3428 * sexception: x = 1;
3429 * sfinally: if (!x) statement;
3431 static int num;
3432 char name[5 + sizeof(num) * 3 + 1];
3433 sprintf(name, "__osf%d", ++num);
3434 Identifier *id = Lexer::idPool(name);
3436 ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(0));
3437 VarDeclaration *v = new VarDeclaration(loc, Type::tint32, id, ie);
3438 *sentry = new DeclarationStatement(loc, v);
3440 Expression *e = new IntegerExp(1);
3441 e = new AssignExp(0, new VarExp(0, v), e);
3442 *sexception = new ExpStatement(0, e);
3444 e = new VarExp(0, v);
3445 e = new NotExp(0, e);
3446 *sfinally = new IfStatement(0, NULL, e, statement, NULL);
3448 break;
3451 default:
3452 assert(0);
3456 /******************************** ThrowStatement ***************************/
3458 ThrowStatement::ThrowStatement(Loc loc, Expression *exp)
3459 : Statement(loc)
3461 this->exp = exp;
3464 Statement *ThrowStatement::syntaxCopy()
3466 ThrowStatement *s = new ThrowStatement(loc, exp->syntaxCopy());
3467 return s;
3470 Statement *ThrowStatement::semantic(Scope *sc)
3472 //printf("ThrowStatement::semantic()\n");
3474 FuncDeclaration *fd = sc->parent->isFuncDeclaration();
3475 fd->hasReturnExp |= 2;
3477 if (sc->incontract)
3478 error("Throw statements cannot be in contracts");
3479 exp = exp->semantic(sc);
3480 exp = resolveProperties(sc, exp);
3481 if (!exp->type->toBasetype()->isClassHandle())
3482 error("can only throw class objects, not type %s", exp->type->toChars());
3483 return this;
3486 int ThrowStatement::fallOffEnd()
3488 return FALSE;
3491 void ThrowStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3493 buf->printf("throw ");
3494 exp->toCBuffer(buf, hgs);
3495 buf->writeByte(';');
3496 buf->writenl();
3499 /******************************** VolatileStatement **************************/
3501 VolatileStatement::VolatileStatement(Loc loc, Statement *statement)
3502 : Statement(loc)
3504 this->statement = statement;
3507 Statement *VolatileStatement::syntaxCopy()
3509 VolatileStatement *s = new VolatileStatement(loc,
3510 statement ? statement->syntaxCopy() : NULL);
3511 return s;
3514 Statement *VolatileStatement::semantic(Scope *sc)
3516 statement = statement ? statement->semantic(sc) : NULL;
3517 return this;
3520 Statements *VolatileStatement::flatten(Scope *sc)
3522 Statements *a;
3524 a = statement ? statement->flatten(sc) : NULL;
3525 if (a)
3526 { for (int i = 0; i < a->dim; i++)
3527 { Statement *s = (Statement *)a->data[i];
3529 s = new VolatileStatement(loc, s);
3530 a->data[i] = s;
3534 return a;
3537 int VolatileStatement::fallOffEnd()
3539 return statement ? statement->fallOffEnd() : TRUE;
3542 void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3544 buf->writestring("volatile");
3545 if (statement)
3546 { if (statement->isScopeStatement())
3547 buf->writenl();
3548 else
3549 buf->writebyte(' ');
3550 statement->toCBuffer(buf, hgs);
3555 /******************************** GotoStatement ***************************/
3557 GotoStatement::GotoStatement(Loc loc, Identifier *ident)
3558 : Statement(loc)
3560 this->ident = ident;
3561 this->label = NULL;
3562 this->tf = NULL;
3565 Statement *GotoStatement::syntaxCopy()
3567 GotoStatement *s = new GotoStatement(loc, ident);
3568 return s;
3571 Statement *GotoStatement::semantic(Scope *sc)
3572 { FuncDeclaration *fd = sc->parent->isFuncDeclaration();
3574 //printf("GotoStatement::semantic()\n");
3575 tf = sc->tf;
3576 label = fd->searchLabel(ident);
3577 if (!label->statement && sc->fes)
3579 /* Either the goto label is forward referenced or it
3580 * is in the function that the enclosing foreach is in.
3581 * Can't know yet, so wrap the goto in a compound statement
3582 * so we can patch it later, and add it to a 'look at this later'
3583 * list.
3585 Statements *a = new Statements();
3586 Statement *s;
3588 a->push(this);
3589 s = new CompoundStatement(loc, a);
3590 sc->fes->gotos.push(s); // 'look at this later' list
3591 return s;
3593 if (label->statement && label->statement->tf != sc->tf)
3594 error("cannot goto in or out of finally block");
3595 return this;
3598 int GotoStatement::fallOffEnd()
3600 return FALSE;
3603 void GotoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3605 buf->writestring("goto ");
3606 buf->writestring(ident->toChars());
3607 buf->writebyte(';');
3608 buf->writenl();
3611 /******************************** LabelStatement ***************************/
3613 LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement)
3614 : Statement(loc)
3616 this->ident = ident;
3617 this->statement = statement;
3618 this->tf = NULL;
3619 this->lblock = NULL;
3620 this->isReturnLabel = 0;
3623 Statement *LabelStatement::syntaxCopy()
3625 LabelStatement *s = new LabelStatement(loc, ident, statement->syntaxCopy());
3626 return s;
3629 Statement *LabelStatement::semantic(Scope *sc)
3630 { LabelDsymbol *ls;
3631 FuncDeclaration *fd = sc->parent->isFuncDeclaration();
3633 //printf("LabelStatement::semantic()\n");
3634 ls = fd->searchLabel(ident);
3635 if (ls->statement)
3636 error("Label '%s' already defined", ls->toChars());
3637 else
3638 ls->statement = this;
3639 tf = sc->tf;
3640 sc = sc->push();
3641 sc->scopesym = sc->enclosing->scopesym;
3642 sc->callSuper |= CSXlabel;
3643 sc->slabel = this;
3644 if (statement)
3645 statement = statement->semantic(sc);
3646 sc->pop();
3647 return this;
3650 Statements *LabelStatement::flatten(Scope *sc)
3652 Statements *a = NULL;
3654 if (statement)
3656 a = statement->flatten(sc);
3657 if (a)
3659 if (!a->dim)
3661 a->push(new ExpStatement(loc, NULL));
3663 Statement *s = (Statement *)a->data[0];
3665 s = new LabelStatement(loc, ident, s);
3666 a->data[0] = s;
3670 return a;
3674 int LabelStatement::usesEH()
3676 return statement ? statement->usesEH() : FALSE;
3679 int LabelStatement::fallOffEnd()
3681 return statement ? statement->fallOffEnd() : TRUE;
3684 int LabelStatement::comeFrom()
3686 //printf("LabelStatement::comeFrom()\n");
3687 return TRUE;
3690 void LabelStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3692 buf->writestring(ident->toChars());
3693 buf->writebyte(':');
3694 buf->writenl();
3695 if (statement)
3696 statement->toCBuffer(buf, hgs);
3700 /******************************** LabelDsymbol ***************************/
3702 LabelDsymbol::LabelDsymbol(Identifier *ident)
3703 : Dsymbol(ident)
3705 statement = NULL;
3706 #if IN_GCC
3707 asmLabelNum = 0;
3708 #endif
3711 LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()?
3713 return this;