Mercurial > projects > ldc
comparison dmd2/statement.c @ 1577:e4f7b5d9c68a
DMD 2.032 Merge.
author | Robert Clipsham <robert@octarineparrot.com> |
---|---|
date | Tue, 08 Sep 2009 10:07:56 +0100 |
parents | 54b3c1394d62 |
children | 1dee66f6ec0b |
comparison
equal
deleted
inserted
replaced
1576:4551475bc6b6 | 1577:e4f7b5d9c68a |
---|---|
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 #include "attrib.h" |
31 | 31 |
32 #if IN_LLVM | |
33 #include "gen/tollvm.h" | |
34 #elif IN_DMD | |
35 extern int os_critsecsize(); | |
36 #endif | |
37 | |
32 /******************************** Statement ***************************/ | 38 /******************************** Statement ***************************/ |
33 | 39 |
34 Statement::Statement(Loc loc) | 40 Statement::Statement(Loc loc) |
35 : loc(loc) | 41 : loc(loc) |
36 { | 42 { |
180 { | 186 { |
181 return NULL; | 187 return NULL; |
182 } | 188 } |
183 | 189 |
184 | 190 |
191 /******************************** PeelStatement ***************************/ | |
192 | |
193 PeelStatement::PeelStatement(Statement *s) | |
194 : Statement(s->loc) | |
195 { | |
196 this->s = s; | |
197 } | |
198 | |
199 Statement *PeelStatement::semantic(Scope *sc) | |
200 { | |
201 /* "peel" off this wrapper, and don't run semantic() | |
202 * on the result. | |
203 */ | |
204 return s; | |
205 } | |
206 | |
185 /******************************** ExpStatement ***************************/ | 207 /******************************** ExpStatement ***************************/ |
186 | 208 |
187 ExpStatement::ExpStatement(Loc loc, Expression *exp) | 209 ExpStatement::ExpStatement(Loc loc, Expression *exp) |
188 : Statement(loc) | 210 : Statement(loc) |
189 { | 211 { |
342 | 364 |
343 e = v->callAutoDtor(sc); | 365 e = v->callAutoDtor(sc); |
344 if (e) | 366 if (e) |
345 { | 367 { |
346 //printf("dtor is: "); e->print(); | 368 //printf("dtor is: "); e->print(); |
369 #if 0 | |
370 if (v->type->toBasetype()->ty == Tstruct) | |
371 { /* Need a 'gate' to turn on/off destruction, | |
372 * in case v gets moved elsewhere. | |
373 */ | |
374 Identifier *id = Lexer::uniqueId("__runDtor"); | |
375 ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(1)); | |
376 VarDeclaration *rd = new VarDeclaration(loc, Type::tint32, id, ie); | |
377 *sentry = new DeclarationStatement(loc, rd); | |
378 v->rundtor = rd; | |
379 | |
380 /* Rewrite e as: | |
381 * rundtor && e | |
382 */ | |
383 Expression *ve = new VarExp(loc, v->rundtor); | |
384 e = new AndAndExp(loc, ve, e); | |
385 e->type = Type::tbool; | |
386 } | |
387 #endif | |
347 *sfinally = new ExpStatement(loc, e); | 388 *sfinally = new ExpStatement(loc, e); |
348 } | 389 } |
349 } | 390 } |
350 } | 391 } |
351 } | 392 } |
416 | 457 |
417 s->scopeCode(sc, &sentry, &sexception, &sfinally); | 458 s->scopeCode(sc, &sentry, &sexception, &sfinally); |
418 if (sentry) | 459 if (sentry) |
419 { | 460 { |
420 sentry = sentry->semantic(sc); | 461 sentry = sentry->semantic(sc); |
421 statements->data[i] = sentry; | 462 if (s->isDeclarationStatement()) |
463 { statements->insert(i, sentry); | |
464 i++; | |
465 } | |
466 else | |
467 statements->data[i] = sentry; | |
422 } | 468 } |
423 if (sexception) | 469 if (sexception) |
424 { | 470 { |
425 if (i + 1 == statements->dim && !sfinally) | 471 if (i + 1 == statements->dim && !sfinally) |
426 { | 472 { |
560 { | 606 { |
561 //printf("result = x%x\n", result); | 607 //printf("result = x%x\n", result); |
562 //printf("%s\n", s->toChars()); | 608 //printf("%s\n", s->toChars()); |
563 if (!(result & BEfallthru) && !s->comeFrom()) | 609 if (!(result & BEfallthru) && !s->comeFrom()) |
564 { | 610 { |
565 s->warning("statement is not reachable"); | 611 if (s->blockExit() != BEhalt) |
612 s->warning("statement is not reachable"); | |
566 } | 613 } |
567 | 614 |
568 result &= ~BEfallthru; | 615 result &= ~BEfallthru; |
569 result |= s->blockExit(); | 616 result |= s->blockExit(); |
570 } | 617 } |
907 } | 954 } |
908 | 955 |
909 | 956 |
910 Statement *WhileStatement::semantic(Scope *sc) | 957 Statement *WhileStatement::semantic(Scope *sc) |
911 { | 958 { |
912 #if 0 | 959 /* Rewrite as a for(;condition;) loop |
913 if (condition->op == TOKmatch) | 960 */ |
914 { | 961 |
915 /* Rewrite while (condition) body as: | 962 Statement *s = new ForStatement(loc, NULL, condition, NULL, body); |
916 * if (condition) | 963 s = s->semantic(sc); |
917 * do | 964 return s; |
918 * body | |
919 * while ((_match = _match.opNext), _match); | |
920 */ | |
921 | |
922 Expression *ew = new IdentifierExp(0, Id::_match); | |
923 ew = new DotIdExp(0, ew, Id::next); | |
924 ew = new AssignExp(0, new IdentifierExp(0, Id::_match), ew); | |
925 ////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0)); | |
926 Expression *ev = new IdentifierExp(0, Id::_match); | |
927 //ev = new CastExp(0, ev, Type::tvoidptr); | |
928 ew = new CommaExp(0, ew, ev); | |
929 Statement *sw = new DoStatement(loc, body, ew); | |
930 Statement *si = new IfStatement(loc, condition, sw, NULL); | |
931 return si->semantic(sc); | |
932 } | |
933 #endif | |
934 | |
935 condition = condition->semantic(sc); | |
936 condition = resolveProperties(sc, condition); | |
937 condition = condition->optimize(WANTvalue); | |
938 condition = condition->checkToBoolean(); | |
939 | |
940 sc->noctor++; | |
941 | |
942 Scope *scd = sc->push(); | |
943 scd->sbreak = this; | |
944 scd->scontinue = this; | |
945 if (body) | |
946 body = body->semantic(scd); | |
947 scd->pop(); | |
948 | |
949 sc->noctor--; | |
950 | |
951 return this; | |
952 } | 965 } |
953 | 966 |
954 int WhileStatement::hasBreak() | 967 int WhileStatement::hasBreak() |
955 { | 968 { |
956 return TRUE; | 969 return TRUE; |
961 return TRUE; | 974 return TRUE; |
962 } | 975 } |
963 | 976 |
964 int WhileStatement::usesEH() | 977 int WhileStatement::usesEH() |
965 { | 978 { |
979 assert(0); | |
966 return body ? body->usesEH() : 0; | 980 return body ? body->usesEH() : 0; |
967 } | 981 } |
968 | 982 |
969 int WhileStatement::blockExit() | 983 int WhileStatement::blockExit() |
970 { | 984 { |
985 assert(0); | |
971 //printf("WhileStatement::blockExit(%p)\n", this); | 986 //printf("WhileStatement::blockExit(%p)\n", this); |
972 | 987 |
973 int result = BEnone; | 988 int result = BEnone; |
974 if (condition->canThrow()) | 989 if (condition->canThrow()) |
975 result |= BEthrow; | 990 result |= BEthrow; |
996 } | 1011 } |
997 | 1012 |
998 | 1013 |
999 int WhileStatement::comeFrom() | 1014 int WhileStatement::comeFrom() |
1000 { | 1015 { |
1016 assert(0); | |
1001 if (body) | 1017 if (body) |
1002 return body->comeFrom(); | 1018 return body->comeFrom(); |
1003 return FALSE; | 1019 return FALSE; |
1004 } | 1020 } |
1005 | 1021 |
1191 return result; | 1207 return result; |
1192 } | 1208 } |
1193 if (condition) | 1209 if (condition) |
1194 { if (condition->canThrow()) | 1210 { if (condition->canThrow()) |
1195 result |= BEthrow; | 1211 result |= BEthrow; |
1212 if (condition->isBool(TRUE)) | |
1213 result &= ~BEfallthru; | |
1214 else if (condition->isBool(FALSE)) | |
1215 return result; | |
1196 } | 1216 } |
1197 else | 1217 else |
1198 result &= ~BEfallthru; // the body must do the exiting | 1218 result &= ~BEfallthru; // the body must do the exiting |
1199 if (body) | 1219 if (body) |
1200 { int r = body->blockExit(); | 1220 { int r = body->blockExit(); |
1450 } | 1470 } |
1451 | 1471 |
1452 for (size_t i = 0; i < dim; i++) | 1472 for (size_t i = 0; i < dim; i++) |
1453 { // Declare args | 1473 { // Declare args |
1454 Argument *arg = (Argument *)arguments->data[i]; | 1474 Argument *arg = (Argument *)arguments->data[i]; |
1475 Type *argtype = arg->type->semantic(loc, sc); | |
1455 VarDeclaration *var; | 1476 VarDeclaration *var; |
1456 | 1477 |
1457 var = new VarDeclaration(loc, arg->type, arg->ident, NULL); | 1478 var = new VarDeclaration(loc, argtype, arg->ident, NULL); |
1458 var->storage_class |= STCforeach; | 1479 var->storage_class |= STCforeach; |
1459 var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR); | 1480 var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR); |
1481 if (var->storage_class & (STCref | STCout)) | |
1482 var->storage_class |= STCnodtor; | |
1460 if (dim == 2 && i == 0) | 1483 if (dim == 2 && i == 0) |
1461 { key = var; | 1484 { key = var; |
1462 //var->storage_class |= STCfinal; | 1485 //var->storage_class |= STCfinal; |
1463 } | 1486 } |
1464 else | 1487 else |
1469 if (var->storage_class & STCref && !tn->isMutable()) | 1492 if (var->storage_class & STCref && !tn->isMutable()) |
1470 { | 1493 { |
1471 var->storage_class |= STCconst; | 1494 var->storage_class |= STCconst; |
1472 } | 1495 } |
1473 } | 1496 } |
1474 #if 1 | 1497 #if 0 |
1475 DeclarationExp *de = new DeclarationExp(loc, var); | 1498 DeclarationExp *de = new DeclarationExp(loc, var); |
1476 de->semantic(sc); | 1499 de->semantic(sc); |
1477 #else | |
1478 var->semantic(sc); | |
1479 if (!sc->insert(var)) | |
1480 error("%s already defined", var->ident->toChars()); | |
1481 #endif | 1500 #endif |
1482 } | 1501 } |
1483 | 1502 |
1484 sc->sbreak = this; | 1503 #if 1 |
1485 sc->scontinue = this; | 1504 { |
1486 body = body->semantic(sc); | 1505 /* Convert to a ForStatement |
1487 | 1506 * foreach (key, value; a) body => |
1507 * for (T[] tmp = a[], size_t key; key < tmp.length; ++key) | |
1508 * { T value = tmp[k]; body } | |
1509 * | |
1510 * foreach_reverse (key, value; a) body => | |
1511 * for (T[] tmp = a[], size_t key = tmp.length; key--; ) | |
1512 * { T value = tmp[k]; body } | |
1513 */ | |
1514 Identifier *id = Lexer::uniqueId("__aggr"); | |
1515 ExpInitializer *ie = new ExpInitializer(loc, new SliceExp(loc, aggr, NULL, NULL)); | |
1516 VarDeclaration *tmp = new VarDeclaration(loc, aggr->type->nextOf()->arrayOf(), id, ie); | |
1517 | |
1518 Expression *tmp_length = new DotIdExp(loc, new VarExp(loc, tmp), Id::length); | |
1519 | |
1520 if (!key) | |
1521 { | |
1522 Identifier *id = Lexer::uniqueId("__key"); | |
1523 key = new VarDeclaration(loc, Type::tsize_t, id, NULL); | |
1524 } | |
1525 if (op == TOKforeach_reverse) | |
1526 key->init = new ExpInitializer(loc, tmp_length); | |
1527 else | |
1528 key->init = new ExpInitializer(loc, new IntegerExp(0)); | |
1529 | |
1530 Statements *cs = new Statements(); | |
1531 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); | |
1532 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key))); | |
1533 Statement *forinit = new CompoundDeclarationStatement(loc, cs); | |
1534 | |
1535 Expression *cond; | |
1536 if (op == TOKforeach_reverse) | |
1537 // key-- | |
1538 cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key)); | |
1539 else | |
1540 // key < tmp.length | |
1541 cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), tmp_length); | |
1542 | |
1543 Expression *increment = NULL; | |
1544 if (op == TOKforeach) | |
1545 // key += 1 | |
1546 increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1)); | |
1547 | |
1548 // T value = tmp[key]; | |
1549 value->init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, key))); | |
1550 Statement *ds = new DeclarationStatement(loc, new DeclarationExp(loc, value)); | |
1551 | |
1552 body = new CompoundStatement(loc, ds, body); | |
1553 | |
1554 ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body); | |
1555 s = fs->semantic(sc); | |
1556 break; | |
1557 } | |
1558 #else | |
1488 if (tab->nextOf()->implicitConvTo(value->type) < MATCHconst) | 1559 if (tab->nextOf()->implicitConvTo(value->type) < MATCHconst) |
1489 { | 1560 { |
1490 if (aggr->op == TOKstring) | 1561 if (aggr->op == TOKstring) |
1491 aggr = aggr->implicitCastTo(sc, value->type->arrayOf()); | 1562 aggr = aggr->implicitCastTo(sc, value->type->arrayOf()); |
1492 else | 1563 else |
1493 error("foreach: %s is not an array of %s", | 1564 error("foreach: %s is not an array of %s", |
1494 tab->toChars(), value->type->toChars()); | 1565 tab->toChars(), value->type->toChars()); |
1495 } | 1566 } |
1496 | 1567 |
1497 if (key && key->type->ty != Tint32 && key->type->ty != Tuns32) | 1568 if (key) |
1498 { | 1569 { |
1499 if (global.params.is64bit) | 1570 if (global.params.is64bit) |
1500 { | 1571 { |
1501 if (key->type->ty != Tint64 && key->type->ty != Tuns64) | 1572 if (key->type->ty != Tint64 && key->type->ty != Tuns64) |
1502 error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars()); | 1573 error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars()); |
1503 } | 1574 } |
1504 else | 1575 |
1505 error("foreach: key type must be int or uint, not %s", key->type->toChars()); | 1576 if (key->storage_class & (STCout | STCref)) |
1577 error("foreach: key cannot be out or ref"); | |
1506 } | 1578 } |
1507 | 1579 |
1508 if (key && key->storage_class & (STCout | STCref)) | 1580 sc->sbreak = this; |
1509 error("foreach: key cannot be out or ref"); | 1581 sc->scontinue = this; |
1582 body = body->semantic(sc); | |
1510 break; | 1583 break; |
1584 #endif | |
1511 | 1585 |
1512 case Taarray: | 1586 case Taarray: |
1513 if (!checkForArgTypes()) | 1587 if (!checkForArgTypes()) |
1514 return this; | 1588 return this; |
1515 | 1589 |
1743 exps->push(aggr); | 1817 exps->push(aggr); |
1744 size_t keysize = taa->index->size(); | 1818 size_t keysize = taa->index->size(); |
1745 keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1); | 1819 keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1); |
1746 exps->push(new IntegerExp(0, keysize, Type::tsize_t)); | 1820 exps->push(new IntegerExp(0, keysize, Type::tsize_t)); |
1747 | 1821 |
1822 #if IN_LLVM | |
1748 // LDC paint delegate argument to the type runtime expects | 1823 // LDC paint delegate argument to the type runtime expects |
1749 if (!fldeTy->equals(flde->type)) | 1824 if (!fldeTy->equals(flde->type)) |
1750 { | 1825 { |
1751 flde = new CastExp(loc, flde, flde->type); | 1826 flde = new CastExp(loc, flde, flde->type); |
1752 flde->type = fldeTy; | 1827 flde->type = fldeTy; |
1753 } | 1828 } |
1829 #endif | |
1754 exps->push(flde); | 1830 exps->push(flde); |
1755 e = new CallExp(loc, ec, exps); | 1831 e = new CallExp(loc, ec, exps); |
1756 e->type = Type::tindex; // don't run semantic() on e | 1832 e->type = Type::tindex; // don't run semantic() on e |
1757 } | 1833 } |
1758 else if (tab->ty == Tarray || tab->ty == Tsarray) | 1834 else if (tab->ty == Tarray || tab->ty == Tsarray) |
2053 ea.typeCombine(sc); | 2129 ea.typeCombine(sc); |
2054 arg->type = ea.type->mutableOf(); | 2130 arg->type = ea.type->mutableOf(); |
2055 lwr = ea.e1; | 2131 lwr = ea.e1; |
2056 upr = ea.e2; | 2132 upr = ea.e2; |
2057 } | 2133 } |
2134 #if 1 | |
2135 /* Convert to a for loop: | |
2136 * foreach (key; lwr .. upr) => | |
2137 * for (auto key = lwr, auto tmp = upr; key < tmp; ++key) | |
2138 * | |
2139 * foreach_reverse (key; lwr .. upr) => | |
2140 * for (auto tmp = lwr, auto key = upr; key-- > tmp;) | |
2141 */ | |
2142 | |
2143 ExpInitializer *ie = new ExpInitializer(loc, (op == TOKforeach) ? lwr : upr); | |
2144 key = new VarDeclaration(loc, arg->type, arg->ident, ie); | |
2145 | |
2146 Identifier *id = Lexer::uniqueId("__limit"); | |
2147 ie = new ExpInitializer(loc, (op == TOKforeach) ? upr : lwr); | |
2148 VarDeclaration *tmp = new VarDeclaration(loc, arg->type, id, ie); | |
2149 | |
2150 Statements *cs = new Statements(); | |
2151 // Keep order of evaluation as lwr, then upr | |
2152 if (op == TOKforeach) | |
2153 { | |
2154 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key))); | |
2155 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); | |
2156 } | |
2157 else | |
2158 { | |
2159 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); | |
2160 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key))); | |
2161 } | |
2162 Statement *forinit = new CompoundDeclarationStatement(loc, cs); | |
2163 | |
2164 Expression *cond; | |
2165 if (op == TOKforeach_reverse) | |
2166 { // key-- > tmp | |
2167 cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key)); | |
2168 cond = new CmpExp(TOKgt, loc, cond, new VarExp(loc, tmp)); | |
2169 } | |
2170 else | |
2171 // key < tmp | |
2172 cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), new VarExp(loc, tmp)); | |
2173 | |
2174 Expression *increment = NULL; | |
2175 if (op == TOKforeach) | |
2176 // key += 1 | |
2177 increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1)); | |
2178 | |
2179 ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body); | |
2180 s = fs->semantic(sc); | |
2181 return s; | |
2182 #else | |
2058 if (!arg->type->isscalar()) | 2183 if (!arg->type->isscalar()) |
2059 error("%s is not a scalar type", arg->type->toChars()); | 2184 error("%s is not a scalar type", arg->type->toChars()); |
2060 | 2185 |
2061 sym = new ScopeDsymbol(); | 2186 sym = new ScopeDsymbol(); |
2062 sym->parent = sc->scopesym; | 2187 sym->parent = sc->scopesym; |
2076 body = body->semantic(sc); | 2201 body = body->semantic(sc); |
2077 | 2202 |
2078 sc->noctor--; | 2203 sc->noctor--; |
2079 sc->pop(); | 2204 sc->pop(); |
2080 return s; | 2205 return s; |
2206 #endif | |
2081 } | 2207 } |
2082 | 2208 |
2083 int ForeachRangeStatement::hasBreak() | 2209 int ForeachRangeStatement::hasBreak() |
2084 { | 2210 { |
2085 return TRUE; | 2211 return TRUE; |
2090 return TRUE; | 2216 return TRUE; |
2091 } | 2217 } |
2092 | 2218 |
2093 int ForeachRangeStatement::usesEH() | 2219 int ForeachRangeStatement::usesEH() |
2094 { | 2220 { |
2221 assert(0); | |
2095 return body->usesEH(); | 2222 return body->usesEH(); |
2096 } | 2223 } |
2097 | 2224 |
2098 int ForeachRangeStatement::blockExit() | 2225 int ForeachRangeStatement::blockExit() |
2099 { int result = BEfallthru; | 2226 { |
2227 assert(0); | |
2228 int result = BEfallthru; | |
2100 | 2229 |
2101 if (lwr && lwr->canThrow()) | 2230 if (lwr && lwr->canThrow()) |
2102 result |= BEthrow; | 2231 result |= BEthrow; |
2103 else if (upr && upr->canThrow()) | 2232 else if (upr && upr->canThrow()) |
2104 result |= BEthrow; | 2233 result |= BEthrow; |
2111 } | 2240 } |
2112 | 2241 |
2113 | 2242 |
2114 int ForeachRangeStatement::comeFrom() | 2243 int ForeachRangeStatement::comeFrom() |
2115 { | 2244 { |
2245 assert(0); | |
2116 if (body) | 2246 if (body) |
2117 return body->comeFrom(); | 2247 return body->comeFrom(); |
2118 return FALSE; | 2248 return FALSE; |
2119 } | 2249 } |
2120 | 2250 |
2460 // LDC | 2590 // LDC |
2461 else if (ident == Id::allow_inline) | 2591 else if (ident == Id::allow_inline) |
2462 { | 2592 { |
2463 sc->func->allowInlining = true; | 2593 sc->func->allowInlining = true; |
2464 } | 2594 } |
2465 | 2595 #if DMDV2 |
2466 else if (ident == Id::startaddress) | 2596 else if (ident == Id::startaddress) |
2467 { | 2597 { |
2468 if (!args || args->dim != 1) | 2598 if (!args || args->dim != 1) |
2469 error("function name expected for start address"); | 2599 error("function name expected for start address"); |
2470 else | 2600 else |
2481 body = body->semantic(sc); | 2611 body = body->semantic(sc); |
2482 } | 2612 } |
2483 return this; | 2613 return this; |
2484 } | 2614 } |
2485 } | 2615 } |
2616 #endif | |
2486 else | 2617 else |
2487 error("unrecognized pragma(%s)", ident->toChars()); | 2618 error("unrecognized pragma(%s)", ident->toChars()); |
2488 | 2619 |
2489 if (body) | 2620 if (body) |
2490 { | 2621 { |
2655 | 2786 |
2656 Lfoundcase: | 2787 Lfoundcase: |
2657 ; | 2788 ; |
2658 } | 2789 } |
2659 | 2790 |
2660 if (!sc->sw->sdefault) | 2791 if (!sc->sw->sdefault && !isFinal) |
2661 { hasNoDefault = 1; | 2792 { hasNoDefault = 1; |
2662 | 2793 |
2663 warning("switch statement has no default"); | 2794 warning("switch statement has no default"); |
2664 | 2795 |
2665 // Generate runtime error if the default is hit | 2796 // Generate runtime error if the default is hit |
3691 } | 3822 } |
3692 | 3823 |
3693 Statement *SynchronizedStatement::semantic(Scope *sc) | 3824 Statement *SynchronizedStatement::semantic(Scope *sc) |
3694 { | 3825 { |
3695 if (exp) | 3826 if (exp) |
3696 { ClassDeclaration *cd; | 3827 { |
3697 | |
3698 exp = exp->semantic(sc); | 3828 exp = exp->semantic(sc); |
3699 exp = resolveProperties(sc, exp); | 3829 exp = resolveProperties(sc, exp); |
3700 cd = exp->type->isClassHandle(); | 3830 ClassDeclaration *cd = exp->type->isClassHandle(); |
3701 if (!cd) | 3831 if (!cd) |
3702 error("can only synchronize on class objects, not '%s'", exp->type->toChars()); | 3832 error("can only synchronize on class objects, not '%s'", exp->type->toChars()); |
3703 else if (cd->isInterfaceDeclaration()) | 3833 else if (cd->isInterfaceDeclaration()) |
3704 { Type *t = new TypeIdentifier(0, Id::Object); | 3834 { /* Cast the interface to an object, as the object has the monitor, |
3835 * not the interface. | |
3836 */ | |
3837 Type *t = new TypeIdentifier(0, Id::Object); | |
3705 | 3838 |
3706 t = t->semantic(0, sc); | 3839 t = t->semantic(0, sc); |
3707 exp = new CastExp(loc, exp, t); | 3840 exp = new CastExp(loc, exp, t); |
3708 exp = exp->semantic(sc); | 3841 exp = exp->semantic(sc); |
3709 } | 3842 } |
3710 } | 3843 |
3844 #if 1 | |
3845 /* Rewrite as: | |
3846 * auto tmp = exp; | |
3847 * _d_monitorenter(tmp); | |
3848 * try { body } finally { _d_monitorexit(tmp); } | |
3849 */ | |
3850 Identifier *id = Lexer::uniqueId("__sync"); | |
3851 ExpInitializer *ie = new ExpInitializer(loc, exp); | |
3852 VarDeclaration *tmp = new VarDeclaration(loc, exp->type, id, ie); | |
3853 | |
3854 Statements *cs = new Statements(); | |
3855 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); | |
3856 | |
3857 #if IN_LLVM | |
3858 // LDC: Build args | |
3859 Arguments* args = new Arguments; | |
3860 args->push(new Argument(STCin, ClassDeclaration::object->type, NULL, NULL)); | |
3861 FuncDeclaration *fdenter = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorenter); | |
3862 #else | |
3863 FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::monitorenter); | |
3864 #endif | |
3865 Expression *e = new CallExp(loc, new VarExp(loc, fdenter), new VarExp(loc, tmp)); | |
3866 e->type = Type::tvoid; // do not run semantic on e | |
3867 cs->push(new ExpStatement(loc, e)); | |
3868 | |
3869 #if IN_LLVM | |
3870 FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorexit); | |
3871 #else | |
3872 FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorexit); | |
3873 #endif | |
3874 e = new CallExp(loc, new VarExp(loc, fdexit), new VarExp(loc, tmp)); | |
3875 e->type = Type::tvoid; // do not run semantic on e | |
3876 Statement *s = new ExpStatement(loc, e); | |
3877 s = new TryFinallyStatement(loc, body, s); | |
3878 cs->push(s); | |
3879 | |
3880 s = new CompoundStatement(loc, cs); | |
3881 return s->semantic(sc); | |
3882 #endif | |
3883 } | |
3884 #if 1 | |
3885 else | |
3886 { /* Generate our own critical section, then rewrite as: | |
3887 * __gshared byte[CriticalSection.sizeof] critsec; | |
3888 * _d_criticalenter(critsec.ptr); | |
3889 * try { body } finally { _d_criticalexit(critsec.ptr); } | |
3890 */ | |
3891 Identifier *id = Lexer::uniqueId("__critsec"); | |
3892 #if IN_LLVM | |
3893 Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + getTypePaddedSize(DtoMutexType()))); | |
3894 #elif IN_DMD | |
3895 Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + os_critsecsize())); | |
3896 #endif | |
3897 VarDeclaration *tmp = new VarDeclaration(loc, t, id, NULL); | |
3898 tmp->storage_class |= STCgshared | STCstatic; | |
3899 | |
3900 Statements *cs = new Statements(); | |
3901 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); | |
3902 | |
3903 #if IN_LLVM | |
3904 // LDC: Build args (based on the code from gen/tollvm.cpp:DtoMutexType() | |
3905 Arguments* args = new Arguments; | |
3906 StructDeclaration* dcs = new StructDeclaration(loc, id); | |
3907 if (global.params.os == OSWindows) | |
3908 { | |
3909 dcs->addField(dcs->scope, new VarDeclaration(loc, Type::tint32, id, NULL)); | |
3910 } | |
3911 else if (global.params.os == OSFreeBSD) | |
3912 { | |
3913 dcs->addField(dcs->scope, new VarDeclaration(loc, Type::tsize_t, id, NULL)); | |
3914 } | |
3915 else | |
3916 { | |
3917 // pthread_fastlock | |
3918 StructDeclaration* pfl = new StructDeclaration(loc, id); | |
3919 pfl->scope->linkage = LINKc; | |
3920 pfl->addField(pfl->scope, new VarDeclaration(loc, Type::tsize_t, id, NULL)); | |
3921 pfl->addField(pfl->scope, new VarDeclaration(loc, Type::tint32, id, NULL)); | |
3922 | |
3923 // pthread_mutex | |
3924 StructDeclaration* pm = new StructDeclaration(loc, id); | |
3925 pm->scope->linkage = LINKc; | |
3926 pm->addField(pm->scope, new VarDeclaration(loc, Type::tint32, id, NULL)); | |
3927 pm->addField(pm->scope, new VarDeclaration(loc, Type::tint32, id, NULL)); | |
3928 pm->addField(pm->scope, new VarDeclaration(loc, Type::tvoidptr, id, NULL)); | |
3929 pm->addField(pm->scope, new VarDeclaration(loc, Type::tint32, id, NULL)); | |
3930 pm->addField(pm->scope, new VarDeclaration(loc, pfl->type, id, NULL)); | |
3931 | |
3932 // D_CRITICAL_SECTION | |
3933 dcs->scope->linkage = LINKc; | |
3934 dcs->addField(dcs->scope, new VarDeclaration(loc, dcs->type->pointerTo(), id, NULL)); | |
3935 dcs->addField(dcs->scope, new VarDeclaration(loc, pm->type, id, NULL)); | |
3936 } | |
3937 args->push(new Argument(STCin, dcs->type->pointerTo(), NULL, NULL)); | |
3938 | |
3939 FuncDeclaration *fdenter = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalenter); | |
3940 #else | |
3941 FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalenter); | |
3942 #endif | |
3943 Expression *e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr); | |
3944 e = e->semantic(sc); | |
3945 e = new CallExp(loc, new VarExp(loc, fdenter), e); | |
3946 e->type = Type::tvoid; // do not run semantic on e | |
3947 cs->push(new ExpStatement(loc, e)); | |
3948 | |
3949 #if IN_LLVM | |
3950 FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalexit); | |
3951 #else | |
3952 FuncDeclaration *fdexit = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalexit); | |
3953 #endif | |
3954 e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr); | |
3955 e = e->semantic(sc); | |
3956 e = new CallExp(loc, new VarExp(loc, fdexit), e); | |
3957 e->type = Type::tvoid; // do not run semantic on e | |
3958 Statement *s = new ExpStatement(loc, e); | |
3959 s = new TryFinallyStatement(loc, body, s); | |
3960 cs->push(s); | |
3961 | |
3962 s = new CompoundStatement(loc, cs); | |
3963 return s->semantic(sc); | |
3964 } | |
3965 #endif | |
3711 if (body) | 3966 if (body) |
3712 { | 3967 { |
3713 Statement* oldScopeExit = sc->enclosingScopeExit; | 3968 Statement* oldScopeExit = sc->enclosingScopeExit; |
3714 sc->enclosingScopeExit = this; | 3969 sc->enclosingScopeExit = this; |
3715 body = body->semantic(sc); | 3970 body = body->semantic(sc); |