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