Mercurial > projects > ldc
comparison dmd/statement.c @ 336:aaade6ded589 trunk
[svn r357] Merged DMD 1.033
author | lindquist |
---|---|
date | Sat, 12 Jul 2008 19:38:31 +0200 |
parents | d20cf0dec9c1 |
children | a7a26f538d6e |
comparison
equal
deleted
inserted
replaced
335:17b844102023 | 336:aaade6ded589 |
---|---|
1 | 1 |
2 // Compiler implementation of the D programming language | 2 // Compiler implementation of the D programming language |
3 // Copyright (c) 1999-2007 by Digital Mars | 3 // Copyright (c) 1999-2008 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. |
111 int Statement::usesEH() | 111 int Statement::usesEH() |
112 { | 112 { |
113 return FALSE; | 113 return FALSE; |
114 } | 114 } |
115 | 115 |
116 /* Only valid after semantic analysis | |
117 */ | |
118 int Statement::blockExit() | |
119 { | |
120 printf("Statement::blockExit(%p)\n", this); | |
121 printf("%s\n", toChars()); | |
122 assert(0); | |
123 return BEany; | |
124 } | |
125 | |
116 // TRUE if statement may fall off the end without a throw or return | 126 // TRUE if statement may fall off the end without a throw or return |
117 | 127 |
118 int Statement::fallOffEnd() | 128 int Statement::fallOffEnd() |
119 { | 129 { |
120 return TRUE; | 130 return TRUE; |
195 //exp = exp->optimize(isDeclarationStatement() ? WANTvalue : 0); | 205 //exp = exp->optimize(isDeclarationStatement() ? WANTvalue : 0); |
196 } | 206 } |
197 return this; | 207 return this; |
198 } | 208 } |
199 | 209 |
210 int ExpStatement::blockExit() | |
211 { int result = BEfallthru; | |
212 | |
213 if (exp) | |
214 { | |
215 if (exp->op == TOKhalt) | |
216 return BEhalt; | |
217 if (exp->op == TOKassert) | |
218 { AssertExp *a = (AssertExp *)exp; | |
219 | |
220 if (a->e1->isBool(FALSE)) // if it's an assert(0) | |
221 return BEhalt; | |
222 } | |
223 if (exp->canThrow()) | |
224 result |= BEthrow; | |
225 } | |
226 return result; | |
227 } | |
228 | |
200 int ExpStatement::fallOffEnd() | 229 int ExpStatement::fallOffEnd() |
201 { | 230 { |
202 if (exp) | 231 if (exp) |
203 { | 232 { |
204 if (exp->op == TOKassert) | 233 if (exp->op == TOKassert) |
235 buf->writestring(");"); | 264 buf->writestring(");"); |
236 if (!hgs->FLinit.init) | 265 if (!hgs->FLinit.init) |
237 buf->writenl(); | 266 buf->writenl(); |
238 } | 267 } |
239 | 268 |
240 Statement *CompileStatement::semantic(Scope *sc) | 269 Statements *CompileStatement::flatten(Scope *sc) |
241 { | 270 { |
242 //printf("CompileStatement::semantic() %s\n", exp->toChars()); | 271 //printf("CompileStatement::flatten() %s\n", exp->toChars()); |
243 exp = exp->semantic(sc); | 272 exp = exp->semantic(sc); |
244 exp = resolveProperties(sc, exp); | 273 exp = resolveProperties(sc, exp); |
245 exp = exp->optimize(WANTvalue | WANTinterpret); | 274 exp = exp->optimize(WANTvalue | WANTinterpret); |
246 if (exp->op != TOKstring) | 275 if (exp->op != TOKstring) |
247 { error("argument to mixin must be a string, not (%s)", exp->toChars()); | 276 { error("argument to mixin must be a string, not (%s)", exp->toChars()); |
248 return this; | 277 return NULL; |
249 } | 278 } |
250 StringExp *se = (StringExp *)exp; | 279 StringExp *se = (StringExp *)exp; |
251 se = se->toUTF8(sc); | 280 se = se->toUTF8(sc); |
252 Parser p(sc->module, (unsigned char *)se->string, se->len, 0); | 281 Parser p(sc->module, (unsigned char *)se->string, se->len, 0); |
253 p.loc = loc; | 282 p.loc = loc; |
254 p.nextToken(); | 283 p.nextToken(); |
255 | 284 |
256 Statements *statements = new Statements(); | 285 Statements *a = new Statements(); |
257 while (p.token.value != TOKeof) | 286 while (p.token.value != TOKeof) |
258 { | 287 { |
259 Statement *s = p.parseStatement(PSsemi | PScurlyscope); | 288 Statement *s = p.parseStatement(PSsemi | PScurlyscope); |
260 statements->push(s); | 289 a->push(s); |
261 } | 290 } |
262 | 291 return a; |
263 Statement *s = new CompoundStatement(loc, statements); | 292 } |
293 | |
294 Statement *CompileStatement::semantic(Scope *sc) | |
295 { | |
296 //printf("CompileStatement::semantic() %s\n", exp->toChars()); | |
297 Statements *a = flatten(sc); | |
298 if (!a) | |
299 return NULL; | |
300 Statement *s = new CompoundStatement(loc, a); | |
264 return s->semantic(sc); | 301 return s->semantic(sc); |
265 } | 302 } |
266 | 303 |
267 | 304 |
268 /******************************** DeclarationStatement ***************************/ | 305 /******************************** DeclarationStatement ***************************/ |
466 } | 503 } |
467 } | 504 } |
468 i++; | 505 i++; |
469 } | 506 } |
470 if (statements->dim == 1 && !isAsmBlockStatement()) | 507 if (statements->dim == 1 && !isAsmBlockStatement()) |
471 return s; | 508 { |
509 return (Statement *)statements->data[0]; | |
510 } | |
472 return this; | 511 return this; |
473 } | 512 } |
474 | 513 |
475 Statements *CompoundStatement::flatten(Scope *sc) | 514 Statements *CompoundStatement::flatten(Scope *sc) |
476 { | 515 { |
477 return statements; | 516 return statements; |
478 } | 517 } |
479 | 518 |
480 ReturnStatement *CompoundStatement::isReturnStatement() | 519 ReturnStatement *CompoundStatement::isReturnStatement() |
481 { int i; | 520 { |
482 ReturnStatement *rs = NULL; | 521 ReturnStatement *rs = NULL; |
483 | 522 |
484 for (i = 0; i < statements->dim; i++) | 523 for (int i = 0; i < statements->dim; i++) |
485 { Statement *s; | 524 { Statement *s = (Statement *) statements->data[i]; |
486 | |
487 s = (Statement *) statements->data[i]; | |
488 if (s) | 525 if (s) |
489 { | 526 { |
490 rs = s->isReturnStatement(); | 527 rs = s->isReturnStatement(); |
491 if (rs) | 528 if (rs) |
492 break; | 529 break; |
494 } | 531 } |
495 return rs; | 532 return rs; |
496 } | 533 } |
497 | 534 |
498 void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 535 void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
499 { int i; | 536 { |
500 | 537 for (int i = 0; i < statements->dim; i++) |
501 for (i = 0; i < statements->dim; i++) | 538 { Statement *s = (Statement *) statements->data[i]; |
502 { Statement *s; | |
503 | |
504 s = (Statement *) statements->data[i]; | |
505 if (s) | 539 if (s) |
506 s->toCBuffer(buf, hgs); | 540 s->toCBuffer(buf, hgs); |
507 } | 541 } |
508 } | 542 } |
509 | 543 |
510 int CompoundStatement::usesEH() | 544 int CompoundStatement::usesEH() |
511 { | 545 { |
512 for (int i = 0; i < statements->dim; i++) | 546 for (int i = 0; i < statements->dim; i++) |
513 { Statement *s; | 547 { Statement *s = (Statement *) statements->data[i]; |
514 | |
515 s = (Statement *) statements->data[i]; | |
516 if (s && s->usesEH()) | 548 if (s && s->usesEH()) |
517 return TRUE; | 549 return TRUE; |
518 } | 550 } |
519 return FALSE; | 551 return FALSE; |
552 } | |
553 | |
554 int CompoundStatement::blockExit() | |
555 { | |
556 //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim); | |
557 int result = BEfallthru; | |
558 for (size_t i = 0; i < statements->dim; i++) | |
559 { Statement *s = (Statement *) statements->data[i]; | |
560 if (s) | |
561 { | |
562 //printf("result = x%x\n", result); | |
563 //printf("%s\n", s->toChars()); | |
564 if (!(result & BEfallthru) && !s->comeFrom()) | |
565 { | |
566 if (global.params.warnings) | |
567 { fprintf(stdmsg, "warning - "); | |
568 s->error("statement is not reachable"); | |
569 } | |
570 } | |
571 | |
572 result &= ~BEfallthru; | |
573 result |= s->blockExit(); | |
574 } | |
575 } | |
576 return result; | |
520 } | 577 } |
521 | 578 |
522 int CompoundStatement::fallOffEnd() | 579 int CompoundStatement::fallOffEnd() |
523 { int falloff = TRUE; | 580 { int falloff = TRUE; |
524 | 581 |
632 } | 689 } |
633 | 690 |
634 int UnrolledLoopStatement::usesEH() | 691 int UnrolledLoopStatement::usesEH() |
635 { | 692 { |
636 for (size_t i = 0; i < statements->dim; i++) | 693 for (size_t i = 0; i < statements->dim; i++) |
637 { Statement *s; | 694 { Statement *s = (Statement *) statements->data[i]; |
638 | |
639 s = (Statement *) statements->data[i]; | |
640 if (s && s->usesEH()) | 695 if (s && s->usesEH()) |
641 return TRUE; | 696 return TRUE; |
642 } | 697 } |
643 return FALSE; | 698 return FALSE; |
699 } | |
700 | |
701 int UnrolledLoopStatement::blockExit() | |
702 { | |
703 int result = BEfallthru; | |
704 for (size_t i = 0; i < statements->dim; i++) | |
705 { Statement *s = (Statement *) statements->data[i]; | |
706 if (s) | |
707 { | |
708 int r = s->blockExit(); | |
709 result |= r & ~(BEbreak | BEcontinue); | |
710 } | |
711 } | |
712 return result; | |
644 } | 713 } |
645 | 714 |
646 int UnrolledLoopStatement::fallOffEnd() | 715 int UnrolledLoopStatement::fallOffEnd() |
647 { | 716 { |
648 //printf("UnrolledLoopStatement::fallOffEnd()\n"); | 717 //printf("UnrolledLoopStatement::fallOffEnd()\n"); |
652 if (s) | 721 if (s) |
653 s->fallOffEnd(); | 722 s->fallOffEnd(); |
654 } | 723 } |
655 return TRUE; | 724 return TRUE; |
656 } | 725 } |
657 | |
658 | 726 |
659 int UnrolledLoopStatement::comeFrom() | 727 int UnrolledLoopStatement::comeFrom() |
660 { int comefrom = FALSE; | 728 { int comefrom = FALSE; |
661 | 729 |
662 //printf("UnrolledLoopStatement::comeFrom()\n"); | 730 //printf("UnrolledLoopStatement::comeFrom()\n"); |
739 } | 807 } |
740 | 808 |
741 int ScopeStatement::usesEH() | 809 int ScopeStatement::usesEH() |
742 { | 810 { |
743 return statement ? statement->usesEH() : FALSE; | 811 return statement ? statement->usesEH() : FALSE; |
812 } | |
813 | |
814 int ScopeStatement::blockExit() | |
815 { | |
816 //printf("ScopeStatement::blockExit(%p)\n", statement); | |
817 return statement ? statement->blockExit() : BEfallthru; | |
744 } | 818 } |
745 | 819 |
746 int ScopeStatement::fallOffEnd() | 820 int ScopeStatement::fallOffEnd() |
747 { | 821 { |
748 return statement ? statement->fallOffEnd() : TRUE; | 822 return statement ? statement->fallOffEnd() : TRUE; |
842 int WhileStatement::usesEH() | 916 int WhileStatement::usesEH() |
843 { | 917 { |
844 return body ? body->usesEH() : 0; | 918 return body ? body->usesEH() : 0; |
845 } | 919 } |
846 | 920 |
921 int WhileStatement::blockExit() | |
922 { | |
923 //printf("WhileStatement::blockExit(%p)\n", this); | |
924 | |
925 int result = BEnone; | |
926 if (condition->canThrow()) | |
927 result |= BEthrow; | |
928 if (condition->isBool(TRUE)) | |
929 { | |
930 if (body) | |
931 { result |= body->blockExit(); | |
932 if (result & BEbreak) | |
933 result |= BEfallthru; | |
934 } | |
935 } | |
936 else if (condition->isBool(FALSE)) | |
937 { | |
938 result |= BEfallthru; | |
939 } | |
940 else | |
941 { | |
942 if (body) | |
943 result |= body->blockExit(); | |
944 result |= BEfallthru; | |
945 } | |
946 result &= ~(BEbreak | BEcontinue); | |
947 return result; | |
948 } | |
949 | |
847 int WhileStatement::fallOffEnd() | 950 int WhileStatement::fallOffEnd() |
848 { | 951 { |
849 if (body) | 952 if (body) |
850 body->fallOffEnd(); | 953 body->fallOffEnd(); |
851 return TRUE; | 954 return TRUE; |
913 } | 1016 } |
914 | 1017 |
915 int DoStatement::usesEH() | 1018 int DoStatement::usesEH() |
916 { | 1019 { |
917 return body ? body->usesEH() : 0; | 1020 return body ? body->usesEH() : 0; |
1021 } | |
1022 | |
1023 int DoStatement::blockExit() | |
1024 { int result; | |
1025 | |
1026 if (body) | |
1027 { result = body->blockExit(); | |
1028 if (result == BEbreak) | |
1029 return BEfallthru; | |
1030 if (result & BEcontinue) | |
1031 result |= BEfallthru; | |
1032 } | |
1033 else | |
1034 result = BEfallthru; | |
1035 if (result & BEfallthru) | |
1036 { if (condition->canThrow()) | |
1037 result |= BEthrow; | |
1038 if (!(result & BEbreak) && condition->isBool(TRUE)) | |
1039 result &= ~BEfallthru; | |
1040 } | |
1041 result &= ~(BEbreak | BEcontinue); | |
1042 return result; | |
918 } | 1043 } |
919 | 1044 |
920 int DoStatement::fallOffEnd() | 1045 int DoStatement::fallOffEnd() |
921 { | 1046 { |
922 if (body) | 1047 if (body) |
1020 } | 1145 } |
1021 | 1146 |
1022 int ForStatement::usesEH() | 1147 int ForStatement::usesEH() |
1023 { | 1148 { |
1024 return (init && init->usesEH()) || body->usesEH(); | 1149 return (init && init->usesEH()) || body->usesEH(); |
1150 } | |
1151 | |
1152 int ForStatement::blockExit() | |
1153 { int result = BEfallthru; | |
1154 | |
1155 if (init) | |
1156 { result = init->blockExit(); | |
1157 if (!(result & BEfallthru)) | |
1158 return result; | |
1159 } | |
1160 if (condition) | |
1161 { if (condition->canThrow()) | |
1162 result |= BEthrow; | |
1163 } | |
1164 else | |
1165 result &= ~BEfallthru; // the body must do the exiting | |
1166 if (body) | |
1167 { int r = body->blockExit(); | |
1168 if (r & BEbreak) | |
1169 result |= BEfallthru; | |
1170 result |= r & ~(BEbreak | BEcontinue); | |
1171 } | |
1172 if (increment && increment->canThrow()) | |
1173 result |= BEthrow; | |
1174 return result; | |
1025 } | 1175 } |
1026 | 1176 |
1027 int ForStatement::fallOffEnd() | 1177 int ForStatement::fallOffEnd() |
1028 { | 1178 { |
1029 if (body) | 1179 if (body) |
1214 arg->type = e->type; | 1364 arg->type = e->type; |
1215 Initializer *ie = new ExpInitializer(0, e); | 1365 Initializer *ie = new ExpInitializer(0, e); |
1216 VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie); | 1366 VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie); |
1217 if (e->isConst()) | 1367 if (e->isConst()) |
1218 v->storage_class |= STCconst; | 1368 v->storage_class |= STCconst; |
1219 #if V2 | |
1220 else | |
1221 v->storage_class |= STCfinal; | |
1222 #endif | |
1223 var = v; | 1369 var = v; |
1224 } | 1370 } |
1225 } | 1371 } |
1226 else | 1372 else |
1227 { | 1373 { |
1587 int ForeachStatement::usesEH() | 1733 int ForeachStatement::usesEH() |
1588 { | 1734 { |
1589 return body->usesEH(); | 1735 return body->usesEH(); |
1590 } | 1736 } |
1591 | 1737 |
1738 int ForeachStatement::blockExit() | |
1739 { int result = BEfallthru; | |
1740 | |
1741 if (aggr->canThrow()) | |
1742 result |= BEthrow; | |
1743 | |
1744 if (body) | |
1745 { | |
1746 result |= body->blockExit() & ~(BEbreak | BEcontinue); | |
1747 } | |
1748 return result; | |
1749 } | |
1750 | |
1592 int ForeachStatement::fallOffEnd() | 1751 int ForeachStatement::fallOffEnd() |
1593 { | 1752 { |
1594 if (body) | 1753 if (body) |
1595 body->fallOffEnd(); | 1754 body->fallOffEnd(); |
1596 return TRUE; | 1755 return TRUE; |
1605 | 1764 |
1606 void ForeachStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 1765 void ForeachStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
1607 { | 1766 { |
1608 buf->writestring(Token::toChars(op)); | 1767 buf->writestring(Token::toChars(op)); |
1609 buf->writestring(" ("); | 1768 buf->writestring(" ("); |
1610 int i; | |
1611 for (int i = 0; i < arguments->dim; i++) | 1769 for (int i = 0; i < arguments->dim; i++) |
1612 { | 1770 { |
1613 Argument *a = (Argument *)arguments->data[i]; | 1771 Argument *a = (Argument *)arguments->data[i]; |
1614 if (i) | 1772 if (i) |
1615 buf->writestring(", "); | 1773 buf->writestring(", "); |
1716 int IfStatement::usesEH() | 1874 int IfStatement::usesEH() |
1717 { | 1875 { |
1718 return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH()); | 1876 return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH()); |
1719 } | 1877 } |
1720 | 1878 |
1879 int IfStatement::blockExit() | |
1880 { | |
1881 //printf("IfStatement::blockExit(%p)\n", this); | |
1882 | |
1883 int result = BEnone; | |
1884 if (condition->canThrow()) | |
1885 result |= BEthrow; | |
1886 if (condition->isBool(TRUE)) | |
1887 { | |
1888 if (ifbody) | |
1889 result |= ifbody->blockExit(); | |
1890 else | |
1891 result |= BEfallthru; | |
1892 } | |
1893 else if (condition->isBool(FALSE)) | |
1894 { | |
1895 if (elsebody) | |
1896 result |= elsebody->blockExit(); | |
1897 else | |
1898 result |= BEfallthru; | |
1899 } | |
1900 else | |
1901 { | |
1902 if (ifbody) | |
1903 result |= ifbody->blockExit(); | |
1904 else | |
1905 result |= BEfallthru; | |
1906 if (elsebody) | |
1907 result |= elsebody->blockExit(); | |
1908 else | |
1909 result |= BEfallthru; | |
1910 } | |
1911 //printf("IfStatement::blockExit(%p) = x%x\n", this, result); | |
1912 return result; | |
1913 } | |
1914 | |
1721 int IfStatement::fallOffEnd() | 1915 int IfStatement::fallOffEnd() |
1722 { | 1916 { |
1723 if (!ifbody || ifbody->fallOffEnd() || | 1917 if (!ifbody || ifbody->fallOffEnd() || |
1724 !elsebody || elsebody->fallOffEnd()) | 1918 !elsebody || elsebody->fallOffEnd()) |
1725 return TRUE; | 1919 return TRUE; |
1810 | 2004 |
1811 void ConditionalStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 2005 void ConditionalStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
1812 { | 2006 { |
1813 condition->toCBuffer(buf, hgs); | 2007 condition->toCBuffer(buf, hgs); |
1814 buf->writenl(); | 2008 buf->writenl(); |
2009 buf->writeByte('{'); | |
2010 buf->writenl(); | |
1815 if (ifbody) | 2011 if (ifbody) |
1816 ifbody->toCBuffer(buf, hgs); | 2012 ifbody->toCBuffer(buf, hgs); |
2013 buf->writeByte('}'); | |
2014 buf->writenl(); | |
1817 if (elsebody) | 2015 if (elsebody) |
1818 { | 2016 { |
1819 buf->writestring("else"); | 2017 buf->writestring("else"); |
1820 buf->writenl(); | 2018 buf->writenl(); |
2019 buf->writeByte('{'); | |
2020 buf->writenl(); | |
1821 elsebody->toCBuffer(buf, hgs); | 2021 elsebody->toCBuffer(buf, hgs); |
2022 buf->writeByte('}'); | |
2023 buf->writenl(); | |
1822 } | 2024 } |
1823 buf->writenl(); | 2025 buf->writenl(); |
1824 } | 2026 } |
1825 | 2027 |
1826 | 2028 |
1906 int PragmaStatement::usesEH() | 2108 int PragmaStatement::usesEH() |
1907 { | 2109 { |
1908 return body && body->usesEH(); | 2110 return body && body->usesEH(); |
1909 } | 2111 } |
1910 | 2112 |
2113 int PragmaStatement::blockExit() | |
2114 { | |
2115 int result = BEfallthru; | |
2116 #if 0 // currently, no code is generated for Pragma's, so it's just fallthru | |
2117 if (arrayExpressionCanThrow(args)) | |
2118 result |= BEthrow; | |
2119 if (body) | |
2120 result |= body->blockExit(); | |
2121 #endif | |
2122 return result; | |
2123 } | |
2124 | |
1911 int PragmaStatement::fallOffEnd() | 2125 int PragmaStatement::fallOffEnd() |
1912 { | 2126 { |
1913 if (body) | 2127 if (body) |
1914 return body->fallOffEnd(); | 2128 return body->fallOffEnd(); |
1915 return TRUE; | 2129 return TRUE; |
2093 } | 2307 } |
2094 | 2308 |
2095 int SwitchStatement::usesEH() | 2309 int SwitchStatement::usesEH() |
2096 { | 2310 { |
2097 return body ? body->usesEH() : 0; | 2311 return body ? body->usesEH() : 0; |
2312 } | |
2313 | |
2314 int SwitchStatement::blockExit() | |
2315 { int result = BEnone; | |
2316 if (condition->canThrow()) | |
2317 result |= BEthrow; | |
2318 | |
2319 if (body) | |
2320 { result |= body->blockExit(); | |
2321 if (result & BEbreak) | |
2322 { result |= BEfallthru; | |
2323 result &= ~BEbreak; | |
2324 } | |
2325 } | |
2326 else | |
2327 result |= BEfallthru; | |
2328 | |
2329 return result; | |
2098 } | 2330 } |
2099 | 2331 |
2100 int SwitchStatement::fallOffEnd() | 2332 int SwitchStatement::fallOffEnd() |
2101 { | 2333 { |
2102 if (body) | 2334 if (body) |
2202 int CaseStatement::usesEH() | 2434 int CaseStatement::usesEH() |
2203 { | 2435 { |
2204 return statement->usesEH(); | 2436 return statement->usesEH(); |
2205 } | 2437 } |
2206 | 2438 |
2439 int CaseStatement::blockExit() | |
2440 { | |
2441 return statement->blockExit(); | |
2442 } | |
2443 | |
2207 int CaseStatement::fallOffEnd() | 2444 int CaseStatement::fallOffEnd() |
2208 { | 2445 { |
2209 return statement->fallOffEnd(); | 2446 return statement->fallOffEnd(); |
2210 } | 2447 } |
2211 | 2448 |
2241 return s; | 2478 return s; |
2242 } | 2479 } |
2243 | 2480 |
2244 Statement *DefaultStatement::semantic(Scope *sc) | 2481 Statement *DefaultStatement::semantic(Scope *sc) |
2245 { | 2482 { |
2483 //printf("DefaultStatement::semantic()\n"); | |
2246 if (sc->sw) | 2484 if (sc->sw) |
2247 { | 2485 { |
2248 if (sc->sw->sdefault) | 2486 if (sc->sw->sdefault) |
2249 { | 2487 { |
2250 error("switch statement already has a default"); | 2488 error("switch statement already has a default"); |
2258 } | 2496 } |
2259 | 2497 |
2260 int DefaultStatement::usesEH() | 2498 int DefaultStatement::usesEH() |
2261 { | 2499 { |
2262 return statement->usesEH(); | 2500 return statement->usesEH(); |
2501 } | |
2502 | |
2503 int DefaultStatement::blockExit() | |
2504 { | |
2505 return statement->blockExit(); | |
2263 } | 2506 } |
2264 | 2507 |
2265 int DefaultStatement::fallOffEnd() | 2508 int DefaultStatement::fallOffEnd() |
2266 { | 2509 { |
2267 return statement->fallOffEnd(); | 2510 return statement->fallOffEnd(); |
2298 enclosinghandler = sc->tfOfTry; | 2541 enclosinghandler = sc->tfOfTry; |
2299 sw = sc->sw; | 2542 sw = sc->sw; |
2300 if (!sw) | 2543 if (!sw) |
2301 error("goto default not in switch statement"); | 2544 error("goto default not in switch statement"); |
2302 return this; | 2545 return this; |
2546 } | |
2547 | |
2548 int GotoDefaultStatement::blockExit() | |
2549 { | |
2550 return BEgoto; | |
2303 } | 2551 } |
2304 | 2552 |
2305 int GotoDefaultStatement::fallOffEnd() | 2553 int GotoDefaultStatement::fallOffEnd() |
2306 { | 2554 { |
2307 return FALSE; | 2555 return FALSE; |
2349 } | 2597 } |
2350 } | 2598 } |
2351 return this; | 2599 return this; |
2352 } | 2600 } |
2353 | 2601 |
2602 int GotoCaseStatement::blockExit() | |
2603 { | |
2604 return BEgoto; | |
2605 } | |
2606 | |
2354 int GotoCaseStatement::fallOffEnd() | 2607 int GotoCaseStatement::fallOffEnd() |
2355 { | 2608 { |
2356 return FALSE; | 2609 return FALSE; |
2357 } | 2610 } |
2358 | 2611 |
2370 /******************************** SwitchErrorStatement ***************************/ | 2623 /******************************** SwitchErrorStatement ***************************/ |
2371 | 2624 |
2372 SwitchErrorStatement::SwitchErrorStatement(Loc loc) | 2625 SwitchErrorStatement::SwitchErrorStatement(Loc loc) |
2373 : Statement(loc) | 2626 : Statement(loc) |
2374 { | 2627 { |
2628 } | |
2629 | |
2630 int SwitchErrorStatement::blockExit() | |
2631 { | |
2632 return BEthrow; | |
2375 } | 2633 } |
2376 | 2634 |
2377 int SwitchErrorStatement::fallOffEnd() | 2635 int SwitchErrorStatement::fallOffEnd() |
2378 { | 2636 { |
2379 return FALSE; | 2637 return FALSE; |
2425 } | 2683 } |
2426 } | 2684 } |
2427 | 2685 |
2428 Type *tret = fd->type->nextOf(); | 2686 Type *tret = fd->type->nextOf(); |
2429 if (fd->tintro) | 2687 if (fd->tintro) |
2688 /* We'll be implicitly casting the return expression to tintro | |
2689 */ | |
2430 tret = fd->tintro->nextOf(); | 2690 tret = fd->tintro->nextOf(); |
2431 Type *tbret = NULL; | 2691 Type *tbret = NULL; |
2432 | 2692 |
2433 if (tret) | 2693 if (tret) |
2434 tbret = tret->toBasetype(); | 2694 tbret = tret->toBasetype(); |
2634 } | 2894 } |
2635 return gs; | 2895 return gs; |
2636 } | 2896 } |
2637 | 2897 |
2638 if (exp && tbret->ty == Tvoid && !fd->isMain()) | 2898 if (exp && tbret->ty == Tvoid && !fd->isMain()) |
2639 { Statement *s; | 2899 { |
2640 | 2900 /* Replace: |
2641 s = new ExpStatement(loc, exp); | 2901 * return exp; |
2902 * with: | |
2903 * exp; return; | |
2904 */ | |
2905 Statement *s = new ExpStatement(loc, exp); | |
2642 loc = 0; | 2906 loc = 0; |
2643 exp = NULL; | 2907 exp = NULL; |
2644 return new CompoundStatement(loc, s, this); | 2908 return new CompoundStatement(loc, s, this); |
2645 } | 2909 } |
2646 | 2910 |
2647 return this; | 2911 return this; |
2912 } | |
2913 | |
2914 int ReturnStatement::blockExit() | |
2915 { int result = BEreturn; | |
2916 | |
2917 if (exp && exp->canThrow()) | |
2918 result |= BEthrow; | |
2919 return result; | |
2648 } | 2920 } |
2649 | 2921 |
2650 int ReturnStatement::fallOffEnd() | 2922 int ReturnStatement::fallOffEnd() |
2651 { | 2923 { |
2652 return FALSE; | 2924 return FALSE; |
2676 return s; | 2948 return s; |
2677 } | 2949 } |
2678 | 2950 |
2679 Statement *BreakStatement::semantic(Scope *sc) | 2951 Statement *BreakStatement::semantic(Scope *sc) |
2680 { | 2952 { |
2953 //printf("BreakStatement::semantic()\n"); | |
2681 enclosinghandler = sc->tfOfTry; | 2954 enclosinghandler = sc->tfOfTry; |
2682 // If: | 2955 // If: |
2683 // break Identifier; | 2956 // break Identifier; |
2684 if (ident) | 2957 if (ident) |
2685 { | 2958 { |
2737 error("break is not inside a loop or switch"); | 3010 error("break is not inside a loop or switch"); |
2738 } | 3011 } |
2739 return this; | 3012 return this; |
2740 } | 3013 } |
2741 | 3014 |
3015 int BreakStatement::blockExit() | |
3016 { | |
3017 //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak); | |
3018 return ident ? BEgoto : BEbreak; | |
3019 } | |
3020 | |
2742 int BreakStatement::fallOffEnd() | 3021 int BreakStatement::fallOffEnd() |
2743 { | 3022 { |
2744 return FALSE; | 3023 return FALSE; |
2745 } | 3024 } |
2746 | 3025 |
2840 error("continue is not inside a loop"); | 3119 error("continue is not inside a loop"); |
2841 } | 3120 } |
2842 return this; | 3121 return this; |
2843 } | 3122 } |
2844 | 3123 |
3124 int ContinueStatement::blockExit() | |
3125 { | |
3126 return ident ? BEgoto : BEcontinue; | |
3127 } | |
3128 | |
2845 int ContinueStatement::fallOffEnd() | 3129 int ContinueStatement::fallOffEnd() |
2846 { | 3130 { |
2847 return FALSE; | 3131 return FALSE; |
2848 } | 3132 } |
2849 | 3133 |
2928 } | 3212 } |
2929 | 3213 |
2930 int SynchronizedStatement::usesEH() | 3214 int SynchronizedStatement::usesEH() |
2931 { | 3215 { |
2932 return TRUE; | 3216 return TRUE; |
3217 } | |
3218 | |
3219 int SynchronizedStatement::blockExit() | |
3220 { | |
3221 return body ? body->blockExit() : BEfallthru; | |
2933 } | 3222 } |
2934 | 3223 |
2935 int SynchronizedStatement::fallOffEnd() | 3224 int SynchronizedStatement::fallOffEnd() |
2936 { | 3225 { |
2937 return body ? body->fallOffEnd() : TRUE; | 3226 return body ? body->fallOffEnd() : TRUE; |
3040 int WithStatement::usesEH() | 3329 int WithStatement::usesEH() |
3041 { | 3330 { |
3042 return body ? body->usesEH() : 0; | 3331 return body ? body->usesEH() : 0; |
3043 } | 3332 } |
3044 | 3333 |
3334 int WithStatement::blockExit() | |
3335 { | |
3336 int result = BEnone; | |
3337 if (exp->canThrow()) | |
3338 result = BEthrow; | |
3339 if (body) | |
3340 result |= body->blockExit(); | |
3341 else | |
3342 result |= BEfallthru; | |
3343 return result; | |
3344 } | |
3345 | |
3045 int WithStatement::fallOffEnd() | 3346 int WithStatement::fallOffEnd() |
3046 { | 3347 { |
3047 return body ? body->fallOffEnd() : TRUE; | 3348 return body ? body->fallOffEnd() : TRUE; |
3048 } | 3349 } |
3049 | 3350 |
3073 | 3374 |
3074 Statement *TryCatchStatement::semantic(Scope *sc) | 3375 Statement *TryCatchStatement::semantic(Scope *sc) |
3075 { | 3376 { |
3076 body = body->semanticScope(sc, NULL /*this*/, NULL); | 3377 body = body->semanticScope(sc, NULL /*this*/, NULL); |
3077 | 3378 |
3078 for (int i = 0; i < catches->dim; i++) | 3379 /* Even if body is NULL, still do semantic analysis on catches |
3079 { Catch *c; | 3380 */ |
3080 | 3381 for (size_t i = 0; i < catches->dim; i++) |
3081 c = (Catch *)catches->data[i]; | 3382 { Catch *c = (Catch *)catches->data[i]; |
3082 c->semantic(sc); | 3383 c->semantic(sc); |
3083 | 3384 |
3084 // Determine if current catch 'hides' any previous catches | 3385 // Determine if current catch 'hides' any previous catches |
3085 for (int j = 0; j < i; j++) | 3386 for (size_t j = 0; j < i; j++) |
3086 { Catch *cj = (Catch *)catches->data[j]; | 3387 { Catch *cj = (Catch *)catches->data[j]; |
3087 char *si = c->loc.toChars(); | 3388 char *si = c->loc.toChars(); |
3088 char *sj = cj->loc.toChars(); | 3389 char *sj = cj->loc.toChars(); |
3089 | 3390 |
3090 if (c->type->toBasetype()->implicitConvTo(cj->type->toBasetype())) | 3391 if (c->type->toBasetype()->implicitConvTo(cj->type->toBasetype())) |
3100 } | 3401 } |
3101 | 3402 |
3102 int TryCatchStatement::usesEH() | 3403 int TryCatchStatement::usesEH() |
3103 { | 3404 { |
3104 return TRUE; | 3405 return TRUE; |
3406 } | |
3407 | |
3408 int TryCatchStatement::blockExit() | |
3409 { int result; | |
3410 | |
3411 assert(body); | |
3412 result = body->blockExit(); | |
3413 | |
3414 for (size_t i = 0; i < catches->dim; i++) | |
3415 { | |
3416 Catch *c = (Catch *)catches->data[i]; | |
3417 result |= c->blockExit(); | |
3418 } | |
3419 return result; | |
3105 } | 3420 } |
3106 | 3421 |
3107 int TryCatchStatement::fallOffEnd() | 3422 int TryCatchStatement::fallOffEnd() |
3108 { | 3423 { |
3109 int result = FALSE; | 3424 int result = FALSE; |
3124 { | 3439 { |
3125 buf->writestring("try"); | 3440 buf->writestring("try"); |
3126 buf->writenl(); | 3441 buf->writenl(); |
3127 if (body) | 3442 if (body) |
3128 body->toCBuffer(buf, hgs); | 3443 body->toCBuffer(buf, hgs); |
3129 int i; | 3444 for (size_t i = 0; i < catches->dim; i++) |
3130 for (i = 0; i < catches->dim; i++) | |
3131 { | 3445 { |
3132 Catch *c = (Catch *)catches->data[i]; | 3446 Catch *c = (Catch *)catches->data[i]; |
3133 c->toCBuffer(buf, hgs); | 3447 c->toCBuffer(buf, hgs); |
3134 } | 3448 } |
3135 } | 3449 } |
3191 handler = handler->semantic(sc); | 3505 handler = handler->semantic(sc); |
3192 | 3506 |
3193 sc->pop(); | 3507 sc->pop(); |
3194 } | 3508 } |
3195 | 3509 |
3510 int Catch::blockExit() | |
3511 { | |
3512 return handler ? handler->blockExit() : BEfallthru; | |
3513 } | |
3514 | |
3196 void Catch::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 3515 void Catch::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3197 { | 3516 { |
3198 buf->writestring("catch"); | 3517 buf->writestring("catch"); |
3199 if (type) | 3518 if (type) |
3200 { buf->writebyte('('); | 3519 { buf->writebyte('('); |
3202 buf->writebyte(')'); | 3521 buf->writebyte(')'); |
3203 } | 3522 } |
3204 buf->writenl(); | 3523 buf->writenl(); |
3205 buf->writebyte('{'); | 3524 buf->writebyte('{'); |
3206 buf->writenl(); | 3525 buf->writenl(); |
3207 handler->toCBuffer(buf, hgs); | 3526 if (handler) |
3527 handler->toCBuffer(buf, hgs); | |
3208 buf->writebyte('}'); | 3528 buf->writebyte('}'); |
3209 buf->writenl(); | 3529 buf->writenl(); |
3210 } | 3530 } |
3211 | 3531 |
3212 /****************************** TryFinallyStatement ***************************/ | 3532 /****************************** TryFinallyStatement ***************************/ |
3267 int TryFinallyStatement::usesEH() | 3587 int TryFinallyStatement::usesEH() |
3268 { | 3588 { |
3269 return TRUE; | 3589 return TRUE; |
3270 } | 3590 } |
3271 | 3591 |
3592 int TryFinallyStatement::blockExit() | |
3593 { | |
3594 int result = body->blockExit(); | |
3595 return result; | |
3596 } | |
3597 | |
3272 int TryFinallyStatement::fallOffEnd() | 3598 int TryFinallyStatement::fallOffEnd() |
3273 { int result; | 3599 { int result; |
3274 | 3600 |
3275 result = body ? body->fallOffEnd() : TRUE; | 3601 result = body ? body->fallOffEnd() : TRUE; |
3276 // if (finalbody) | 3602 // if (finalbody) |
3296 | 3622 |
3297 Statement *OnScopeStatement::semantic(Scope *sc) | 3623 Statement *OnScopeStatement::semantic(Scope *sc) |
3298 { | 3624 { |
3299 /* semantic is called on results of scopeCode() */ | 3625 /* semantic is called on results of scopeCode() */ |
3300 return this; | 3626 return this; |
3627 } | |
3628 | |
3629 int OnScopeStatement::blockExit() | |
3630 { // At this point, this statement is just an empty placeholder | |
3631 return BEfallthru; | |
3301 } | 3632 } |
3302 | 3633 |
3303 void OnScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | 3634 void OnScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3304 { | 3635 { |
3305 buf->writestring(Token::toChars(tok)); | 3636 buf->writestring(Token::toChars(tok)); |
3389 if (!exp->type->toBasetype()->isClassHandle()) | 3720 if (!exp->type->toBasetype()->isClassHandle()) |
3390 error("can only throw class objects, not type %s", exp->type->toChars()); | 3721 error("can only throw class objects, not type %s", exp->type->toChars()); |
3391 return this; | 3722 return this; |
3392 } | 3723 } |
3393 | 3724 |
3725 int ThrowStatement::blockExit() | |
3726 { | |
3727 return BEthrow; // obviously | |
3728 } | |
3729 | |
3394 int ThrowStatement::fallOffEnd() | 3730 int ThrowStatement::fallOffEnd() |
3395 { | 3731 { |
3396 return FALSE; | 3732 return FALSE; |
3397 } | 3733 } |
3398 | 3734 |
3445 a->data[i] = s; | 3781 a->data[i] = s; |
3446 } | 3782 } |
3447 } | 3783 } |
3448 | 3784 |
3449 return a; | 3785 return a; |
3786 } | |
3787 | |
3788 int VolatileStatement::blockExit() | |
3789 { | |
3790 return statement ? statement->blockExit() : BEfallthru; | |
3450 } | 3791 } |
3451 | 3792 |
3452 int VolatileStatement::fallOffEnd() | 3793 int VolatileStatement::fallOffEnd() |
3453 { | 3794 { |
3454 return statement ? statement->fallOffEnd() : TRUE; | 3795 return statement ? statement->fallOffEnd() : TRUE; |
3508 return s; | 3849 return s; |
3509 } | 3850 } |
3510 if (label->statement && label->statement->tf != sc->tf) | 3851 if (label->statement && label->statement->tf != sc->tf) |
3511 error("cannot goto in or out of finally block"); | 3852 error("cannot goto in or out of finally block"); |
3512 return this; | 3853 return this; |
3854 } | |
3855 | |
3856 int GotoStatement::blockExit() | |
3857 { | |
3858 //printf("GotoStatement::blockExit(%p)\n", this); | |
3859 return BEgoto; | |
3513 } | 3860 } |
3514 | 3861 |
3515 int GotoStatement::fallOffEnd() | 3862 int GotoStatement::fallOffEnd() |
3516 { | 3863 { |
3517 return FALSE; | 3864 return FALSE; |
3599 int LabelStatement::usesEH() | 3946 int LabelStatement::usesEH() |
3600 { | 3947 { |
3601 return statement ? statement->usesEH() : FALSE; | 3948 return statement ? statement->usesEH() : FALSE; |
3602 } | 3949 } |
3603 | 3950 |
3951 int LabelStatement::blockExit() | |
3952 { | |
3953 //printf("LabelStatement::blockExit(%p)\n", this); | |
3954 return statement ? statement->blockExit() : BEfallthru; | |
3955 } | |
3956 | |
3604 int LabelStatement::fallOffEnd() | 3957 int LabelStatement::fallOffEnd() |
3605 { | 3958 { |
3606 return statement ? statement->fallOffEnd() : TRUE; | 3959 return statement ? statement->fallOffEnd() : TRUE; |
3607 } | 3960 } |
3608 | 3961 |