Mercurial > projects > ldc
comparison dmd2/statement.c @ 1452:638d16625da2
LDC 2 compiles again.
author | Robert Clipsham <robert@octarineparrot.com> |
---|---|
date | Sat, 30 May 2009 17:23:32 +0100 |
parents | 5fa3e0ea06e9 |
children | 54b3c1394d62 |
comparison
equal
deleted
inserted
replaced
1423:42bd767ec5a4 | 1452:638d16625da2 |
---|---|
1 | 1 |
2 // Compiler implementation of the D programming language | 2 // Compiler implementation of the D programming language |
3 // Copyright (c) 1999-2008 by Digital Mars | 3 // Copyright (c) 1999-2009 by Digital Mars |
4 // All Rights Reserved | 4 // All Rights Reserved |
5 // written by Walter Bright | 5 // written by Walter Bright |
6 // http://www.digitalmars.com | 6 // http://www.digitalmars.com |
7 // License for redistribution is by either the Artistic License | 7 // License for redistribution is by either the Artistic License |
8 // in artistic.txt, or the GNU General Public License in gnu.txt. | 8 // in artistic.txt, or the GNU General Public License in gnu.txt. |
10 | 10 |
11 #include <stdio.h> | 11 #include <stdio.h> |
12 #include <stdlib.h> | 12 #include <stdlib.h> |
13 #include <assert.h> | 13 #include <assert.h> |
14 | 14 |
15 #include "mem.h" | 15 #include "rmem.h" |
16 | 16 |
17 #include "statement.h" | 17 #include "statement.h" |
18 #include "expression.h" | 18 #include "expression.h" |
19 #include "cond.h" | 19 #include "cond.h" |
20 #include "init.h" | 20 #include "init.h" |
25 #include "aggregate.h" | 25 #include "aggregate.h" |
26 #include "id.h" | 26 #include "id.h" |
27 #include "hdrgen.h" | 27 #include "hdrgen.h" |
28 #include "parse.h" | 28 #include "parse.h" |
29 #include "template.h" | 29 #include "template.h" |
30 #include "attrib.h" | |
30 | 31 |
31 /******************************** Statement ***************************/ | 32 /******************************** Statement ***************************/ |
32 | 33 |
33 Statement::Statement(Loc loc) | 34 Statement::Statement(Loc loc) |
34 : loc(loc) | 35 : loc(loc) |
94 va_start(ap, format); | 95 va_start(ap, format); |
95 ::verror(loc, format, ap); | 96 ::verror(loc, format, ap); |
96 va_end( ap ); | 97 va_end( ap ); |
97 } | 98 } |
98 | 99 |
100 void Statement::warning(const char *format, ...) | |
101 { | |
102 if (global.params.warnings && !global.gag) | |
103 { | |
104 va_list ap; | |
105 va_start(ap, format); | |
106 ::vwarning(loc, format, ap); | |
107 va_end( ap ); | |
108 } | |
109 } | |
110 | |
99 int Statement::hasBreak() | 111 int Statement::hasBreak() |
100 { | 112 { |
101 //printf("Statement::hasBreak()\n"); | 113 //printf("Statement::hasBreak()\n"); |
102 return FALSE; | 114 return FALSE; |
103 } | 115 } |
120 { | 132 { |
121 printf("Statement::blockExit(%p)\n", this); | 133 printf("Statement::blockExit(%p)\n", this); |
122 printf("%s\n", toChars()); | 134 printf("%s\n", toChars()); |
123 assert(0); | 135 assert(0); |
124 return BEany; | 136 return BEany; |
125 } | |
126 | |
127 // TRUE if statement may fall off the end without a throw or return | |
128 | |
129 int Statement::fallOffEnd() | |
130 { | |
131 return TRUE; | |
132 } | 137 } |
133 | 138 |
134 // TRUE if statement 'comes from' somewhere else, like a goto | 139 // TRUE if statement 'comes from' somewhere else, like a goto |
135 | 140 |
136 int Statement::comeFrom() | 141 int Statement::comeFrom() |
229 result |= BEthrow; | 234 result |= BEthrow; |
230 } | 235 } |
231 return result; | 236 return result; |
232 } | 237 } |
233 | 238 |
234 int ExpStatement::fallOffEnd() | |
235 { | |
236 if (exp) | |
237 { | |
238 if (exp->op == TOKassert) | |
239 { AssertExp *a = (AssertExp *)exp; | |
240 | |
241 if (a->e1->isBool(FALSE)) // if it's an assert(0) | |
242 return FALSE; | |
243 } | |
244 else if (exp->op == TOKhalt) | |
245 return FALSE; | |
246 } | |
247 return TRUE; | |
248 } | |
249 | 239 |
250 /******************************** CompileStatement ***************************/ | 240 /******************************** CompileStatement ***************************/ |
251 | 241 |
252 CompileStatement::CompileStatement(Loc loc, Expression *exp) | 242 CompileStatement::CompileStatement(Loc loc, Expression *exp) |
253 : Statement(loc) | 243 : Statement(loc) |
563 { | 553 { |
564 //printf("result = x%x\n", result); | 554 //printf("result = x%x\n", result); |
565 //printf("%s\n", s->toChars()); | 555 //printf("%s\n", s->toChars()); |
566 if (!(result & BEfallthru) && !s->comeFrom()) | 556 if (!(result & BEfallthru) && !s->comeFrom()) |
567 { | 557 { |
568 if (global.params.warnings) | 558 s->warning("statement is not reachable"); |
569 { fprintf(stdmsg, "warning - "); | |
570 s->error("statement is not reachable"); | |
571 } | |
572 } | 559 } |
573 | 560 |
574 result &= ~BEfallthru; | 561 result &= ~BEfallthru; |
575 result |= s->blockExit(); | 562 result |= s->blockExit(); |
576 } | 563 } |
577 } | 564 } |
578 return result; | 565 return result; |
579 } | |
580 | |
581 int CompoundStatement::fallOffEnd() | |
582 { int falloff = TRUE; | |
583 | |
584 //printf("CompoundStatement::fallOffEnd() %s\n", toChars()); | |
585 for (int i = 0; i < statements->dim; i++) | |
586 { Statement *s = (Statement *)statements->data[i]; | |
587 | |
588 if (!s) | |
589 continue; | |
590 | |
591 #if 0 | |
592 if (!falloff && global.params.warnings && !s->comeFrom()) | |
593 { | |
594 warning("%s: statement is not reachable", s->loc.toChars()); | |
595 } | |
596 #endif | |
597 falloff = s->fallOffEnd(); | |
598 } | |
599 return falloff; | |
600 } | 566 } |
601 | 567 |
602 int CompoundStatement::comeFrom() | 568 int CompoundStatement::comeFrom() |
603 { int comefrom = FALSE; | 569 { int comefrom = FALSE; |
604 | 570 |
613 } | 579 } |
614 return comefrom; | 580 return comefrom; |
615 } | 581 } |
616 | 582 |
617 | 583 |
618 /**************************** UnrolledLoopStatement ***************************/ | 584 /******************************** CompoundDeclarationStatement ***************************/ |
619 | 585 |
620 UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s) | 586 CompoundDeclarationStatement::CompoundDeclarationStatement(Loc loc, Statements *s) |
621 : Statement(loc) | 587 : CompoundStatement(loc, s) |
622 { | 588 { |
623 statements = s; | 589 statements = s; |
624 enclosinghandler = NULL; | 590 } |
625 } | 591 |
626 | 592 Statement *CompoundDeclarationStatement::syntaxCopy() |
627 Statement *UnrolledLoopStatement::syntaxCopy() | |
628 { | 593 { |
629 Statements *a = new Statements(); | 594 Statements *a = new Statements(); |
630 a->setDim(statements->dim); | 595 a->setDim(statements->dim); |
631 for (size_t i = 0; i < statements->dim; i++) | 596 for (size_t i = 0; i < statements->dim; i++) |
632 { Statement *s = (Statement *)statements->data[i]; | 597 { Statement *s = (Statement *)statements->data[i]; |
633 if (s) | 598 if (s) |
634 s = s->syntaxCopy(); | 599 s = s->syntaxCopy(); |
635 a->data[i] = s; | 600 a->data[i] = s; |
636 } | 601 } |
602 CompoundDeclarationStatement *cs = new CompoundDeclarationStatement(loc, a); | |
603 return cs; | |
604 } | |
605 | |
606 void CompoundDeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
607 { | |
608 int nwritten = 0; | |
609 for (int i = 0; i < statements->dim; i++) | |
610 { Statement *s = (Statement *) statements->data[i]; | |
611 if (s) | |
612 { DeclarationStatement *ds = s->isDeclarationStatement(); | |
613 assert(ds); | |
614 DeclarationExp *de = (DeclarationExp *)ds->exp; | |
615 assert(de->op == TOKdeclaration); | |
616 Declaration *d = de->declaration->isDeclaration(); | |
617 assert(d); | |
618 VarDeclaration *v = d->isVarDeclaration(); | |
619 if (v) | |
620 { | |
621 /* This essentially copies the part of VarDeclaration::toCBuffer() | |
622 * that does not print the type. | |
623 * Should refactor this. | |
624 */ | |
625 if (nwritten) | |
626 { | |
627 buf->writeByte(','); | |
628 buf->writestring(v->ident->toChars()); | |
629 } | |
630 else | |
631 { | |
632 StorageClassDeclaration::stcToCBuffer(buf, v->storage_class); | |
633 if (v->type) | |
634 v->type->toCBuffer(buf, v->ident, hgs); | |
635 else | |
636 buf->writestring(v->ident->toChars()); | |
637 } | |
638 | |
639 if (v->init) | |
640 { buf->writestring(" = "); | |
641 #if DMDV2 | |
642 ExpInitializer *ie = v->init->isExpInitializer(); | |
643 if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit)) | |
644 ((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs); | |
645 else | |
646 #endif | |
647 v->init->toCBuffer(buf, hgs); | |
648 } | |
649 } | |
650 else | |
651 d->toCBuffer(buf, hgs); | |
652 nwritten++; | |
653 } | |
654 } | |
655 buf->writeByte(';'); | |
656 if (!hgs->FLinit.init) | |
657 buf->writenl(); | |
658 } | |
659 | |
660 /**************************** UnrolledLoopStatement ***************************/ | |
661 | |
662 UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s) | |
663 : Statement(loc) | |
664 { | |
665 statements = s; | |
666 } | |
667 | |
668 Statement *UnrolledLoopStatement::syntaxCopy() | |
669 { | |
670 Statements *a = new Statements(); | |
671 a->setDim(statements->dim); | |
672 for (size_t i = 0; i < statements->dim; i++) | |
673 { Statement *s = (Statement *)statements->data[i]; | |
674 if (s) | |
675 s = s->syntaxCopy(); | |
676 a->data[i] = s; | |
677 } | |
637 UnrolledLoopStatement *cs = new UnrolledLoopStatement(loc, a); | 678 UnrolledLoopStatement *cs = new UnrolledLoopStatement(loc, a); |
638 return cs; | 679 return cs; |
639 } | 680 } |
640 | 681 |
641 | 682 |
642 Statement *UnrolledLoopStatement::semantic(Scope *sc) | 683 Statement *UnrolledLoopStatement::semantic(Scope *sc) |
643 { | 684 { |
644 //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc); | 685 //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc); |
645 | |
646 enclosinghandler = sc->tfOfTry; | |
647 | 686 |
648 sc->noctor++; | 687 sc->noctor++; |
649 Scope *scd = sc->push(); | 688 Scope *scd = sc->push(); |
650 scd->sbreak = this; | 689 scd->sbreak = this; |
651 scd->scontinue = this; | 690 scd->scontinue = this; |
714 } | 753 } |
715 } | 754 } |
716 return result; | 755 return result; |
717 } | 756 } |
718 | 757 |
719 int UnrolledLoopStatement::fallOffEnd() | |
720 { | |
721 //printf("UnrolledLoopStatement::fallOffEnd()\n"); | |
722 for (size_t i = 0; i < statements->dim; i++) | |
723 { Statement *s = (Statement *)statements->data[i]; | |
724 | |
725 if (s) | |
726 s->fallOffEnd(); | |
727 } | |
728 return TRUE; | |
729 } | |
730 | 758 |
731 int UnrolledLoopStatement::comeFrom() | 759 int UnrolledLoopStatement::comeFrom() |
732 { int comefrom = FALSE; | 760 { int comefrom = FALSE; |
733 | 761 |
734 //printf("UnrolledLoopStatement::comeFrom()\n"); | 762 //printf("UnrolledLoopStatement::comeFrom()\n"); |
819 { | 847 { |
820 //printf("ScopeStatement::blockExit(%p)\n", statement); | 848 //printf("ScopeStatement::blockExit(%p)\n", statement); |
821 return statement ? statement->blockExit() : BEfallthru; | 849 return statement ? statement->blockExit() : BEfallthru; |
822 } | 850 } |
823 | 851 |
824 int ScopeStatement::fallOffEnd() | |
825 { | |
826 return statement ? statement->fallOffEnd() : TRUE; | |
827 } | |
828 | 852 |
829 int ScopeStatement::comeFrom() | 853 int ScopeStatement::comeFrom() |
830 { | 854 { |
831 //printf("ScopeStatement::comeFrom()\n"); | 855 //printf("ScopeStatement::comeFrom()\n"); |
832 return statement ? statement->comeFrom() : FALSE; | 856 return statement ? statement->comeFrom() : FALSE; |
849 WhileStatement::WhileStatement(Loc loc, Expression *c, Statement *b) | 873 WhileStatement::WhileStatement(Loc loc, Expression *c, Statement *b) |
850 : Statement(loc) | 874 : Statement(loc) |
851 { | 875 { |
852 condition = c; | 876 condition = c; |
853 body = b; | 877 body = b; |
854 enclosinghandler = NULL; | |
855 } | 878 } |
856 | 879 |
857 Statement *WhileStatement::syntaxCopy() | 880 Statement *WhileStatement::syntaxCopy() |
858 { | 881 { |
859 WhileStatement *s = new WhileStatement(loc, condition->syntaxCopy(), body ? body->syntaxCopy() : NULL); | 882 WhileStatement *s = new WhileStatement(loc, condition->syntaxCopy(), body ? body->syntaxCopy() : NULL); |
884 Statement *si = new IfStatement(loc, condition, sw, NULL); | 907 Statement *si = new IfStatement(loc, condition, sw, NULL); |
885 return si->semantic(sc); | 908 return si->semantic(sc); |
886 } | 909 } |
887 #endif | 910 #endif |
888 | 911 |
889 enclosinghandler = sc->tfOfTry; | |
890 | |
891 condition = condition->semantic(sc); | 912 condition = condition->semantic(sc); |
892 condition = resolveProperties(sc, condition); | 913 condition = resolveProperties(sc, condition); |
893 condition = condition->optimize(WANTvalue); | 914 condition = condition->optimize(WANTvalue); |
894 condition = condition->checkToBoolean(); | 915 condition = condition->checkToBoolean(); |
895 | 916 |
949 } | 970 } |
950 result &= ~(BEbreak | BEcontinue); | 971 result &= ~(BEbreak | BEcontinue); |
951 return result; | 972 return result; |
952 } | 973 } |
953 | 974 |
954 int WhileStatement::fallOffEnd() | |
955 { | |
956 if (body) | |
957 body->fallOffEnd(); | |
958 return TRUE; | |
959 } | |
960 | 975 |
961 int WhileStatement::comeFrom() | 976 int WhileStatement::comeFrom() |
962 { | 977 { |
963 if (body) | 978 if (body) |
964 return body->comeFrom(); | 979 return body->comeFrom(); |
980 DoStatement::DoStatement(Loc loc, Statement *b, Expression *c) | 995 DoStatement::DoStatement(Loc loc, Statement *b, Expression *c) |
981 : Statement(loc) | 996 : Statement(loc) |
982 { | 997 { |
983 body = b; | 998 body = b; |
984 condition = c; | 999 condition = c; |
985 enclosinghandler = NULL; | |
986 } | 1000 } |
987 | 1001 |
988 Statement *DoStatement::syntaxCopy() | 1002 Statement *DoStatement::syntaxCopy() |
989 { | 1003 { |
990 DoStatement *s = new DoStatement(loc, body ? body->syntaxCopy() : NULL, condition->syntaxCopy()); | 1004 DoStatement *s = new DoStatement(loc, body ? body->syntaxCopy() : NULL, condition->syntaxCopy()); |
992 } | 1006 } |
993 | 1007 |
994 | 1008 |
995 Statement *DoStatement::semantic(Scope *sc) | 1009 Statement *DoStatement::semantic(Scope *sc) |
996 { | 1010 { |
997 enclosinghandler = sc->tfOfTry; | |
998 | |
999 sc->noctor++; | 1011 sc->noctor++; |
1000 if (body) | 1012 if (body) |
1001 body = body->semanticScope(sc, this, this); | 1013 body = body->semanticScope(sc, this, this); |
1002 sc->noctor--; | 1014 sc->noctor--; |
1003 condition = condition->semantic(sc); | 1015 condition = condition->semantic(sc); |
1044 } | 1056 } |
1045 result &= ~(BEbreak | BEcontinue); | 1057 result &= ~(BEbreak | BEcontinue); |
1046 return result; | 1058 return result; |
1047 } | 1059 } |
1048 | 1060 |
1049 int DoStatement::fallOffEnd() | |
1050 { | |
1051 if (body) | |
1052 body->fallOffEnd(); | |
1053 return TRUE; | |
1054 } | |
1055 | 1061 |
1056 int DoStatement::comeFrom() | 1062 int DoStatement::comeFrom() |
1057 { | 1063 { |
1058 if (body) | 1064 if (body) |
1059 return body->comeFrom(); | 1065 return body->comeFrom(); |
1078 { | 1084 { |
1079 this->init = init; | 1085 this->init = init; |
1080 this->condition = condition; | 1086 this->condition = condition; |
1081 this->increment = increment; | 1087 this->increment = increment; |
1082 this->body = body; | 1088 this->body = body; |
1083 this->enclosinghandler = NULL; | |
1084 } | 1089 } |
1085 | 1090 |
1086 Statement *ForStatement::syntaxCopy() | 1091 Statement *ForStatement::syntaxCopy() |
1087 { | 1092 { |
1088 Statement *i = NULL; | 1093 Statement *i = NULL; |
1098 return s; | 1103 return s; |
1099 } | 1104 } |
1100 | 1105 |
1101 Statement *ForStatement::semantic(Scope *sc) | 1106 Statement *ForStatement::semantic(Scope *sc) |
1102 { | 1107 { |
1103 enclosinghandler = sc->tfOfTry; | |
1104 | |
1105 ScopeDsymbol *sym = new ScopeDsymbol(); | 1108 ScopeDsymbol *sym = new ScopeDsymbol(); |
1106 sym->parent = sc->scopesym; | 1109 sym->parent = sc->scopesym; |
1107 sc = sc->push(sym); | 1110 sc = sc->push(sym); |
1108 if (init) | 1111 if (init) |
1109 init = init->semantic(sc); | 1112 init = init->semantic(sc); |
1120 increment = resolveProperties(sc, increment); | 1123 increment = resolveProperties(sc, increment); |
1121 } | 1124 } |
1122 | 1125 |
1123 sc->sbreak = this; | 1126 sc->sbreak = this; |
1124 sc->scontinue = this; | 1127 sc->scontinue = this; |
1125 body = body->semantic(sc); | 1128 if (body) |
1129 body = body->semantic(sc); | |
1126 sc->noctor--; | 1130 sc->noctor--; |
1127 | 1131 |
1128 sc->pop(); | 1132 sc->pop(); |
1129 return this; | 1133 return this; |
1130 } | 1134 } |
1169 } | 1173 } |
1170 else | 1174 else |
1171 result &= ~BEfallthru; // the body must do the exiting | 1175 result &= ~BEfallthru; // the body must do the exiting |
1172 if (body) | 1176 if (body) |
1173 { int r = body->blockExit(); | 1177 { int r = body->blockExit(); |
1174 if (r & BEbreak) | 1178 if (r & (BEbreak | BEgoto)) |
1175 result |= BEfallthru; | 1179 result |= BEfallthru; |
1176 result |= r & ~(BEbreak | BEcontinue); | 1180 result |= r & ~(BEfallthru | BEbreak | BEcontinue); |
1177 } | 1181 } |
1178 if (increment && increment->canThrow()) | 1182 if (increment && increment->canThrow()) |
1179 result |= BEthrow; | 1183 result |= BEthrow; |
1180 return result; | 1184 return result; |
1181 } | 1185 } |
1182 | 1186 |
1183 int ForStatement::fallOffEnd() | |
1184 { | |
1185 if (body) | |
1186 body->fallOffEnd(); | |
1187 return TRUE; | |
1188 } | |
1189 | 1187 |
1190 int ForStatement::comeFrom() | 1188 int ForStatement::comeFrom() |
1191 { | 1189 { |
1192 //printf("ForStatement::comeFrom()\n"); | 1190 //printf("ForStatement::comeFrom()\n"); |
1193 if (body) | 1191 if (body) |
1202 { | 1200 { |
1203 buf->writestring("for ("); | 1201 buf->writestring("for ("); |
1204 if (init) | 1202 if (init) |
1205 { | 1203 { |
1206 hgs->FLinit.init++; | 1204 hgs->FLinit.init++; |
1207 hgs->FLinit.decl = 0; | |
1208 init->toCBuffer(buf, hgs); | 1205 init->toCBuffer(buf, hgs); |
1209 if (hgs->FLinit.decl > 0) | |
1210 buf->writebyte(';'); | |
1211 hgs->FLinit.decl = 0; | |
1212 hgs->FLinit.init--; | 1206 hgs->FLinit.init--; |
1213 } | 1207 } |
1214 else | 1208 else |
1215 buf->writebyte(';'); | 1209 buf->writebyte(';'); |
1216 if (condition) | 1210 if (condition) |
1239 { | 1233 { |
1240 this->op = op; | 1234 this->op = op; |
1241 this->arguments = arguments; | 1235 this->arguments = arguments; |
1242 this->aggr = aggr; | 1236 this->aggr = aggr; |
1243 this->body = body; | 1237 this->body = body; |
1244 this->enclosinghandler = NULL; | |
1245 | 1238 |
1246 this->key = NULL; | 1239 this->key = NULL; |
1247 this->value = NULL; | 1240 this->value = NULL; |
1248 | 1241 |
1249 this->func = NULL; | 1242 this->func = NULL; |
1267 TypeAArray *taa = NULL; | 1260 TypeAArray *taa = NULL; |
1268 | 1261 |
1269 Type *tn = NULL; | 1262 Type *tn = NULL; |
1270 Type *tnv = NULL; | 1263 Type *tnv = NULL; |
1271 | 1264 |
1272 enclosinghandler = sc->tfOfTry; | |
1273 | |
1274 func = sc->func; | 1265 func = sc->func; |
1275 if (func->fes) | 1266 if (func->fes) |
1276 func = func->fes->func; | 1267 func = func->fes->func; |
1277 | 1268 |
1278 aggr = aggr->semantic(sc); | 1269 aggr = aggr->semantic(sc); |
1282 { | 1273 { |
1283 error("invalid foreach aggregate %s", aggr->toChars()); | 1274 error("invalid foreach aggregate %s", aggr->toChars()); |
1284 return this; | 1275 return this; |
1285 } | 1276 } |
1286 | 1277 |
1287 inferApplyArgTypes(op, arguments, aggr); | 1278 inferApplyArgTypes(op, arguments, aggr, sc->module); |
1288 | 1279 |
1289 /* Check for inference errors | 1280 /* Check for inference errors |
1290 */ | 1281 */ |
1291 if (dim != arguments->dim) | 1282 if (dim != arguments->dim) |
1292 { | 1283 { |
1334 if (dim == 2) | 1325 if (dim == 2) |
1335 { // Declare key | 1326 { // Declare key |
1336 if (arg->storageClass & (STCout | STCref | STClazy)) | 1327 if (arg->storageClass & (STCout | STCref | STClazy)) |
1337 error("no storage class for key %s", arg->ident->toChars()); | 1328 error("no storage class for key %s", arg->ident->toChars()); |
1338 TY keyty = arg->type->ty; | 1329 TY keyty = arg->type->ty; |
1339 if (global.params.is64bit) | 1330 if (keyty != Tint32 && keyty != Tuns32) |
1340 { | 1331 { |
1341 if (keyty != Tint32 && keyty != Tuns32 && keyty != Tint64 && keyty != Tuns64) | 1332 if (global.params.is64bit) |
1342 { | 1333 { |
1343 error("foreach: key type must be int, uint, long or ulong, not %s", key->type->toChars()); | 1334 if (keyty != Tint64 && keyty != Tuns64) |
1344 } | 1335 error("foreach: key type must be int or uint, long or ulong, not %s", arg->type->toChars()); |
1345 } | 1336 } |
1346 else if (keyty != Tint32 && keyty != Tuns32) | 1337 else |
1347 { | 1338 error("foreach: key type must be int or uint, not %s", arg->type->toChars()); |
1348 error("foreach: key type must be int or uint, not %s", key->type->toChars()); | 1339 } |
1349 } | |
1350 Initializer *ie = new ExpInitializer(0, new IntegerExp(k)); | 1340 Initializer *ie = new ExpInitializer(0, new IntegerExp(k)); |
1351 VarDeclaration *var = new VarDeclaration(loc, arg->type, arg->ident, ie); | 1341 VarDeclaration *var = new VarDeclaration(loc, arg->type, arg->ident, ie); |
1352 var->storage_class |= STCmanifest; | 1342 var->storage_class |= STCmanifest; |
1353 DeclarationExp *de = new DeclarationExp(loc, var); | 1343 DeclarationExp *de = new DeclarationExp(loc, var); |
1354 st->push(new ExpStatement(loc, de)); | 1344 st->push(new ExpStatement(loc, de)); |
1441 Argument *arg = (Argument *)arguments->data[i]; | 1431 Argument *arg = (Argument *)arguments->data[i]; |
1442 VarDeclaration *var; | 1432 VarDeclaration *var; |
1443 | 1433 |
1444 var = new VarDeclaration(loc, arg->type, arg->ident, NULL); | 1434 var = new VarDeclaration(loc, arg->type, arg->ident, NULL); |
1445 var->storage_class |= STCforeach; | 1435 var->storage_class |= STCforeach; |
1446 var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant); | 1436 var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR); |
1447 if (dim == 2 && i == 0) | 1437 if (dim == 2 && i == 0) |
1448 { key = var; | 1438 { key = var; |
1449 //var->storage_class |= STCfinal; | 1439 //var->storage_class |= STCfinal; |
1450 } | 1440 } |
1451 else | 1441 else |
1479 else | 1469 else |
1480 error("foreach: %s is not an array of %s", | 1470 error("foreach: %s is not an array of %s", |
1481 tab->toChars(), value->type->toChars()); | 1471 tab->toChars(), value->type->toChars()); |
1482 } | 1472 } |
1483 | 1473 |
1484 if (key) | 1474 if (key && key->type->ty != Tint32 && key->type->ty != Tuns32) |
1485 { | 1475 { |
1486 if (global.params.is64bit) | 1476 if (global.params.is64bit) |
1487 { | 1477 { |
1488 if (key->type->ty != Tint32 && key->type->ty != Tuns32 && key->type->ty != Tint64 && key->type->ty != Tuns64) | 1478 if (key->type->ty != Tint64 && key->type->ty != Tuns64) |
1489 { | 1479 error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars()); |
1490 error("foreach: key type must be int, uint, long or ulong, not %s", key->type->toChars()); | 1480 } |
1491 } | 1481 else |
1492 } | 1482 error("foreach: key type must be int or uint, not %s", key->type->toChars()); |
1493 else if (key->type->ty != Tint32 && key->type->ty != Tuns32) | 1483 } |
1494 { | |
1495 error("foreach: key type must be int or uint, not %s", key->type->toChars()); | |
1496 } | |
1497 } | |
1498 | 1484 |
1499 if (key && key->storage_class & (STCout | STCref)) | 1485 if (key && key->storage_class & (STCout | STCref)) |
1500 error("foreach: key cannot be out or ref"); | 1486 error("foreach: key cannot be out or ref"); |
1501 break; | 1487 break; |
1502 | 1488 |
1519 case Tclass: | 1505 case Tclass: |
1520 case Tstruct: | 1506 case Tstruct: |
1521 #if DMDV2 | 1507 #if DMDV2 |
1522 { /* Look for range iteration, i.e. the properties | 1508 { /* Look for range iteration, i.e. the properties |
1523 * .empty, .next, .retreat, .head and .rear | 1509 * .empty, .next, .retreat, .head and .rear |
1524 * foreach (e; range) { ... } | 1510 * foreach (e; aggr) { ... } |
1525 * translates to: | 1511 * translates to: |
1526 * for (auto __r = range; !__r.empty; __r.next) | 1512 * for (auto __r = aggr[]; !__r.empty; __r.next) |
1527 * { auto e = __r.head; | 1513 * { auto e = __r.head; |
1528 * ... | 1514 * ... |
1529 * } | 1515 * } |
1530 */ | 1516 */ |
1531 if (dim != 1) // only one argument allowed with ranges | 1517 if (dim != 1) // only one argument allowed with ranges |
1548 goto Lapply; | 1534 goto Lapply; |
1549 | 1535 |
1550 /* Generate a temporary __r and initialize it with the aggregate. | 1536 /* Generate a temporary __r and initialize it with the aggregate. |
1551 */ | 1537 */ |
1552 Identifier *id = Identifier::generateId("__r"); | 1538 Identifier *id = Identifier::generateId("__r"); |
1553 VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, aggr)); | 1539 aggr = aggr->semantic(sc); |
1554 r->semantic(sc); | 1540 Expression *rinit = new SliceExp(loc, aggr, NULL, NULL); |
1541 rinit = rinit->trySemantic(sc); | |
1542 if (!rinit) // if application of [] failed | |
1543 rinit = aggr; | |
1544 VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, rinit)); | |
1545 // r->semantic(sc); | |
1546 //printf("r: %s, init: %s\n", r->toChars(), r->init->toChars()); | |
1555 Statement *init = new DeclarationStatement(loc, r); | 1547 Statement *init = new DeclarationStatement(loc, r); |
1548 //printf("init: %s\n", init->toChars()); | |
1556 | 1549 |
1557 // !__r.empty | 1550 // !__r.empty |
1558 Expression *e = new VarExp(loc, r); | 1551 Expression *e = new VarExp(loc, r); |
1559 e = new DotIdExp(loc, e, Id::Fempty); | 1552 e = new DotIdExp(loc, e, Id::Fempty); |
1560 Expression *condition = new NotExp(loc, e); | 1553 Expression *condition = new NotExp(loc, e); |
1566 /* Declaration statement for e: | 1559 /* Declaration statement for e: |
1567 * auto e = __r.idhead; | 1560 * auto e = __r.idhead; |
1568 */ | 1561 */ |
1569 e = new VarExp(loc, r); | 1562 e = new VarExp(loc, r); |
1570 Expression *einit = new DotIdExp(loc, e, idhead); | 1563 Expression *einit = new DotIdExp(loc, e, idhead); |
1571 einit = einit->semantic(sc); | 1564 // einit = einit->semantic(sc); |
1572 Argument *arg = (Argument *)arguments->data[0]; | 1565 Argument *arg = (Argument *)arguments->data[0]; |
1573 VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit)); | 1566 VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit)); |
1574 ve->storage_class |= STCforeach; | 1567 ve->storage_class |= STCforeach; |
1575 ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant); | 1568 ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR); |
1576 | 1569 |
1577 DeclarationExp *de = new DeclarationExp(loc, ve); | 1570 DeclarationExp *de = new DeclarationExp(loc, ve); |
1578 | 1571 |
1579 Statement *body = new CompoundStatement(loc, | 1572 Statement *body = new CompoundStatement(loc, |
1580 new DeclarationStatement(loc, de), this->body); | 1573 new DeclarationStatement(loc, de), this->body); |
1581 | 1574 |
1582 s = new ForStatement(loc, init, condition, increment, body); | 1575 s = new ForStatement(loc, init, condition, increment, body); |
1576 #if 0 | |
1577 printf("init: %s\n", init->toChars()); | |
1578 printf("condition: %s\n", condition->toChars()); | |
1579 printf("increment: %s\n", increment->toChars()); | |
1580 printf("body: %s\n", body->toChars()); | |
1581 #endif | |
1583 s = s->semantic(sc); | 1582 s = s->semantic(sc); |
1584 break; | 1583 break; |
1585 } | 1584 } |
1586 #endif | 1585 #endif |
1587 case Tdelegate: | 1586 case Tdelegate: |
1599 TypeDelegate* dgty; | 1598 TypeDelegate* dgty; |
1600 TypeDelegate* dgty2; | 1599 TypeDelegate* dgty2; |
1601 TypeDelegate* fldeTy; | 1600 TypeDelegate* fldeTy; |
1602 | 1601 |
1603 if (!checkForArgTypes()) | 1602 if (!checkForArgTypes()) |
1603 { body = body->semantic(sc); | |
1604 return this; | 1604 return this; |
1605 } | |
1605 | 1606 |
1606 tret = func->type->nextOf(); | 1607 tret = func->type->nextOf(); |
1607 | 1608 |
1608 // Need a variable to hold value from any return statements in body. | 1609 // Need a variable to hold value from any return statements in body. |
1609 if (!sc->func->vresult && tret && tret != Type::tvoid) | 1610 if (!sc->func->vresult && tret && tret != Type::tvoid) |
1727 { | 1728 { |
1728 flde = new CastExp(loc, flde, flde->type); | 1729 flde = new CastExp(loc, flde, flde->type); |
1729 flde->type = fldeTy; | 1730 flde->type = fldeTy; |
1730 } | 1731 } |
1731 exps->push(flde); | 1732 exps->push(flde); |
1732 | |
1733 e = new CallExp(loc, ec, exps); | 1733 e = new CallExp(loc, ec, exps); |
1734 e->type = Type::tindex; // don't run semantic() on e | 1734 e->type = Type::tindex; // don't run semantic() on e |
1735 } | 1735 } |
1736 else if (tab->ty == Tarray || tab->ty == Tsarray) | 1736 else if (tab->ty == Tarray || tab->ty == Tsarray) |
1737 { | 1737 { |
1759 case Twchar: flag += 1; break; | 1759 case Twchar: flag += 1; break; |
1760 case Tdchar: flag += 2; break; | 1760 case Tdchar: flag += 2; break; |
1761 default: assert(0); | 1761 default: assert(0); |
1762 } | 1762 } |
1763 const char *r = (op == TOKforeach_reverse) ? "R" : ""; | 1763 const char *r = (op == TOKforeach_reverse) ? "R" : ""; |
1764 int j = sprintf(fdname, "_aApply%s%.*s%d", r, 2, fntab[flag], dim); | 1764 #ifdef __MINGW32__ |
1765 int j = sprintf(fdname, "_aApply%s%.*s%lu", r, 2, fntab[flag], dim); | |
1766 #else | |
1767 int j = sprintf(fdname, "_aApply%s%.*s%zu", r, 2, fntab[flag], dim); | |
1768 #endif | |
1765 assert(j < sizeof(fdname)); | 1769 assert(j < sizeof(fdname)); |
1766 //LDC: Build arguments. | 1770 //LDC: Build arguments. |
1767 Arguments* args = new Arguments; | 1771 Arguments* args = new Arguments; |
1768 args->push(new Argument(STCin, tn->arrayOf(), NULL, NULL)); | 1772 args->push(new Argument(STCin, tn->arrayOf(), NULL, NULL)); |
1769 if (dim == 2) { | 1773 if (dim == 2) { |
1792 { | 1796 { |
1793 flde = new CastExp(loc, flde, flde->type); | 1797 flde = new CastExp(loc, flde, flde->type); |
1794 flde->type = dgty; | 1798 flde->type = dgty; |
1795 } | 1799 } |
1796 exps->push(flde); | 1800 exps->push(flde); |
1797 | |
1798 e = new CallExp(loc, ec, exps); | 1801 e = new CallExp(loc, ec, exps); |
1799 e->type = Type::tindex; // don't run semantic() on e | 1802 e->type = Type::tindex; // don't run semantic() on e |
1800 } | 1803 } |
1801 else if (tab->ty == Tdelegate) | 1804 else if (tab->ty == Tdelegate) |
1802 { | 1805 { |
1873 break; | 1876 break; |
1874 } | 1877 } |
1875 | 1878 |
1876 default: | 1879 default: |
1877 error("foreach: %s is not an aggregate type", aggr->type->toChars()); | 1880 error("foreach: %s is not an aggregate type", aggr->type->toChars()); |
1881 s = NULL; // error recovery | |
1878 break; | 1882 break; |
1879 } | 1883 } |
1880 sc->noctor--; | 1884 sc->noctor--; |
1881 sc->pop(); | 1885 sc->pop(); |
1882 return s; | 1886 return s; |
1883 } | 1887 } |
1884 | 1888 |
1885 bool ForeachStatement::checkForArgTypes() | 1889 bool ForeachStatement::checkForArgTypes() |
1886 { | 1890 { bool result = TRUE; |
1891 | |
1887 for (size_t i = 0; i < arguments->dim; i++) | 1892 for (size_t i = 0; i < arguments->dim; i++) |
1888 { Argument *arg = (Argument *)arguments->data[i]; | 1893 { Argument *arg = (Argument *)arguments->data[i]; |
1889 if (!arg->type) | 1894 if (!arg->type) |
1890 { | 1895 { |
1891 error("cannot infer type for %s", arg->ident->toChars()); | 1896 error("cannot infer type for %s", arg->ident->toChars()); |
1892 return FALSE; | 1897 arg->type = Type::terror; |
1893 } | 1898 result = FALSE; |
1894 } | 1899 } |
1895 return TRUE; | 1900 } |
1901 return result; | |
1896 } | 1902 } |
1897 | 1903 |
1898 int ForeachStatement::hasBreak() | 1904 int ForeachStatement::hasBreak() |
1899 { | 1905 { |
1900 return TRUE; | 1906 return TRUE; |
1921 result |= body->blockExit() & ~(BEbreak | BEcontinue); | 1927 result |= body->blockExit() & ~(BEbreak | BEcontinue); |
1922 } | 1928 } |
1923 return result; | 1929 return result; |
1924 } | 1930 } |
1925 | 1931 |
1926 int ForeachStatement::fallOffEnd() | |
1927 { | |
1928 if (body) | |
1929 body->fallOffEnd(); | |
1930 return TRUE; | |
1931 } | |
1932 | 1932 |
1933 int ForeachStatement::comeFrom() | 1933 int ForeachStatement::comeFrom() |
1934 { | 1934 { |
1935 if (body) | 1935 if (body) |
1936 return body->comeFrom(); | 1936 return body->comeFrom(); |
1978 this->arg = arg; | 1978 this->arg = arg; |
1979 this->lwr = lwr; | 1979 this->lwr = lwr; |
1980 this->upr = upr; | 1980 this->upr = upr; |
1981 this->body = body; | 1981 this->body = body; |
1982 | 1982 |
1983 this->enclosinghandler = NULL; | |
1984 | |
1985 this->key = NULL; | 1983 this->key = NULL; |
1986 } | 1984 } |
1987 | 1985 |
1988 Statement *ForeachRangeStatement::syntaxCopy() | 1986 Statement *ForeachRangeStatement::syntaxCopy() |
1989 { | 1987 { |
1999 { | 1997 { |
2000 //printf("ForeachRangeStatement::semantic() %p\n", this); | 1998 //printf("ForeachRangeStatement::semantic() %p\n", this); |
2001 ScopeDsymbol *sym; | 1999 ScopeDsymbol *sym; |
2002 Statement *s = this; | 2000 Statement *s = this; |
2003 | 2001 |
2004 enclosinghandler = sc->tfOfTry; | |
2005 | |
2006 lwr = lwr->semantic(sc); | 2002 lwr = lwr->semantic(sc); |
2007 lwr = resolveProperties(sc, lwr); | 2003 lwr = resolveProperties(sc, lwr); |
2008 lwr = lwr->optimize(WANTvalue); | 2004 lwr = lwr->optimize(WANTvalue); |
2009 if (!lwr->type) | 2005 if (!lwr->type) |
2010 { | 2006 { |
2021 return this; | 2017 return this; |
2022 } | 2018 } |
2023 | 2019 |
2024 if (arg->type) | 2020 if (arg->type) |
2025 { | 2021 { |
2022 arg->type = arg->type->semantic(loc, sc); | |
2026 lwr = lwr->implicitCastTo(sc, arg->type); | 2023 lwr = lwr->implicitCastTo(sc, arg->type); |
2027 upr = upr->implicitCastTo(sc, arg->type); | 2024 upr = upr->implicitCastTo(sc, arg->type); |
2028 } | 2025 } |
2029 else | 2026 else |
2030 { | 2027 { |
2089 result |= body->blockExit() & ~(BEbreak | BEcontinue); | 2086 result |= body->blockExit() & ~(BEbreak | BEcontinue); |
2090 } | 2087 } |
2091 return result; | 2088 return result; |
2092 } | 2089 } |
2093 | 2090 |
2094 int ForeachRangeStatement::fallOffEnd() | |
2095 { | |
2096 if (body) | |
2097 body->fallOffEnd(); | |
2098 return TRUE; | |
2099 } | |
2100 | 2091 |
2101 int ForeachRangeStatement::comeFrom() | 2092 int ForeachRangeStatement::comeFrom() |
2102 { | 2093 { |
2103 if (body) | 2094 if (body) |
2104 return body->comeFrom(); | 2095 return body->comeFrom(); |
2195 */ | 2186 */ |
2196 VarExp *v = new VarExp(0, match); | 2187 VarExp *v = new VarExp(0, match); |
2197 condition = new AssignExp(loc, v, condition); | 2188 condition = new AssignExp(loc, v, condition); |
2198 condition = condition->semantic(scd); | 2189 condition = condition->semantic(scd); |
2199 } | 2190 } |
2200 | |
2201 else | 2191 else |
2202 scd = sc->push(); | 2192 scd = sc->push(); |
2203 ifbody = ifbody->semantic(scd); | 2193 ifbody = ifbody->semantic(scd); |
2204 scd->pop(); | 2194 scd->pop(); |
2205 | 2195 |
2249 else | 2239 else |
2250 result |= BEfallthru; | 2240 result |= BEfallthru; |
2251 } | 2241 } |
2252 //printf("IfStatement::blockExit(%p) = x%x\n", this, result); | 2242 //printf("IfStatement::blockExit(%p) = x%x\n", this, result); |
2253 return result; | 2243 return result; |
2254 } | |
2255 | |
2256 int IfStatement::fallOffEnd() | |
2257 { | |
2258 if (!ifbody || ifbody->fallOffEnd() || | |
2259 !elsebody || elsebody->fallOffEnd()) | |
2260 return TRUE; | |
2261 return FALSE; | |
2262 } | 2244 } |
2263 | 2245 |
2264 | 2246 |
2265 void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 2247 void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2266 { | 2248 { |
2412 e = e->semantic(sc); | 2394 e = e->semantic(sc); |
2413 e = e->optimize(WANTvalue | WANTinterpret); | 2395 e = e->optimize(WANTvalue | WANTinterpret); |
2414 if (e->op == TOKstring) | 2396 if (e->op == TOKstring) |
2415 { | 2397 { |
2416 StringExp *se = (StringExp *)e; | 2398 StringExp *se = (StringExp *)e; |
2417 fprintf(stdmsg, "%.*s", (int)se->len, se->string); | 2399 fprintf(stdmsg, "%.*s", (int)se->len, (char*)se->string); |
2418 } | 2400 } |
2419 else | 2401 else |
2420 error("string expected for message, not '%s'", e->toChars()); | 2402 error("string expected for message, not '%s'", e->toChars()); |
2421 } | 2403 } |
2422 fprintf(stdmsg, "\n"); | 2404 fprintf(stdmsg, "\n"); |
2450 mem.free(name); | 2432 mem.free(name); |
2451 } | 2433 } |
2452 } | 2434 } |
2453 #endif | 2435 #endif |
2454 } | 2436 } |
2437 | |
2438 // LDC | |
2439 else if (ident == Id::allow_inline) | |
2440 { | |
2441 sc->func->allowInlining = true; | |
2442 } | |
2443 | |
2455 else if (ident == Id::startaddress) | 2444 else if (ident == Id::startaddress) |
2456 { | 2445 { |
2457 if (!args || args->dim != 1) | 2446 if (!args || args->dim != 1) |
2458 error("function name expected for start address"); | 2447 error("function name expected for start address"); |
2459 else | 2448 else |
2470 body = body->semantic(sc); | 2459 body = body->semantic(sc); |
2471 } | 2460 } |
2472 return this; | 2461 return this; |
2473 } | 2462 } |
2474 } | 2463 } |
2475 | |
2476 // LDC | |
2477 else if (ident == Id::allow_inline) | |
2478 { | |
2479 sc->func->allowInlining = true; | |
2480 } | |
2481 | |
2482 else | 2464 else |
2483 error("unrecognized pragma(%s)", ident->toChars()); | 2465 error("unrecognized pragma(%s)", ident->toChars()); |
2484 | 2466 |
2485 if (body) | 2467 if (body) |
2486 { | 2468 { |
2504 result |= body->blockExit(); | 2486 result |= body->blockExit(); |
2505 #endif | 2487 #endif |
2506 return result; | 2488 return result; |
2507 } | 2489 } |
2508 | 2490 |
2509 int PragmaStatement::fallOffEnd() | |
2510 { | |
2511 if (body) | |
2512 return body->fallOffEnd(); | |
2513 return TRUE; | |
2514 } | |
2515 | 2491 |
2516 void PragmaStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 2492 void PragmaStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2517 { | 2493 { |
2518 buf->writestring("pragma ("); | 2494 buf->writestring("pragma ("); |
2519 buf->writestring(ident->toChars()); | 2495 buf->writestring(ident->toChars()); |
2574 : Statement(loc) | 2550 : Statement(loc) |
2575 { | 2551 { |
2576 condition = c; | 2552 condition = c; |
2577 body = b; | 2553 body = b; |
2578 sdefault = NULL; | 2554 sdefault = NULL; |
2579 tf = NULL; | |
2580 cases = NULL; | 2555 cases = NULL; |
2581 hasNoDefault = 0; | 2556 hasNoDefault = 0; |
2582 hasVars = 0; | 2557 hasVars = 0; |
2583 // LDC | 2558 // LDC |
2584 enclosinghandler = NULL; | 2559 enclosingScopeExit = NULL; |
2585 } | 2560 } |
2586 | 2561 |
2587 Statement *SwitchStatement::syntaxCopy() | 2562 Statement *SwitchStatement::syntaxCopy() |
2588 { | 2563 { |
2589 SwitchStatement *s = new SwitchStatement(loc, | 2564 SwitchStatement *s = new SwitchStatement(loc, |
2592 } | 2567 } |
2593 | 2568 |
2594 Statement *SwitchStatement::semantic(Scope *sc) | 2569 Statement *SwitchStatement::semantic(Scope *sc) |
2595 { | 2570 { |
2596 //printf("SwitchStatement::semantic(%p)\n", this); | 2571 //printf("SwitchStatement::semantic(%p)\n", this); |
2597 tf = sc->tf; | |
2598 assert(!cases); // ensure semantic() is only run once | 2572 assert(!cases); // ensure semantic() is only run once |
2599 | 2573 |
2600 enclosinghandler = sc->tfOfTry; | 2574 // LDC |
2575 enclosingScopeExit = sc->enclosingScopeExit; | |
2601 | 2576 |
2602 condition = condition->semantic(sc); | 2577 condition = condition->semantic(sc); |
2603 condition = resolveProperties(sc, condition); | 2578 condition = resolveProperties(sc, condition); |
2604 if (condition->type->isString()) | 2579 if (condition->type->isString()) |
2605 { | 2580 { |
2658 } | 2633 } |
2659 | 2634 |
2660 if (!sc->sw->sdefault) | 2635 if (!sc->sw->sdefault) |
2661 { hasNoDefault = 1; | 2636 { hasNoDefault = 1; |
2662 | 2637 |
2663 if (global.params.warnings) | 2638 warning("switch statement has no default"); |
2664 { warning("%s: switch statement has no default", loc.toChars()); | |
2665 } | |
2666 | 2639 |
2667 // Generate runtime error if the default is hit | 2640 // Generate runtime error if the default is hit |
2668 Statements *a = new Statements(); | 2641 Statements *a = new Statements(); |
2669 CompoundStatement *cs; | 2642 CompoundStatement *cs; |
2670 Statement *s; | 2643 Statement *s; |
2676 s = new ExpStatement(loc, e); | 2649 s = new ExpStatement(loc, e); |
2677 } | 2650 } |
2678 | 2651 |
2679 a->reserve(4); | 2652 a->reserve(4); |
2680 a->push(body); | 2653 a->push(body); |
2681 a->push(new BreakStatement(loc, NULL)); | 2654 |
2655 // LDC needs semantic to be run on break | |
2656 Statement *breakstmt = new BreakStatement(loc, NULL); | |
2657 breakstmt->semantic(sc); | |
2658 a->push(breakstmt); | |
2659 | |
2682 sc->sw->sdefault = new DefaultStatement(loc, s); | 2660 sc->sw->sdefault = new DefaultStatement(loc, s); |
2683 a->push(sc->sw->sdefault); | 2661 a->push(sc->sw->sdefault); |
2684 cs = new CompoundStatement(loc, a); | 2662 cs = new CompoundStatement(loc, a); |
2685 body = cs; | 2663 body = cs; |
2686 } | 2664 } |
2715 result |= BEfallthru; | 2693 result |= BEfallthru; |
2716 | 2694 |
2717 return result; | 2695 return result; |
2718 } | 2696 } |
2719 | 2697 |
2720 int SwitchStatement::fallOffEnd() | |
2721 { | |
2722 if (body) | |
2723 body->fallOffEnd(); | |
2724 return TRUE; // need to do this better | |
2725 } | |
2726 | 2698 |
2727 void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 2699 void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2728 { | 2700 { |
2729 buf->writestring("switch ("); | 2701 buf->writestring("switch ("); |
2730 condition->toCBuffer(buf, hgs); | 2702 condition->toCBuffer(buf, hgs); |
2755 this->statement = s; | 2727 this->statement = s; |
2756 index = 0; | 2728 index = 0; |
2757 cblock = NULL; | 2729 cblock = NULL; |
2758 bodyBB = NULL; | 2730 bodyBB = NULL; |
2759 llvmIdx = NULL; | 2731 llvmIdx = NULL; |
2732 // LDC | |
2733 enclosingScopeExit = NULL; | |
2760 } | 2734 } |
2761 | 2735 |
2762 Statement *CaseStatement::syntaxCopy() | 2736 Statement *CaseStatement::syntaxCopy() |
2763 { | 2737 { |
2764 CaseStatement *s = new CaseStatement(loc, exp->syntaxCopy(), statement->syntaxCopy()); | 2738 CaseStatement *s = new CaseStatement(loc, exp->syntaxCopy(), statement->syntaxCopy()); |
2770 | 2744 |
2771 //printf("CaseStatement::semantic() %s\n", toChars()); | 2745 //printf("CaseStatement::semantic() %s\n", toChars()); |
2772 exp = exp->semantic(sc); | 2746 exp = exp->semantic(sc); |
2773 if (sw) | 2747 if (sw) |
2774 { | 2748 { |
2749 // LDC | |
2750 enclosingScopeExit = sc->enclosingScopeExit; | |
2751 if (enclosingScopeExit != sw->enclosingScopeExit) | |
2752 { | |
2753 error("case must be inside the same try, synchronized or volatile level as switch"); | |
2754 } | |
2755 | |
2775 exp = exp->implicitCastTo(sc, sw->condition->type); | 2756 exp = exp->implicitCastTo(sc, sw->condition->type); |
2776 exp = exp->optimize(WANTvalue | WANTinterpret); | 2757 exp = exp->optimize(WANTvalue | WANTinterpret); |
2777 | 2758 |
2778 /* This is where variables are allowed as case expressions. | 2759 /* This is where variables are allowed as case expressions. |
2779 */ | 2760 */ |
2819 { | 2800 { |
2820 gcs->cs = this; | 2801 gcs->cs = this; |
2821 sw->gotoCases.remove(i); // remove from array | 2802 sw->gotoCases.remove(i); // remove from array |
2822 } | 2803 } |
2823 } | 2804 } |
2824 | 2805 #if IN_DMD |
2825 if (sc->sw->tf != sc->tf) | 2806 if (sc->sw->tf != sc->tf) |
2826 error("switch and case are in different finally blocks"); | 2807 error("switch and case are in different finally blocks"); |
2808 #endif | |
2827 } | 2809 } |
2828 else | 2810 else |
2829 error("case not in switch statement"); | 2811 error("case not in switch statement"); |
2830 statement = statement->semantic(sc); | 2812 statement = statement->semantic(sc); |
2831 return this; | 2813 return this; |
2847 int CaseStatement::blockExit() | 2829 int CaseStatement::blockExit() |
2848 { | 2830 { |
2849 return statement->blockExit(); | 2831 return statement->blockExit(); |
2850 } | 2832 } |
2851 | 2833 |
2852 int CaseStatement::fallOffEnd() | |
2853 { | |
2854 return statement->fallOffEnd(); | |
2855 } | |
2856 | 2834 |
2857 int CaseStatement::comeFrom() | 2835 int CaseStatement::comeFrom() |
2858 { | 2836 { |
2859 return TRUE; | 2837 return TRUE; |
2860 } | 2838 } |
2876 this->statement = s; | 2854 this->statement = s; |
2877 #if IN_GCC | 2855 #if IN_GCC |
2878 + cblock = NULL; | 2856 + cblock = NULL; |
2879 #endif | 2857 #endif |
2880 bodyBB = NULL; | 2858 bodyBB = NULL; |
2859 // LDC | |
2860 enclosingScopeExit = NULL; | |
2881 } | 2861 } |
2882 | 2862 |
2883 Statement *DefaultStatement::syntaxCopy() | 2863 Statement *DefaultStatement::syntaxCopy() |
2884 { | 2864 { |
2885 DefaultStatement *s = new DefaultStatement(loc, statement->syntaxCopy()); | 2865 DefaultStatement *s = new DefaultStatement(loc, statement->syntaxCopy()); |
2895 { | 2875 { |
2896 error("switch statement already has a default"); | 2876 error("switch statement already has a default"); |
2897 } | 2877 } |
2898 sc->sw->sdefault = this; | 2878 sc->sw->sdefault = this; |
2899 | 2879 |
2900 if (sc->sw->tf != sc->tf) | 2880 // LDC |
2901 error("switch and default are in different finally blocks"); | 2881 enclosingScopeExit = sc->enclosingScopeExit; |
2882 if (enclosingScopeExit != sc->sw->enclosingScopeExit) | |
2883 { | |
2884 error("default must be inside the same try, synchronized or volatile level as switch"); | |
2885 } | |
2902 } | 2886 } |
2903 else | 2887 else |
2904 error("default not in switch statement"); | 2888 error("default not in switch statement"); |
2905 statement = statement->semantic(sc); | 2889 statement = statement->semantic(sc); |
2906 return this; | 2890 return this; |
2914 int DefaultStatement::blockExit() | 2898 int DefaultStatement::blockExit() |
2915 { | 2899 { |
2916 return statement->blockExit(); | 2900 return statement->blockExit(); |
2917 } | 2901 } |
2918 | 2902 |
2919 int DefaultStatement::fallOffEnd() | |
2920 { | |
2921 return statement->fallOffEnd(); | |
2922 } | |
2923 | 2903 |
2924 int DefaultStatement::comeFrom() | 2904 int DefaultStatement::comeFrom() |
2925 { | 2905 { |
2926 return TRUE; | 2906 return TRUE; |
2927 } | 2907 } |
2936 | 2916 |
2937 GotoDefaultStatement::GotoDefaultStatement(Loc loc) | 2917 GotoDefaultStatement::GotoDefaultStatement(Loc loc) |
2938 : Statement(loc) | 2918 : Statement(loc) |
2939 { | 2919 { |
2940 sw = NULL; | 2920 sw = NULL; |
2941 enclosinghandler = NULL; | |
2942 } | 2921 } |
2943 | 2922 |
2944 Statement *GotoDefaultStatement::syntaxCopy() | 2923 Statement *GotoDefaultStatement::syntaxCopy() |
2945 { | 2924 { |
2946 GotoDefaultStatement *s = new GotoDefaultStatement(loc); | 2925 GotoDefaultStatement *s = new GotoDefaultStatement(loc); |
2947 return s; | 2926 return s; |
2948 } | 2927 } |
2949 | 2928 |
2950 Statement *GotoDefaultStatement::semantic(Scope *sc) | 2929 Statement *GotoDefaultStatement::semantic(Scope *sc) |
2951 { | 2930 { |
2952 enclosinghandler = sc->tfOfTry; | |
2953 sw = sc->sw; | 2931 sw = sc->sw; |
2954 if (!sw) | 2932 if (!sw) |
2955 error("goto default not in switch statement"); | 2933 error("goto default not in switch statement"); |
2956 return this; | 2934 return this; |
2957 } | 2935 } |
2959 int GotoDefaultStatement::blockExit() | 2937 int GotoDefaultStatement::blockExit() |
2960 { | 2938 { |
2961 return BEgoto; | 2939 return BEgoto; |
2962 } | 2940 } |
2963 | 2941 |
2964 int GotoDefaultStatement::fallOffEnd() | |
2965 { | |
2966 return FALSE; | |
2967 } | |
2968 | 2942 |
2969 void GotoDefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 2943 void GotoDefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2970 { | 2944 { |
2971 buf->writestring("goto default;\n"); | 2945 buf->writestring("goto default;\n"); |
2972 } | 2946 } |
2976 GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp) | 2950 GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp) |
2977 : Statement(loc) | 2951 : Statement(loc) |
2978 { | 2952 { |
2979 cs = NULL; | 2953 cs = NULL; |
2980 this->exp = exp; | 2954 this->exp = exp; |
2981 enclosinghandler = NULL; | |
2982 sw = NULL; | 2955 sw = NULL; |
2983 } | 2956 } |
2984 | 2957 |
2985 Statement *GotoCaseStatement::syntaxCopy() | 2958 Statement *GotoCaseStatement::syntaxCopy() |
2986 { | 2959 { |
2989 return s; | 2962 return s; |
2990 } | 2963 } |
2991 | 2964 |
2992 Statement *GotoCaseStatement::semantic(Scope *sc) | 2965 Statement *GotoCaseStatement::semantic(Scope *sc) |
2993 { | 2966 { |
2994 enclosinghandler = sc->tfOfTry; | |
2995 if (exp) | 2967 if (exp) |
2996 exp = exp->semantic(sc); | 2968 exp = exp->semantic(sc); |
2997 | 2969 |
2998 if (!sc->sw) | 2970 if (!sc->sw) |
2999 error("goto case not in switch statement"); | 2971 error("goto case not in switch statement"); |
3013 int GotoCaseStatement::blockExit() | 2985 int GotoCaseStatement::blockExit() |
3014 { | 2986 { |
3015 return BEgoto; | 2987 return BEgoto; |
3016 } | 2988 } |
3017 | 2989 |
3018 int GotoCaseStatement::fallOffEnd() | |
3019 { | |
3020 return FALSE; | |
3021 } | |
3022 | 2990 |
3023 void GotoCaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 2991 void GotoCaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3024 { | 2992 { |
3025 buf->writestring("goto case"); | 2993 buf->writestring("goto case"); |
3026 if (exp) | 2994 if (exp) |
3041 int SwitchErrorStatement::blockExit() | 3009 int SwitchErrorStatement::blockExit() |
3042 { | 3010 { |
3043 return BEthrow; | 3011 return BEthrow; |
3044 } | 3012 } |
3045 | 3013 |
3046 int SwitchErrorStatement::fallOffEnd() | |
3047 { | |
3048 return FALSE; | |
3049 } | |
3050 | 3014 |
3051 void SwitchErrorStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 3015 void SwitchErrorStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3052 { | 3016 { |
3053 buf->writestring("SwitchErrorStatement::toCBuffer()"); | 3017 buf->writestring("SwitchErrorStatement::toCBuffer()"); |
3054 buf->writenl(); | 3018 buf->writenl(); |
3058 | 3022 |
3059 ReturnStatement::ReturnStatement(Loc loc, Expression *exp) | 3023 ReturnStatement::ReturnStatement(Loc loc, Expression *exp) |
3060 : Statement(loc) | 3024 : Statement(loc) |
3061 { | 3025 { |
3062 this->exp = exp; | 3026 this->exp = exp; |
3063 this->enclosinghandler = NULL; | |
3064 } | 3027 } |
3065 | 3028 |
3066 Statement *ReturnStatement::syntaxCopy() | 3029 Statement *ReturnStatement::syntaxCopy() |
3067 { | 3030 { |
3068 Expression *e = NULL; | 3031 Expression *e = NULL; |
3073 } | 3036 } |
3074 | 3037 |
3075 Statement *ReturnStatement::semantic(Scope *sc) | 3038 Statement *ReturnStatement::semantic(Scope *sc) |
3076 { | 3039 { |
3077 //printf("ReturnStatement::semantic() %s\n", toChars()); | 3040 //printf("ReturnStatement::semantic() %s\n", toChars()); |
3078 this->enclosinghandler = sc->tfOfTry; | |
3079 | 3041 |
3080 FuncDeclaration *fd = sc->parent->isFuncDeclaration(); | 3042 FuncDeclaration *fd = sc->parent->isFuncDeclaration(); |
3081 Scope *scx = sc; | 3043 Scope *scx = sc; |
3082 int implicit0 = 0; | 3044 int implicit0 = 0; |
3083 | 3045 |
3110 exp = new IntegerExp(0); | 3072 exp = new IntegerExp(0); |
3111 } | 3073 } |
3112 | 3074 |
3113 if (sc->incontract || scx->incontract) | 3075 if (sc->incontract || scx->incontract) |
3114 error("return statements cannot be in contracts"); | 3076 error("return statements cannot be in contracts"); |
3115 if (sc->tf || scx->tf) | 3077 if (sc->enclosingFinally || scx->enclosingFinally) |
3116 error("return statements cannot be in finally, scope(exit) or scope(success) bodies"); | 3078 error("return statements cannot be in finally, scope(exit) or scope(success) bodies"); |
3117 | 3079 |
3118 if (fd->isCtorDeclaration()) | 3080 if (fd->isCtorDeclaration()) |
3119 { | 3081 { |
3120 // Constructors implicitly do: | 3082 // Constructors implicitly do: |
3183 } | 3145 } |
3184 } | 3146 } |
3185 else if (tbret->ty != Tvoid) | 3147 else if (tbret->ty != Tvoid) |
3186 { | 3148 { |
3187 exp = exp->implicitCastTo(sc, tret); | 3149 exp = exp->implicitCastTo(sc, tret); |
3150 exp = exp->optimize(WANTvalue); | |
3188 } | 3151 } |
3189 } | 3152 } |
3190 else if (fd->inferRetType) | 3153 else if (fd->inferRetType) |
3191 { | 3154 { |
3192 if (fd->type->nextOf()) | 3155 if (fd->type->nextOf()) |
3271 | 3234 |
3272 exp = new AssignExp(loc, v, exp); | 3235 exp = new AssignExp(loc, v, exp); |
3273 exp = exp->semantic(sc); | 3236 exp = exp->semantic(sc); |
3274 } | 3237 } |
3275 | 3238 |
3276 if (((TypeFunction *)fd->type)->isref) | 3239 if (((TypeFunction *)fd->type)->isref && !fd->isCtorDeclaration()) |
3277 { // Function returns a reference | 3240 { // Function returns a reference |
3278 if (tbret->isMutable()) | 3241 if (tbret->isMutable()) |
3279 exp = exp->modifiableLvalue(sc, exp); | 3242 exp = exp->modifiableLvalue(sc, exp); |
3280 else | 3243 else |
3281 exp = exp->toLvalue(sc, exp); | 3244 exp = exp->toLvalue(sc, exp); |
3344 if (exp && exp->canThrow()) | 3307 if (exp && exp->canThrow()) |
3345 result |= BEthrow; | 3308 result |= BEthrow; |
3346 return result; | 3309 return result; |
3347 } | 3310 } |
3348 | 3311 |
3349 int ReturnStatement::fallOffEnd() | |
3350 { | |
3351 return FALSE; | |
3352 } | |
3353 | 3312 |
3354 void ReturnStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 3313 void ReturnStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3355 { | 3314 { |
3356 buf->printf("return "); | 3315 buf->printf("return "); |
3357 if (exp) | 3316 if (exp) |
3364 | 3323 |
3365 BreakStatement::BreakStatement(Loc loc, Identifier *ident) | 3324 BreakStatement::BreakStatement(Loc loc, Identifier *ident) |
3366 : Statement(loc) | 3325 : Statement(loc) |
3367 { | 3326 { |
3368 this->ident = ident; | 3327 this->ident = ident; |
3369 this->enclosinghandler = NULL; | |
3370 } | 3328 } |
3371 | 3329 |
3372 Statement *BreakStatement::syntaxCopy() | 3330 Statement *BreakStatement::syntaxCopy() |
3373 { | 3331 { |
3374 BreakStatement *s = new BreakStatement(loc, ident); | 3332 BreakStatement *s = new BreakStatement(loc, ident); |
3376 } | 3334 } |
3377 | 3335 |
3378 Statement *BreakStatement::semantic(Scope *sc) | 3336 Statement *BreakStatement::semantic(Scope *sc) |
3379 { | 3337 { |
3380 //printf("BreakStatement::semantic()\n"); | 3338 //printf("BreakStatement::semantic()\n"); |
3381 enclosinghandler = sc->tfOfTry; | |
3382 // If: | 3339 // If: |
3383 // break Identifier; | 3340 // break Identifier; |
3384 if (ident) | 3341 if (ident) |
3385 { | 3342 { |
3386 Scope *scx; | 3343 Scope *scx; |
3414 { | 3371 { |
3415 Statement *s = ls->statement; | 3372 Statement *s = ls->statement; |
3416 | 3373 |
3417 if (!s->hasBreak()) | 3374 if (!s->hasBreak()) |
3418 error("label '%s' has no break", ident->toChars()); | 3375 error("label '%s' has no break", ident->toChars()); |
3419 if (ls->tf != sc->tf) | 3376 if (ls->enclosingFinally != sc->enclosingFinally) |
3420 error("cannot break out of finally block"); | 3377 error("cannot break out of finally block"); |
3421 | 3378 |
3422 this->target = ls; | 3379 this->target = ls; |
3423 return this; | 3380 return this; |
3424 } | 3381 } |
3443 { | 3400 { |
3444 //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak); | 3401 //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak); |
3445 return ident ? BEgoto : BEbreak; | 3402 return ident ? BEgoto : BEbreak; |
3446 } | 3403 } |
3447 | 3404 |
3448 int BreakStatement::fallOffEnd() | |
3449 { | |
3450 return FALSE; | |
3451 } | |
3452 | 3405 |
3453 void BreakStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 3406 void BreakStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3454 { | 3407 { |
3455 buf->writestring("break"); | 3408 buf->writestring("break"); |
3456 if (ident) | 3409 if (ident) |
3465 | 3418 |
3466 ContinueStatement::ContinueStatement(Loc loc, Identifier *ident) | 3419 ContinueStatement::ContinueStatement(Loc loc, Identifier *ident) |
3467 : Statement(loc) | 3420 : Statement(loc) |
3468 { | 3421 { |
3469 this->ident = ident; | 3422 this->ident = ident; |
3470 this->enclosinghandler = NULL; | |
3471 } | 3423 } |
3472 | 3424 |
3473 Statement *ContinueStatement::syntaxCopy() | 3425 Statement *ContinueStatement::syntaxCopy() |
3474 { | 3426 { |
3475 ContinueStatement *s = new ContinueStatement(loc, ident); | 3427 ContinueStatement *s = new ContinueStatement(loc, ident); |
3476 return s; | 3428 return s; |
3477 } | 3429 } |
3478 | 3430 |
3479 Statement *ContinueStatement::semantic(Scope *sc) | 3431 Statement *ContinueStatement::semantic(Scope *sc) |
3480 { | 3432 { |
3481 enclosinghandler = sc->tfOfTry; | |
3482 //printf("ContinueStatement::semantic() %p\n", this); | 3433 //printf("ContinueStatement::semantic() %p\n", this); |
3483 if (ident) | 3434 if (ident) |
3484 { | 3435 { |
3485 Scope *scx; | 3436 Scope *scx; |
3486 FuncDeclaration *thisfunc = sc->func; | 3437 FuncDeclaration *thisfunc = sc->func; |
3523 { | 3474 { |
3524 Statement *s = ls->statement; | 3475 Statement *s = ls->statement; |
3525 | 3476 |
3526 if (!s->hasContinue()) | 3477 if (!s->hasContinue()) |
3527 error("label '%s' has no continue", ident->toChars()); | 3478 error("label '%s' has no continue", ident->toChars()); |
3528 if (ls->tf != sc->tf) | 3479 if (ls->enclosingFinally != sc->enclosingFinally) |
3529 error("cannot continue out of finally block"); | 3480 error("cannot continue out of finally block"); |
3530 | 3481 |
3531 this->target = ls; | 3482 this->target = ls; |
3532 return this; | 3483 return this; |
3533 } | 3484 } |
3551 int ContinueStatement::blockExit() | 3502 int ContinueStatement::blockExit() |
3552 { | 3503 { |
3553 return ident ? BEgoto : BEcontinue; | 3504 return ident ? BEgoto : BEcontinue; |
3554 } | 3505 } |
3555 | 3506 |
3556 int ContinueStatement::fallOffEnd() | |
3557 { | |
3558 return FALSE; | |
3559 } | |
3560 | 3507 |
3561 void ContinueStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 3508 void ContinueStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3562 { | 3509 { |
3563 buf->writestring("continue"); | 3510 buf->writestring("continue"); |
3564 if (ident) | 3511 if (ident) |
3575 : Statement(loc) | 3522 : Statement(loc) |
3576 { | 3523 { |
3577 this->exp = exp; | 3524 this->exp = exp; |
3578 this->body = body; | 3525 this->body = body; |
3579 this->esync = NULL; | 3526 this->esync = NULL; |
3580 this->enclosinghandler = NULL; | |
3581 // LDC | 3527 // LDC |
3582 this->llsync = NULL; | 3528 this->llsync = NULL; |
3583 } | 3529 } |
3584 | 3530 |
3585 SynchronizedStatement::SynchronizedStatement(Loc loc, elem *esync, Statement *body) | 3531 SynchronizedStatement::SynchronizedStatement(Loc loc, elem *esync, Statement *body) |
3586 : Statement(loc) | 3532 : Statement(loc) |
3587 { | 3533 { |
3588 this->exp = NULL; | 3534 this->exp = NULL; |
3589 this->body = body; | 3535 this->body = body; |
3590 this->esync = esync; | 3536 this->esync = esync; |
3591 this->enclosinghandler = NULL; | |
3592 // LDC | 3537 // LDC |
3593 this->llsync = NULL; | 3538 this->llsync = NULL; |
3594 } | 3539 } |
3595 | 3540 |
3596 Statement *SynchronizedStatement::syntaxCopy() | 3541 Statement *SynchronizedStatement::syntaxCopy() |
3618 exp = exp->semantic(sc); | 3563 exp = exp->semantic(sc); |
3619 } | 3564 } |
3620 } | 3565 } |
3621 if (body) | 3566 if (body) |
3622 { | 3567 { |
3623 enclosinghandler = sc->tfOfTry; | 3568 Statement* oldScopeExit = sc->enclosingScopeExit; |
3624 sc->tfOfTry = new EnclosingSynchro(this); | 3569 sc->enclosingScopeExit = this; |
3625 body = body->semantic(sc); | 3570 body = body->semantic(sc); |
3626 sc->tfOfTry = enclosinghandler; | 3571 sc->enclosingScopeExit = oldScopeExit; |
3627 } | 3572 } |
3628 return this; | 3573 return this; |
3629 } | 3574 } |
3630 | 3575 |
3631 int SynchronizedStatement::hasBreak() | 3576 int SynchronizedStatement::hasBreak() |
3646 int SynchronizedStatement::blockExit() | 3591 int SynchronizedStatement::blockExit() |
3647 { | 3592 { |
3648 return body ? body->blockExit() : BEfallthru; | 3593 return body ? body->blockExit() : BEfallthru; |
3649 } | 3594 } |
3650 | 3595 |
3651 int SynchronizedStatement::fallOffEnd() | |
3652 { | |
3653 return body ? body->fallOffEnd() : TRUE; | |
3654 } | |
3655 | 3596 |
3656 void SynchronizedStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 3597 void SynchronizedStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3657 { | 3598 { |
3658 buf->writestring("synchronized"); | 3599 buf->writestring("synchronized"); |
3659 if (exp) | 3600 if (exp) |
3768 else | 3709 else |
3769 result |= BEfallthru; | 3710 result |= BEfallthru; |
3770 return result; | 3711 return result; |
3771 } | 3712 } |
3772 | 3713 |
3773 int WithStatement::fallOffEnd() | |
3774 { | |
3775 return body ? body->fallOffEnd() : TRUE; | |
3776 } | |
3777 | 3714 |
3778 /******************************** TryCatchStatement ***************************/ | 3715 /******************************** TryCatchStatement ***************************/ |
3779 | 3716 |
3780 TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Array *catches) | 3717 TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Array *catches) |
3781 : Statement(loc) | 3718 : Statement(loc) |
3835 { | 3772 { |
3836 return TRUE; | 3773 return TRUE; |
3837 } | 3774 } |
3838 | 3775 |
3839 int TryCatchStatement::blockExit() | 3776 int TryCatchStatement::blockExit() |
3840 { int result; | 3777 { |
3841 | |
3842 assert(body); | 3778 assert(body); |
3843 result = body->blockExit(); | 3779 int result = body->blockExit(); |
3844 | 3780 |
3781 int catchresult = 0; | |
3845 for (size_t i = 0; i < catches->dim; i++) | 3782 for (size_t i = 0; i < catches->dim; i++) |
3846 { | 3783 { |
3847 Catch *c = (Catch *)catches->data[i]; | 3784 Catch *c = (Catch *)catches->data[i]; |
3848 result |= c->blockExit(); | 3785 catchresult |= c->blockExit(); |
3849 } | 3786 |
3850 return result; | 3787 /* If we're catching Object, then there is no throwing |
3851 } | 3788 */ |
3852 | 3789 Identifier *id = c->type->toBasetype()->isClassHandle()->ident; |
3853 int TryCatchStatement::fallOffEnd() | 3790 if (i == 0 && |
3854 { | 3791 (id == Id::Object || id == Id::Throwable || id == Id::Exception)) |
3855 int result = FALSE; | 3792 { |
3856 | 3793 result &= ~BEthrow; |
3857 if (body) | 3794 } |
3858 result = body->fallOffEnd(); | 3795 } |
3859 for (int i = 0; i < catches->dim; i++) | 3796 return result | catchresult; |
3860 { Catch *c; | 3797 } |
3861 | 3798 |
3862 c = (Catch *)catches->data[i]; | |
3863 if (c->handler) | |
3864 result |= c->handler->fallOffEnd(); | |
3865 } | |
3866 return result; | |
3867 } | |
3868 | 3799 |
3869 void TryCatchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 3800 void TryCatchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3870 { | 3801 { |
3871 buf->writestring("try"); | 3802 buf->writestring("try"); |
3872 buf->writenl(); | 3803 buf->writenl(); |
3904 { ScopeDsymbol *sym; | 3835 { ScopeDsymbol *sym; |
3905 | 3836 |
3906 //printf("Catch::semantic(%s)\n", ident->toChars()); | 3837 //printf("Catch::semantic(%s)\n", ident->toChars()); |
3907 | 3838 |
3908 #ifndef IN_GCC | 3839 #ifndef IN_GCC |
3909 if (sc->tf) | 3840 if (sc->enclosingFinally) |
3910 { | 3841 { |
3911 /* This is because the _d_local_unwind() gets the stack munged | 3842 /* This is because the _d_local_unwind() gets the stack munged |
3912 * up on this. The workaround is to place any try-catches into | 3843 * up on this. The workaround is to place any try-catches into |
3913 * a separate function, and call that. | 3844 * a separate function, and call that. |
3914 * To fix, have the compiler automatically convert the finally | 3845 * To fix, have the compiler automatically convert the finally |
3965 TryFinallyStatement::TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody) | 3896 TryFinallyStatement::TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody) |
3966 : Statement(loc) | 3897 : Statement(loc) |
3967 { | 3898 { |
3968 this->body = body; | 3899 this->body = body; |
3969 this->finalbody = finalbody; | 3900 this->finalbody = finalbody; |
3970 this->enclosinghandler = NULL; | |
3971 } | 3901 } |
3972 | 3902 |
3973 Statement *TryFinallyStatement::syntaxCopy() | 3903 Statement *TryFinallyStatement::syntaxCopy() |
3974 { | 3904 { |
3975 TryFinallyStatement *s = new TryFinallyStatement(loc, | 3905 TryFinallyStatement *s = new TryFinallyStatement(loc, |
3979 | 3909 |
3980 Statement *TryFinallyStatement::semantic(Scope *sc) | 3910 Statement *TryFinallyStatement::semantic(Scope *sc) |
3981 { | 3911 { |
3982 //printf("TryFinallyStatement::semantic()\n"); | 3912 //printf("TryFinallyStatement::semantic()\n"); |
3983 | 3913 |
3984 enclosinghandler = sc->tfOfTry; | 3914 Statement* oldScopeExit = sc->enclosingScopeExit; |
3985 sc->tfOfTry = new EnclosingTryFinally(this); | 3915 sc->enclosingScopeExit = this; |
3986 body = body->semantic(sc); | 3916 body = body->semantic(sc); |
3987 sc->tfOfTry = enclosinghandler; | 3917 sc->enclosingScopeExit = oldScopeExit; |
3988 | 3918 |
3989 sc = sc->push(); | 3919 sc = sc->push(); |
3990 sc->tf = this; | 3920 sc->enclosingFinally = this; |
3991 sc->sbreak = NULL; | 3921 sc->sbreak = NULL; |
3992 sc->scontinue = NULL; // no break or continue out of finally block | 3922 sc->scontinue = NULL; // no break or continue out of finally block |
3993 finalbody = finalbody->semantic(sc); | 3923 finalbody = finalbody->semantic(sc); |
3994 sc->pop(); | 3924 sc->pop(); |
3995 if (!body) | 3925 if (!body) |
4028 return TRUE; | 3958 return TRUE; |
4029 } | 3959 } |
4030 | 3960 |
4031 int TryFinallyStatement::blockExit() | 3961 int TryFinallyStatement::blockExit() |
4032 { | 3962 { |
4033 int result = body->blockExit(); | 3963 if (body) |
4034 return result; | 3964 return body->blockExit(); |
4035 } | 3965 return BEfallthru; |
4036 | 3966 } |
4037 int TryFinallyStatement::fallOffEnd() | 3967 |
4038 { int result; | |
4039 | |
4040 result = body->fallOffEnd(); | |
4041 // if (finalbody) | |
4042 // result = finalbody->fallOffEnd(); | |
4043 return result; | |
4044 } | |
4045 | 3968 |
4046 /****************************** OnScopeStatement ***************************/ | 3969 /****************************** OnScopeStatement ***************************/ |
4047 | 3970 |
4048 OnScopeStatement::OnScopeStatement(Loc loc, TOK tok, Statement *statement) | 3971 OnScopeStatement::OnScopeStatement(Loc loc, TOK tok, Statement *statement) |
4049 : Statement(loc) | 3972 : Statement(loc) |
4161 int ThrowStatement::blockExit() | 4084 int ThrowStatement::blockExit() |
4162 { | 4085 { |
4163 return BEthrow; // obviously | 4086 return BEthrow; // obviously |
4164 } | 4087 } |
4165 | 4088 |
4166 int ThrowStatement::fallOffEnd() | |
4167 { | |
4168 return FALSE; | |
4169 } | |
4170 | 4089 |
4171 void ThrowStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 4090 void ThrowStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
4172 { | 4091 { |
4173 buf->printf("throw "); | 4092 buf->printf("throw "); |
4174 exp->toCBuffer(buf, hgs); | 4093 exp->toCBuffer(buf, hgs); |
4180 | 4099 |
4181 VolatileStatement::VolatileStatement(Loc loc, Statement *statement) | 4100 VolatileStatement::VolatileStatement(Loc loc, Statement *statement) |
4182 : Statement(loc) | 4101 : Statement(loc) |
4183 { | 4102 { |
4184 this->statement = statement; | 4103 this->statement = statement; |
4185 this->enclosinghandler = NULL; | |
4186 } | 4104 } |
4187 | 4105 |
4188 Statement *VolatileStatement::syntaxCopy() | 4106 Statement *VolatileStatement::syntaxCopy() |
4189 { | 4107 { |
4190 VolatileStatement *s = new VolatileStatement(loc, | 4108 VolatileStatement *s = new VolatileStatement(loc, |
4194 | 4112 |
4195 Statement *VolatileStatement::semantic(Scope *sc) | 4113 Statement *VolatileStatement::semantic(Scope *sc) |
4196 { | 4114 { |
4197 if (statement) | 4115 if (statement) |
4198 { | 4116 { |
4199 enclosinghandler = sc->tfOfTry; | 4117 Statement* oldScopeExit = sc->enclosingScopeExit; |
4200 sc->tfOfTry = new EnclosingVolatile(this); | 4118 sc->enclosingScopeExit = this; |
4201 statement = statement->semantic(sc); | 4119 statement = statement->semantic(sc); |
4202 sc->tfOfTry = enclosinghandler; | 4120 sc->enclosingScopeExit = oldScopeExit; |
4203 } | 4121 } |
4204 return this; | 4122 return this; |
4205 } | 4123 } |
4206 | 4124 |
4207 Statements *VolatileStatement::flatten(Scope *sc) | 4125 Statements *VolatileStatement::flatten(Scope *sc) |
4224 int VolatileStatement::blockExit() | 4142 int VolatileStatement::blockExit() |
4225 { | 4143 { |
4226 return statement ? statement->blockExit() : BEfallthru; | 4144 return statement ? statement->blockExit() : BEfallthru; |
4227 } | 4145 } |
4228 | 4146 |
4229 int VolatileStatement::fallOffEnd() | |
4230 { | |
4231 return statement ? statement->fallOffEnd() : TRUE; | |
4232 } | |
4233 | 4147 |
4234 void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 4148 void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
4235 { | 4149 { |
4236 buf->writestring("volatile"); | 4150 buf->writestring("volatile"); |
4237 if (statement) | 4151 if (statement) |
4249 GotoStatement::GotoStatement(Loc loc, Identifier *ident) | 4163 GotoStatement::GotoStatement(Loc loc, Identifier *ident) |
4250 : Statement(loc) | 4164 : Statement(loc) |
4251 { | 4165 { |
4252 this->ident = ident; | 4166 this->ident = ident; |
4253 this->label = NULL; | 4167 this->label = NULL; |
4254 this->tf = NULL; | 4168 this->enclosingFinally = NULL; |
4255 this->enclosinghandler = NULL; | 4169 this->enclosingScopeExit = NULL; |
4256 } | 4170 } |
4257 | 4171 |
4258 Statement *GotoStatement::syntaxCopy() | 4172 Statement *GotoStatement::syntaxCopy() |
4259 { | 4173 { |
4260 GotoStatement *s = new GotoStatement(loc, ident); | 4174 GotoStatement *s = new GotoStatement(loc, ident); |
4263 | 4177 |
4264 Statement *GotoStatement::semantic(Scope *sc) | 4178 Statement *GotoStatement::semantic(Scope *sc) |
4265 { FuncDeclaration *fd = sc->parent->isFuncDeclaration(); | 4179 { FuncDeclaration *fd = sc->parent->isFuncDeclaration(); |
4266 | 4180 |
4267 //printf("GotoStatement::semantic()\n"); | 4181 //printf("GotoStatement::semantic()\n"); |
4268 tf = sc->tf; | 4182 enclosingFinally = sc->enclosingFinally; |
4269 enclosinghandler = sc->tfOfTry; | 4183 enclosingScopeExit = sc->enclosingScopeExit; |
4184 | |
4270 label = fd->searchLabel(ident); | 4185 label = fd->searchLabel(ident); |
4271 if (!label->statement && sc->fes) | 4186 if (!label->statement && sc->fes) |
4272 { | 4187 { |
4273 /* Either the goto label is forward referenced or it | 4188 /* Either the goto label is forward referenced or it |
4274 * is in the function that the enclosing foreach is in. | 4189 * is in the function that the enclosing foreach is in. |
4282 a->push(this); | 4197 a->push(this); |
4283 s = new CompoundStatement(loc, a); | 4198 s = new CompoundStatement(loc, a); |
4284 sc->fes->gotos.push(s); // 'look at this later' list | 4199 sc->fes->gotos.push(s); // 'look at this later' list |
4285 return s; | 4200 return s; |
4286 } | 4201 } |
4287 if (label->statement && label->statement->tf != sc->tf) | 4202 if (label->statement && label->statement->enclosingFinally != sc->enclosingFinally) |
4288 error("cannot goto in or out of finally block"); | 4203 error("cannot goto in or out of finally block"); |
4289 return this; | 4204 return this; |
4290 } | 4205 } |
4291 | 4206 |
4292 int GotoStatement::blockExit() | 4207 int GotoStatement::blockExit() |
4293 { | 4208 { |
4294 //printf("GotoStatement::blockExit(%p)\n", this); | 4209 //printf("GotoStatement::blockExit(%p)\n", this); |
4295 return BEgoto; | 4210 return BEgoto; |
4296 } | 4211 } |
4297 | 4212 |
4298 int GotoStatement::fallOffEnd() | |
4299 { | |
4300 return FALSE; | |
4301 } | |
4302 | 4213 |
4303 void GotoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 4214 void GotoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
4304 { | 4215 { |
4305 buf->writestring("goto "); | 4216 buf->writestring("goto "); |
4306 buf->writestring(ident->toChars()); | 4217 buf->writestring(ident->toChars()); |
4313 LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement) | 4224 LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement) |
4314 : Statement(loc) | 4225 : Statement(loc) |
4315 { | 4226 { |
4316 this->ident = ident; | 4227 this->ident = ident; |
4317 this->statement = statement; | 4228 this->statement = statement; |
4318 this->tf = NULL; | 4229 this->enclosingFinally = NULL; |
4319 this->enclosinghandler = NULL; | 4230 this->enclosingScopeExit = NULL; |
4320 this->lblock = NULL; | 4231 this->lblock = NULL; |
4321 this->isReturnLabel = 0; | 4232 this->isReturnLabel = 0; |
4322 this->asmLabel = false; | 4233 this->asmLabel = false; |
4323 } | 4234 } |
4324 | 4235 |
4336 ls = fd->searchLabel(ident); | 4247 ls = fd->searchLabel(ident); |
4337 if (ls->statement) | 4248 if (ls->statement) |
4338 error("Label '%s' already defined", ls->toChars()); | 4249 error("Label '%s' already defined", ls->toChars()); |
4339 else | 4250 else |
4340 ls->statement = this; | 4251 ls->statement = this; |
4341 tf = sc->tf; | 4252 |
4342 enclosinghandler = sc->tfOfTry; | 4253 enclosingFinally = sc->enclosingFinally; |
4254 enclosingScopeExit = sc->enclosingScopeExit; | |
4255 | |
4343 sc = sc->push(); | 4256 sc = sc->push(); |
4344 sc->scopesym = sc->enclosing->scopesym; | 4257 sc->scopesym = sc->enclosing->scopesym; |
4345 sc->callSuper |= CSXlabel; | 4258 sc->callSuper |= CSXlabel; |
4346 sc->slabel = this; | 4259 sc->slabel = this; |
4347 if (statement) | 4260 if (statement) |
4387 { | 4300 { |
4388 //printf("LabelStatement::blockExit(%p)\n", this); | 4301 //printf("LabelStatement::blockExit(%p)\n", this); |
4389 return statement ? statement->blockExit() : BEfallthru; | 4302 return statement ? statement->blockExit() : BEfallthru; |
4390 } | 4303 } |
4391 | 4304 |
4392 int LabelStatement::fallOffEnd() | |
4393 { | |
4394 return statement ? statement->fallOffEnd() : TRUE; | |
4395 } | |
4396 | 4305 |
4397 int LabelStatement::comeFrom() | 4306 int LabelStatement::comeFrom() |
4398 { | 4307 { |
4399 //printf("LabelStatement::comeFrom()\n"); | 4308 //printf("LabelStatement::comeFrom()\n"); |
4400 return TRUE; | 4309 return TRUE; |
4414 | 4323 |
4415 LabelDsymbol::LabelDsymbol(Identifier *ident) | 4324 LabelDsymbol::LabelDsymbol(Identifier *ident) |
4416 : Dsymbol(ident) | 4325 : Dsymbol(ident) |
4417 { | 4326 { |
4418 statement = NULL; | 4327 statement = NULL; |
4328 #if IN_GCC | |
4329 asmLabelNum = 0; | |
4330 #endif | |
4419 } | 4331 } |
4420 | 4332 |
4421 LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()? | 4333 LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()? |
4422 { | 4334 { |
4423 return this; | 4335 return this; |
4424 } | 4336 } |
4425 | |
4426 |