comparison dmd/statement.c @ 1587:def7a1d494fd

Merge DMD 1.051
author Christian Kamm <kamm incasoftware de>
date Fri, 06 Nov 2009 23:58:01 +0100
parents 05c235309d6f
children 207a8a438dea
comparison
equal deleted inserted replaced
1586:7f728c52e63c 1587:def7a1d494fd
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 extern int os_critsecsize();
33
32 /******************************** Statement ***************************/ 34 /******************************** Statement ***************************/
33 35
34 Statement::Statement(Loc loc) 36 Statement::Statement(Loc loc)
35 : loc(loc) 37 : loc(loc)
36 { 38 {
139 // TRUE if statement 'comes from' somewhere else, like a goto 141 // TRUE if statement 'comes from' somewhere else, like a goto
140 142
141 int Statement::comeFrom() 143 int Statement::comeFrom()
142 { 144 {
143 //printf("Statement::comeFrom()\n"); 145 //printf("Statement::comeFrom()\n");
146 return FALSE;
147 }
148
149 // Return TRUE if statement has no code in it
150 int Statement::isEmpty()
151 {
152 //printf("Statement::isEmpty()\n");
144 return FALSE; 153 return FALSE;
145 } 154 }
146 155
147 /**************************************** 156 /****************************************
148 * If this statement has code that needs to run in a finally clause 157 * If this statement has code that needs to run in a finally clause
152 * *sentry code executed upon entry to the scope 161 * *sentry code executed upon entry to the scope
153 * *sexception code executed upon exit from the scope via exception 162 * *sexception code executed upon exit from the scope via exception
154 * *sfinally code executed in finally block 163 * *sfinally code executed in finally block
155 */ 164 */
156 165
157 void Statement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally) 166 void Statement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
158 { 167 {
159 //printf("Statement::scopeCode()\n"); 168 //printf("Statement::scopeCode()\n");
160 //print(); 169 //print();
161 *sentry = NULL; 170 *sentry = NULL;
162 *sexception = NULL; 171 *sexception = NULL;
172 Statements *Statement::flatten(Scope *sc) 181 Statements *Statement::flatten(Scope *sc)
173 { 182 {
174 return NULL; 183 return NULL;
175 } 184 }
176 185
186
187 /******************************** PeelStatement ***************************/
188
189 PeelStatement::PeelStatement(Statement *s)
190 : Statement(s->loc)
191 {
192 this->s = s;
193 }
194
195 Statement *PeelStatement::semantic(Scope *sc)
196 {
197 /* "peel" off this wrapper, and don't run semantic()
198 * on the result.
199 */
200 return s;
201 }
177 202
178 /******************************** ExpStatement ***************************/ 203 /******************************** ExpStatement ***************************/
179 204
180 ExpStatement::ExpStatement(Loc loc, Expression *exp) 205 ExpStatement::ExpStatement(Loc loc, Expression *exp)
181 : Statement(loc) 206 : Statement(loc)
234 result |= BEthrow; 259 result |= BEthrow;
235 } 260 }
236 return result; 261 return result;
237 } 262 }
238 263
264 int ExpStatement::isEmpty()
265 {
266 return exp == NULL;
267 }
268
239 269
240 /******************************** CompileStatement ***************************/ 270 /******************************** CompileStatement ***************************/
241 271
242 CompileStatement::CompileStatement(Loc loc, Expression *exp) 272 CompileStatement::CompileStatement(Loc loc, Expression *exp)
243 : Statement(loc) 273 : Statement(loc)
313 { 343 {
314 DeclarationStatement *ds = new DeclarationStatement(loc, exp->syntaxCopy()); 344 DeclarationStatement *ds = new DeclarationStatement(loc, exp->syntaxCopy());
315 return ds; 345 return ds;
316 } 346 }
317 347
318 void DeclarationStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally) 348 void DeclarationStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
319 { 349 {
320 //printf("DeclarationStatement::scopeCode()\n"); 350 //printf("DeclarationStatement::scopeCode()\n");
321 //print(); 351 //print();
322 352
323 *sentry = NULL; 353 *sentry = NULL;
331 DeclarationExp *de = (DeclarationExp *)(exp); 361 DeclarationExp *de = (DeclarationExp *)(exp);
332 VarDeclaration *v = de->declaration->isVarDeclaration(); 362 VarDeclaration *v = de->declaration->isVarDeclaration();
333 if (v) 363 if (v)
334 { Expression *e; 364 { Expression *e;
335 365
336 e = v->callScopeDtor(); 366 e = v->callScopeDtor(sc);
337 if (e) 367 if (e)
338 { 368 {
339 //printf("dtor is: "); e->print(); 369 //printf("dtor is: "); e->print();
340 *sfinally = new ExpStatement(loc, e); 370 *sfinally = new ExpStatement(loc, e);
341 } 371 }
405 { 435 {
406 Statement *sentry; 436 Statement *sentry;
407 Statement *sexception; 437 Statement *sexception;
408 Statement *sfinally; 438 Statement *sfinally;
409 439
410 s->scopeCode(&sentry, &sexception, &sfinally); 440 s->scopeCode(sc, &sentry, &sexception, &sfinally);
411 if (sentry) 441 if (sentry)
412 { 442 {
413 sentry = sentry->semantic(sc); 443 sentry = sentry->semantic(sc);
414 statements->data[i] = sentry; 444 statements->data[i] = sentry;
415 } 445 }
553 { 583 {
554 //printf("result = x%x\n", result); 584 //printf("result = x%x\n", result);
555 //printf("%s\n", s->toChars()); 585 //printf("%s\n", s->toChars());
556 if (!(result & BEfallthru) && !s->comeFrom()) 586 if (!(result & BEfallthru) && !s->comeFrom())
557 { 587 {
558 s->warning("statement is not reachable"); 588 if (s->blockExit() != BEhalt && !s->isEmpty())
589 s->warning("statement is not reachable");
559 } 590 }
560 591 else
561 result &= ~BEfallthru; 592 {
562 result |= s->blockExit(); 593 result &= ~BEfallthru;
594 result |= s->blockExit();
595 }
563 } 596 }
564 } 597 }
565 return result; 598 return result;
566 } 599 }
567 600
576 continue; 609 continue;
577 610
578 comefrom |= s->comeFrom(); 611 comefrom |= s->comeFrom();
579 } 612 }
580 return comefrom; 613 return comefrom;
614 }
615
616 int CompoundStatement::isEmpty()
617 {
618 for (int i = 0; i < statements->dim; i++)
619 { Statement *s = (Statement *) statements->data[i];
620 if (s && !s->isEmpty())
621 return FALSE;
622 }
623 return TRUE;
581 } 624 }
582 625
583 626
584 /******************************** CompoundDeclarationStatement ***************************/ 627 /******************************** CompoundDeclarationStatement ***************************/
585 628
811 { 854 {
812 Statement *sentry; 855 Statement *sentry;
813 Statement *sexception; 856 Statement *sexception;
814 Statement *sfinally; 857 Statement *sfinally;
815 858
816 statement->scopeCode(&sentry, &sexception, &sfinally); 859 statement->scopeCode(sc, &sentry, &sexception, &sfinally);
817 if (sfinally) 860 if (sfinally)
818 { 861 {
819 //printf("adding sfinally\n"); 862 //printf("adding sfinally\n");
820 statement = new CompoundStatement(loc, statement, sfinally); 863 statement = new CompoundStatement(loc, statement, sfinally);
821 } 864 }
846 { 889 {
847 //printf("ScopeStatement::blockExit(%p)\n", statement); 890 //printf("ScopeStatement::blockExit(%p)\n", statement);
848 return statement ? statement->blockExit() : BEfallthru; 891 return statement ? statement->blockExit() : BEfallthru;
849 } 892 }
850 893
894
851 int ScopeStatement::comeFrom() 895 int ScopeStatement::comeFrom()
852 { 896 {
853 //printf("ScopeStatement::comeFrom()\n"); 897 //printf("ScopeStatement::comeFrom()\n");
854 return statement ? statement->comeFrom() : FALSE; 898 return statement ? statement->comeFrom() : FALSE;
855 } 899 }
856 900
901 int ScopeStatement::isEmpty()
902 {
903 //printf("ScopeStatement::isEmpty() %d\n", statement ? statement->isEmpty() : TRUE);
904 return statement ? statement->isEmpty() : TRUE;
905 }
906
857 void ScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 907 void ScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
858 { 908 {
859 buf->writeByte('{'); 909 buf->writeByte('{');
860 buf->writenl(); 910 buf->writenl();
861 911
882 } 932 }
883 933
884 934
885 Statement *WhileStatement::semantic(Scope *sc) 935 Statement *WhileStatement::semantic(Scope *sc)
886 { 936 {
887 #if 0 937 /* Rewrite as a for(;condition;) loop
888 if (condition->op == TOKmatch) 938 */
889 { 939
890 /* Rewrite while (condition) body as: 940 Statement *s = new ForStatement(loc, NULL, condition, NULL, body);
891 * if (condition) 941 s = s->semantic(sc);
892 * do 942 return s;
893 * body
894 * while ((_match = _match.opNext), _match);
895 */
896
897 Expression *ew = new IdentifierExp(0, Id::_match);
898 ew = new DotIdExp(0, ew, Id::next);
899 ew = new AssignExp(0, new IdentifierExp(0, Id::_match), ew);
900 ////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0));
901 Expression *ev = new IdentifierExp(0, Id::_match);
902 //ev = new CastExp(0, ev, Type::tvoidptr);
903 ew = new CommaExp(0, ew, ev);
904 Statement *sw = new DoStatement(loc, body, ew);
905 Statement *si = new IfStatement(loc, condition, sw, NULL);
906 return si->semantic(sc);
907 }
908 #endif
909
910 condition = condition->semantic(sc);
911 condition = resolveProperties(sc, condition);
912 condition = condition->optimize(WANTvalue);
913 condition = condition->checkToBoolean();
914
915 sc->noctor++;
916
917 Scope *scd = sc->push();
918 scd->sbreak = this;
919 scd->scontinue = this;
920 if (body)
921 body = body->semantic(scd);
922 scd->pop();
923
924 sc->noctor--;
925
926 return this;
927 } 943 }
928 944
929 int WhileStatement::hasBreak() 945 int WhileStatement::hasBreak()
930 { 946 {
931 return TRUE; 947 return TRUE;
936 return TRUE; 952 return TRUE;
937 } 953 }
938 954
939 int WhileStatement::usesEH() 955 int WhileStatement::usesEH()
940 { 956 {
957 assert(0);
941 return body ? body->usesEH() : 0; 958 return body ? body->usesEH() : 0;
942 } 959 }
943 960
944 int WhileStatement::blockExit() 961 int WhileStatement::blockExit()
945 { 962 {
963 assert(0);
946 //printf("WhileStatement::blockExit(%p)\n", this); 964 //printf("WhileStatement::blockExit(%p)\n", this);
947 965
948 int result = BEnone; 966 int result = BEnone;
949 if (condition->canThrow()) 967 if (condition->canThrow())
950 result |= BEthrow; 968 result |= BEthrow;
971 } 989 }
972 990
973 991
974 int WhileStatement::comeFrom() 992 int WhileStatement::comeFrom()
975 { 993 {
994 assert(0);
976 if (body) 995 if (body)
977 return body->comeFrom(); 996 return body->comeFrom();
978 return FALSE; 997 return FALSE;
979 } 998 }
980 999
1122 condition = condition->checkToBoolean(); 1141 condition = condition->checkToBoolean();
1123 } 1142 }
1124 if (increment) 1143 if (increment)
1125 { increment = increment->semantic(sc); 1144 { increment = increment->semantic(sc);
1126 increment = resolveProperties(sc, increment); 1145 increment = resolveProperties(sc, increment);
1146 increment = increment->optimize(0);
1127 } 1147 }
1128 1148
1129 sc->sbreak = this; 1149 sc->sbreak = this;
1130 sc->scontinue = this; 1150 sc->scontinue = this;
1131 if (body) 1151 if (body)
1134 1154
1135 sc->pop(); 1155 sc->pop();
1136 return this; 1156 return this;
1137 } 1157 }
1138 1158
1139 void ForStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally) 1159 void ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
1140 { 1160 {
1141 //printf("ForStatement::scopeCode()\n"); 1161 //printf("ForStatement::scopeCode()\n");
1142 //print(); 1162 //print();
1143 if (init) 1163 if (init)
1144 init->scopeCode(sentry, sexception, sfinally); 1164 init->scopeCode(sc, sentry, sexception, sfinally);
1145 else 1165 else
1146 Statement::scopeCode(sentry, sexception, sfinally); 1166 Statement::scopeCode(sc, sentry, sexception, sfinally);
1147 } 1167 }
1148 1168
1149 int ForStatement::hasBreak() 1169 int ForStatement::hasBreak()
1150 { 1170 {
1151 //printf("ForStatement::hasBreak()\n"); 1171 //printf("ForStatement::hasBreak()\n");
1171 return result; 1191 return result;
1172 } 1192 }
1173 if (condition) 1193 if (condition)
1174 { if (condition->canThrow()) 1194 { if (condition->canThrow())
1175 result |= BEthrow; 1195 result |= BEthrow;
1196 if (condition->isBool(TRUE))
1197 result &= ~BEfallthru;
1198 else if (condition->isBool(FALSE))
1199 return result;
1176 } 1200 }
1177 else 1201 else
1178 result &= ~BEfallthru; // the body must do the exiting 1202 result &= ~BEfallthru; // the body must do the exiting
1179 if (body) 1203 if (body)
1180 { int r = body->blockExit(); 1204 { int r = body->blockExit();
1350 // Declare value 1374 // Declare value
1351 if (arg->storageClass & (STCout | STCref | STClazy)) 1375 if (arg->storageClass & (STCout | STCref | STClazy))
1352 error("no storage class for value %s", arg->ident->toChars()); 1376 error("no storage class for value %s", arg->ident->toChars());
1353 Dsymbol *var; 1377 Dsymbol *var;
1354 if (te) 1378 if (te)
1355 { 1379 { Type *tb = e->type->toBasetype();
1356 if (e->type->toBasetype()->ty == Tfunction && 1380 if ((tb->ty == Tfunction || tb->ty == Tsarray) && e->op == TOKvar)
1357 e->op == TOKvar)
1358 { VarExp *ve = (VarExp *)e; 1381 { VarExp *ve = (VarExp *)e;
1359 var = new AliasDeclaration(loc, arg->ident, ve->var); 1382 var = new AliasDeclaration(loc, arg->ident, ve->var);
1360 } 1383 }
1361 else 1384 else
1362 { 1385 {
1437 } 1460 }
1438 1461
1439 for (size_t i = 0; i < dim; i++) 1462 for (size_t i = 0; i < dim; i++)
1440 { // Declare args 1463 { // Declare args
1441 Argument *arg = (Argument *)arguments->data[i]; 1464 Argument *arg = (Argument *)arguments->data[i];
1465 Type *argtype = arg->type->semantic(loc, sc);
1442 VarDeclaration *var; 1466 VarDeclaration *var;
1443 1467
1444 var = new VarDeclaration(loc, arg->type, arg->ident, NULL); 1468 var = new VarDeclaration(loc, argtype, arg->ident, NULL);
1445 var->storage_class |= STCforeach; 1469 var->storage_class |= STCforeach;
1446 var->storage_class |= arg->storageClass & (STCin | STCout | STCref); 1470 var->storage_class |= arg->storageClass & (STCin | STCout | STCref);
1447 #if 1 1471
1448 DeclarationExp *de = new DeclarationExp(loc, var);
1449 de->semantic(sc);
1450 #else
1451 var->semantic(sc);
1452 if (!sc->insert(var))
1453 error("%s already defined", var->ident->toChars());
1454 #endif
1455 if (dim == 2 && i == 0) 1472 if (dim == 2 && i == 0)
1456 key = var; 1473 key = var;
1457 else 1474 else
1458 value = var; 1475 value = var;
1476 #if 0
1477 DeclarationExp *de = new DeclarationExp(loc, var);
1478 de->semantic(sc);
1479 #endif
1459 } 1480 }
1460 1481
1461 sc->sbreak = this; 1482 #if 1
1462 sc->scontinue = this; 1483 {
1463 body = body->semantic(sc); 1484 /* Convert to a ForStatement
1464 1485 * foreach (key, value; a) body =>
1486 * for (T[] tmp = a[], size_t key; key < tmp.length; ++key)
1487 * { T value = tmp[k]; body }
1488 *
1489 * foreach_reverse (key, value; a) body =>
1490 * for (T[] tmp = a[], size_t key = tmp.length; key--; )
1491 * { T value = tmp[k]; body }
1492 */
1493 Identifier *id = Lexer::uniqueId("__aggr");
1494 ExpInitializer *ie = new ExpInitializer(loc, new SliceExp(loc, aggr, NULL, NULL));
1495 VarDeclaration *tmp = new VarDeclaration(loc, aggr->type->nextOf()->arrayOf(), id, ie);
1496
1497 Expression *tmp_length = new DotIdExp(loc, new VarExp(loc, tmp), Id::length);
1498
1499 if (!key)
1500 {
1501 Identifier *id = Lexer::uniqueId("__key");
1502 key = new VarDeclaration(loc, Type::tsize_t, id, NULL);
1503 }
1504 if (op == TOKforeach_reverse)
1505 key->init = new ExpInitializer(loc, tmp_length);
1506 else
1507 key->init = new ExpInitializer(loc, new IntegerExp(0));
1508
1509 Statements *cs = new Statements();
1510 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
1511 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key)));
1512 Statement *forinit = new CompoundDeclarationStatement(loc, cs);
1513
1514 Expression *cond;
1515 if (op == TOKforeach_reverse)
1516 // key--
1517 cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key));
1518 else
1519 // key < tmp.length
1520 cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), tmp_length);
1521
1522 Expression *increment = NULL;
1523 if (op == TOKforeach)
1524 // key += 1
1525 increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1));
1526
1527 // T value = tmp[key];
1528 value->init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, key)));
1529 Statement *ds = new DeclarationStatement(loc, new DeclarationExp(loc, value));
1530
1531 body = new CompoundStatement(loc, ds, body);
1532
1533 ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body);
1534 s = fs->semantic(sc);
1535 break;
1536 }
1537 #else
1465 if (!value->type->equals(tab->next)) 1538 if (!value->type->equals(tab->next))
1466 { 1539 {
1467 if (aggr->op == TOKstring) 1540 if (aggr->op == TOKstring)
1468 aggr = aggr->implicitCastTo(sc, value->type->arrayOf()); 1541 aggr = aggr->implicitCastTo(sc, value->type->arrayOf());
1469 else 1542 else
1470 error("foreach: %s is not an array of %s", 1543 error("foreach: %s is not an array of %s",
1471 tab->toChars(), value->type->toChars()); 1544 tab->toChars(), value->type->toChars());
1472 } 1545 }
1473 1546
1474 if (key && key->type->ty != Tint32 && key->type->ty != Tuns32) 1547 if (key)
1475 { 1548 {
1476 if (global.params.is64bit) 1549 if (key->type->ty != Tint32 && key->type->ty != Tuns32)
1477 { 1550 {
1478 if (key->type->ty != Tint64 && key->type->ty != Tuns64) 1551 if (global.params.is64bit)
1479 error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars()); 1552 {
1553 if (key->type->ty != Tint64 && key->type->ty != Tuns64)
1554 error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars());
1555 }
1556 else
1557 error("foreach: key type must be int or uint, not %s", key->type->toChars());
1480 } 1558 }
1481 else 1559
1482 error("foreach: key type must be int or uint, not %s", key->type->toChars()); 1560 if (key->storage_class & (STCout | STCref))
1561 error("foreach: key cannot be out or ref");
1483 } 1562 }
1484 1563
1485 if (key && key->storage_class & (STCout | STCref)) 1564 sc->sbreak = this;
1486 error("foreach: key cannot be out or ref"); 1565 sc->scontinue = this;
1566 body = body->semantic(sc);
1487 break; 1567 break;
1568 #endif
1488 1569
1489 case Taarray: 1570 case Taarray:
1490 taa = (TypeAArray *)tab; 1571 taa = (TypeAArray *)tab;
1491 if (dim < 1 || dim > 2) 1572 if (dim < 1 || dim > 2)
1492 { 1573 {
1502 case Tclass: 1583 case Tclass:
1503 case Tstruct: 1584 case Tstruct:
1504 #if DMDV2 1585 #if DMDV2
1505 { /* Look for range iteration, i.e. the properties 1586 { /* Look for range iteration, i.e. the properties
1506 * .empty, .next, .retreat, .head and .rear 1587 * .empty, .next, .retreat, .head and .rear
1507 * foreach (e; range) { ... } 1588 * foreach (e; aggr) { ... }
1508 * translates to: 1589 * translates to:
1509 * for (auto __r = range; !__r.empty; __r.next) 1590 * for (auto __r = aggr[]; !__r.empty; __r.next)
1510 * { auto e = __r.head; 1591 * { auto e = __r.head;
1511 * ... 1592 * ...
1512 * } 1593 * }
1513 */ 1594 */
1514 if (dim != 1) // only one argument allowed with ranges 1595 if (dim != 1) // only one argument allowed with ranges
1521 if (op == TOKforeach) 1602 if (op == TOKforeach)
1522 { idhead = Id::Fhead; 1603 { idhead = Id::Fhead;
1523 idnext = Id::Fnext; 1604 idnext = Id::Fnext;
1524 } 1605 }
1525 else 1606 else
1526 { idhead = Id::Frear; 1607 { idhead = Id::Ftoe;
1527 idnext = Id::Fretreat; 1608 idnext = Id::Fretreat;
1528 } 1609 }
1529 Dsymbol *shead = search_function(ad, idhead); 1610 Dsymbol *shead = search_function(ad, idhead);
1530 if (!shead) 1611 if (!shead)
1531 goto Lapply; 1612 goto Lapply;
1532 1613
1533 /* Generate a temporary __r and initialize it with the aggregate. 1614 /* Generate a temporary __r and initialize it with the aggregate.
1534 */ 1615 */
1535 Identifier *id = Identifier::generateId("__r"); 1616 Identifier *id = Identifier::generateId("__r");
1536 VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, aggr)); 1617 Expression *rinit = new SliceExp(loc, aggr, NULL, NULL);
1537 r->semantic(sc); 1618 rinit = rinit->trySemantic(sc);
1619 if (!rinit) // if application of [] failed
1620 rinit = aggr;
1621 VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, rinit));
1622 // r->semantic(sc);
1623 //printf("r: %s, init: %s\n", r->toChars(), r->init->toChars());
1538 Statement *init = new DeclarationStatement(loc, r); 1624 Statement *init = new DeclarationStatement(loc, r);
1625 //printf("init: %s\n", init->toChars());
1539 1626
1540 // !__r.empty 1627 // !__r.empty
1541 Expression *e = new VarExp(loc, r); 1628 Expression *e = new VarExp(loc, r);
1542 e = new DotIdExp(loc, e, Id::Fempty); 1629 e = new DotIdExp(loc, e, Id::Fempty);
1543 Expression *condition = new NotExp(loc, e); 1630 Expression *condition = new NotExp(loc, e);
1549 /* Declaration statement for e: 1636 /* Declaration statement for e:
1550 * auto e = __r.idhead; 1637 * auto e = __r.idhead;
1551 */ 1638 */
1552 e = new VarExp(loc, r); 1639 e = new VarExp(loc, r);
1553 Expression *einit = new DotIdExp(loc, e, idhead); 1640 Expression *einit = new DotIdExp(loc, e, idhead);
1554 einit = einit->semantic(sc); 1641 // einit = einit->semantic(sc);
1555 Argument *arg = (Argument *)arguments->data[0]; 1642 Argument *arg = (Argument *)arguments->data[0];
1556 VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit)); 1643 VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit));
1557 ve->storage_class |= STCforeach; 1644 ve->storage_class |= STCforeach;
1558 ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant); 1645 ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR);
1559 1646
1560 DeclarationExp *de = new DeclarationExp(loc, ve); 1647 DeclarationExp *de = new DeclarationExp(loc, ve);
1561 1648
1562 Statement *body = new CompoundStatement(loc, 1649 Statement *body = new CompoundStatement(loc,
1563 new DeclarationStatement(loc, de), this->body); 1650 new DeclarationStatement(loc, de), this->body);
1564 1651
1565 s = new ForStatement(loc, init, condition, increment, body); 1652 s = new ForStatement(loc, init, condition, increment, body);
1653 #if 0
1654 printf("init: %s\n", init->toChars());
1655 printf("condition: %s\n", condition->toChars());
1656 printf("increment: %s\n", increment->toChars());
1657 printf("body: %s\n", body->toChars());
1658 #endif
1566 s = s->semantic(sc); 1659 s = s->semantic(sc);
1567 break; 1660 break;
1568 } 1661 }
1569 #endif 1662 #endif
1570 case Tdelegate: 1663 case Tdelegate:
1835 break; 1928 break;
1836 } 1929 }
1837 1930
1838 default: 1931 default:
1839 error("foreach: %s is not an aggregate type", aggr->type->toChars()); 1932 error("foreach: %s is not an aggregate type", aggr->type->toChars());
1933 s = NULL; // error recovery
1840 break; 1934 break;
1841 } 1935 }
1842 sc->noctor--; 1936 sc->noctor--;
1843 sc->pop(); 1937 sc->pop();
1844 return s; 1938 return s;
1869 { 1963 {
1870 result |= body->blockExit() & ~(BEbreak | BEcontinue); 1964 result |= body->blockExit() & ~(BEbreak | BEcontinue);
1871 } 1965 }
1872 return result; 1966 return result;
1873 } 1967 }
1968
1874 1969
1875 int ForeachStatement::comeFrom() 1970 int ForeachStatement::comeFrom()
1876 { 1971 {
1877 if (body) 1972 if (body)
1878 return body->comeFrom(); 1973 return body->comeFrom();
1906 body->toCBuffer(buf, hgs); 2001 body->toCBuffer(buf, hgs);
1907 buf->writebyte('}'); 2002 buf->writebyte('}');
1908 buf->writenl(); 2003 buf->writenl();
1909 } 2004 }
1910 2005
2006 /**************************** ForeachRangeStatement ***************************/
2007
2008 #if DMDV2
2009
2010 ForeachRangeStatement::ForeachRangeStatement(Loc loc, enum TOK op, Argument *arg,
2011 Expression *lwr, Expression *upr, Statement *body)
2012 : Statement(loc)
2013 {
2014 this->op = op;
2015 this->arg = arg;
2016 this->lwr = lwr;
2017 this->upr = upr;
2018 this->body = body;
2019
2020 this->key = NULL;
2021 }
2022
2023 Statement *ForeachRangeStatement::syntaxCopy()
2024 {
2025 ForeachRangeStatement *s = new ForeachRangeStatement(loc, op,
2026 arg->syntaxCopy(),
2027 lwr->syntaxCopy(),
2028 upr->syntaxCopy(),
2029 body ? body->syntaxCopy() : NULL);
2030 return s;
2031 }
2032
2033 Statement *ForeachRangeStatement::semantic(Scope *sc)
2034 {
2035 //printf("ForeachRangeStatement::semantic() %p\n", this);
2036 ScopeDsymbol *sym;
2037 Statement *s = this;
2038
2039 lwr = lwr->semantic(sc);
2040 lwr = resolveProperties(sc, lwr);
2041 lwr = lwr->optimize(WANTvalue);
2042 if (!lwr->type)
2043 {
2044 error("invalid range lower bound %s", lwr->toChars());
2045 return this;
2046 }
2047
2048 upr = upr->semantic(sc);
2049 upr = resolveProperties(sc, upr);
2050 upr = upr->optimize(WANTvalue);
2051 if (!upr->type)
2052 {
2053 error("invalid range upper bound %s", upr->toChars());
2054 return this;
2055 }
2056
2057 if (arg->type)
2058 {
2059 arg->type = arg->type->semantic(loc, sc);
2060 lwr = lwr->implicitCastTo(sc, arg->type);
2061 upr = upr->implicitCastTo(sc, arg->type);
2062 }
2063 else
2064 {
2065 /* Must infer types from lwr and upr
2066 */
2067 AddExp ea(loc, lwr, upr);
2068 ea.typeCombine(sc);
2069 arg->type = ea.type->mutableOf();
2070 lwr = ea.e1;
2071 upr = ea.e2;
2072 }
2073 #if 1
2074 /* Convert to a for loop:
2075 * foreach (key; lwr .. upr) =>
2076 * for (auto key = lwr, auto tmp = upr; key < tmp; ++key)
2077 *
2078 * foreach_reverse (key; lwr .. upr) =>
2079 * for (auto tmp = lwr, auto key = upr; key-- > tmp;)
2080 */
2081
2082 ExpInitializer *ie = new ExpInitializer(loc, (op == TOKforeach) ? lwr : upr);
2083 key = new VarDeclaration(loc, arg->type, arg->ident, ie);
2084
2085 Identifier *id = Lexer::uniqueId("__limit");
2086 ie = new ExpInitializer(loc, (op == TOKforeach) ? upr : lwr);
2087 VarDeclaration *tmp = new VarDeclaration(loc, arg->type, id, ie);
2088
2089 Statements *cs = new Statements();
2090 // Keep order of evaluation as lwr, then upr
2091 if (op == TOKforeach)
2092 {
2093 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key)));
2094 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
2095 }
2096 else
2097 {
2098 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
2099 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key)));
2100 }
2101 Statement *forinit = new CompoundDeclarationStatement(loc, cs);
2102
2103 Expression *cond;
2104 if (op == TOKforeach_reverse)
2105 { // key-- > tmp
2106 cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key));
2107 cond = new CmpExp(TOKgt, loc, cond, new VarExp(loc, tmp));
2108 }
2109 else
2110 // key < tmp
2111 cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), new VarExp(loc, tmp));
2112
2113 Expression *increment = NULL;
2114 if (op == TOKforeach)
2115 // key += 1
2116 increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1));
2117
2118 ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body);
2119 s = fs->semantic(sc);
2120 return s;
2121 #else
2122 if (!arg->type->isscalar())
2123 error("%s is not a scalar type", arg->type->toChars());
2124
2125 sym = new ScopeDsymbol();
2126 sym->parent = sc->scopesym;
2127 sc = sc->push(sym);
2128
2129 sc->noctor++;
2130
2131 key = new VarDeclaration(loc, arg->type, arg->ident, NULL);
2132 DeclarationExp *de = new DeclarationExp(loc, key);
2133 de->semantic(sc);
2134
2135 if (key->storage_class)
2136 error("foreach range: key cannot have storage class");
2137
2138 sc->sbreak = this;
2139 sc->scontinue = this;
2140 body = body->semantic(sc);
2141
2142 sc->noctor--;
2143 sc->pop();
2144 return s;
2145 #endif
2146 }
2147
2148 int ForeachRangeStatement::hasBreak()
2149 {
2150 return TRUE;
2151 }
2152
2153 int ForeachRangeStatement::hasContinue()
2154 {
2155 return TRUE;
2156 }
2157
2158 int ForeachRangeStatement::usesEH()
2159 {
2160 assert(0);
2161 return body->usesEH();
2162 }
2163
2164 int ForeachRangeStatement::blockExit()
2165 {
2166 assert(0);
2167 int result = BEfallthru;
2168
2169 if (lwr && lwr->canThrow())
2170 result |= BEthrow;
2171 else if (upr && upr->canThrow())
2172 result |= BEthrow;
2173
2174 if (body)
2175 {
2176 result |= body->blockExit() & ~(BEbreak | BEcontinue);
2177 }
2178 return result;
2179 }
2180
2181
2182 int ForeachRangeStatement::comeFrom()
2183 {
2184 assert(0);
2185 if (body)
2186 return body->comeFrom();
2187 return FALSE;
2188 }
2189
2190 void ForeachRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2191 {
2192 buf->writestring(Token::toChars(op));
2193 buf->writestring(" (");
2194
2195 if (arg->type)
2196 arg->type->toCBuffer(buf, arg->ident, hgs);
2197 else
2198 buf->writestring(arg->ident->toChars());
2199
2200 buf->writestring("; ");
2201 lwr->toCBuffer(buf, hgs);
2202 buf->writestring(" .. ");
2203 upr->toCBuffer(buf, hgs);
2204 buf->writebyte(')');
2205 buf->writenl();
2206 buf->writebyte('{');
2207 buf->writenl();
2208 if (body)
2209 body->toCBuffer(buf, hgs);
2210 buf->writebyte('}');
2211 buf->writenl();
2212 }
2213
2214 #endif
2215
1911 /******************************** IfStatement ***************************/ 2216 /******************************** IfStatement ***************************/
1912 2217
1913 IfStatement::IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody) 2218 IfStatement::IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody)
1914 : Statement(loc) 2219 : Statement(loc)
1915 { 2220 {
2026 result |= BEfallthru; 2331 result |= BEfallthru;
2027 } 2332 }
2028 //printf("IfStatement::blockExit(%p) = x%x\n", this, result); 2333 //printf("IfStatement::blockExit(%p) = x%x\n", this, result);
2029 return result; 2334 return result;
2030 } 2335 }
2336
2031 2337
2032 void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2338 void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2033 { 2339 {
2034 buf->writestring("if ("); 2340 buf->writestring("if (");
2035 if (arg) 2341 if (arg)
2179 e = e->semantic(sc); 2485 e = e->semantic(sc);
2180 e = e->optimize(WANTvalue | WANTinterpret); 2486 e = e->optimize(WANTvalue | WANTinterpret);
2181 if (e->op == TOKstring) 2487 if (e->op == TOKstring)
2182 { 2488 {
2183 StringExp *se = (StringExp *)e; 2489 StringExp *se = (StringExp *)e;
2184 fprintf(stdmsg, "%.*s", (int)se->len, (char*)se->string); 2490 fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string);
2185 } 2491 }
2186 else 2492 else
2187 error("string expected for message, not '%s'", e->toChars()); 2493 fprintf(stdmsg, e->toChars());
2188 } 2494 }
2189 fprintf(stdmsg, "\n"); 2495 fprintf(stdmsg, "\n");
2190 } 2496 }
2191 } 2497 }
2192 else if (ident == Id::lib) 2498 else if (ident == Id::lib)
2223 // LDC 2529 // LDC
2224 else if (ident == Id::allow_inline) 2530 else if (ident == Id::allow_inline)
2225 { 2531 {
2226 sc->func->allowInlining = true; 2532 sc->func->allowInlining = true;
2227 } 2533 }
2228 2534 #if DMDV2
2535 else if (ident == Id::startaddress)
2536 {
2537 if (!args || args->dim != 1)
2538 error("function name expected for start address");
2539 else
2540 {
2541 Expression *e = (Expression *)args->data[0];
2542 e = e->semantic(sc);
2543 e = e->optimize(WANTvalue | WANTinterpret);
2544 args->data[0] = (void *)e;
2545 Dsymbol *sa = getDsymbol(e);
2546 if (!sa || !sa->isFuncDeclaration())
2547 error("function name expected for start address, not '%s'", e->toChars());
2548 if (body)
2549 {
2550 body = body->semantic(sc);
2551 }
2552 return this;
2553 }
2554 }
2555 #endif
2229 else 2556 else
2230 error("unrecognized pragma(%s)", ident->toChars()); 2557 error("unrecognized pragma(%s)", ident->toChars());
2231 2558
2232 if (body) 2559 if (body)
2233 { 2560 {
2251 result |= body->blockExit(); 2578 result |= body->blockExit();
2252 #endif 2579 #endif
2253 return result; 2580 return result;
2254 } 2581 }
2255 2582
2583
2256 void PragmaStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2584 void PragmaStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2257 { 2585 {
2258 buf->writestring("pragma ("); 2586 buf->writestring("pragma (");
2259 buf->writestring(ident->toChars()); 2587 buf->writestring(ident->toChars());
2260 if (args && args->dim) 2588 if (args && args->dim)
2298 2626
2299 Statement *StaticAssertStatement::semantic(Scope *sc) 2627 Statement *StaticAssertStatement::semantic(Scope *sc)
2300 { 2628 {
2301 sa->semantic2(sc); 2629 sa->semantic2(sc);
2302 return NULL; 2630 return NULL;
2631 }
2632
2633 int StaticAssertStatement::blockExit()
2634 {
2635 return BEfallthru;
2303 } 2636 }
2304 2637
2305 void StaticAssertStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2638 void StaticAssertStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2306 { 2639 {
2307 sa->toCBuffer(buf, hgs); 2640 sa->toCBuffer(buf, hgs);
2423 a->push(sc->sw->sdefault); 2756 a->push(sc->sw->sdefault);
2424 cs = new CompoundStatement(loc, a); 2757 cs = new CompoundStatement(loc, a);
2425 body = cs; 2758 body = cs;
2426 } 2759 }
2427 2760
2761 #if DMDV2
2762 if (isFinal)
2763 { Type *t = condition->type;
2764 while (t->ty == Ttypedef)
2765 { // Don't use toBasetype() because that will skip past enums
2766 t = ((TypeTypedef *)t)->sym->basetype;
2767 }
2768 if (condition->type->ty == Tenum)
2769 { TypeEnum *te = (TypeEnum *)condition->type;
2770 EnumDeclaration *ed = te->toDsymbol(sc)->isEnumDeclaration();
2771 assert(ed);
2772 size_t dim = ed->members->dim;
2773 for (size_t i = 0; i < dim; i++)
2774 {
2775 EnumMember *em = ((Dsymbol *)ed->members->data[i])->isEnumMember();
2776 if (em)
2777 {
2778 for (size_t j = 0; j < cases->dim; j++)
2779 { CaseStatement *cs = (CaseStatement *)cases->data[j];
2780 if (cs->exp->equals(em->value))
2781 goto L1;
2782 }
2783 error("enum member %s not represented in final switch", em->toChars());
2784 }
2785 L1:
2786 ;
2787 }
2788 }
2789 }
2790 #endif
2791
2428 sc->pop(); 2792 sc->pop();
2429 return this; 2793 return this;
2430 } 2794 }
2431 2795
2432 int SwitchStatement::hasBreak() 2796 int SwitchStatement::hasBreak()
2454 else 2818 else
2455 result |= BEfallthru; 2819 result |= BEfallthru;
2456 2820
2457 return result; 2821 return result;
2458 } 2822 }
2823
2459 2824
2460 void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2825 void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2461 { 2826 {
2462 buf->writestring("switch ("); 2827 buf->writestring("switch (");
2463 condition->toCBuffer(buf, hgs); 2828 condition->toCBuffer(buf, hgs);
2569 int CaseStatement::blockExit() 2934 int CaseStatement::blockExit()
2570 { 2935 {
2571 return statement->blockExit(); 2936 return statement->blockExit();
2572 } 2937 }
2573 2938
2939
2574 int CaseStatement::comeFrom() 2940 int CaseStatement::comeFrom()
2575 { 2941 {
2576 return TRUE; 2942 return TRUE;
2577 } 2943 }
2578 2944
2582 exp->toCBuffer(buf, hgs); 2948 exp->toCBuffer(buf, hgs);
2583 buf->writebyte(':'); 2949 buf->writebyte(':');
2584 buf->writenl(); 2950 buf->writenl();
2585 statement->toCBuffer(buf, hgs); 2951 statement->toCBuffer(buf, hgs);
2586 } 2952 }
2953
2954 /******************************** CaseRangeStatement ***************************/
2955
2956 #if DMDV2
2957
2958 CaseRangeStatement::CaseRangeStatement(Loc loc, Expression *first,
2959 Expression *last, Statement *s)
2960 : Statement(loc)
2961 {
2962 this->first = first;
2963 this->last = last;
2964 this->statement = s;
2965 }
2966
2967 Statement *CaseRangeStatement::syntaxCopy()
2968 {
2969 CaseRangeStatement *s = new CaseRangeStatement(loc,
2970 first->syntaxCopy(), last->syntaxCopy(), statement->syntaxCopy());
2971 return s;
2972 }
2973
2974 Statement *CaseRangeStatement::semantic(Scope *sc)
2975 { SwitchStatement *sw = sc->sw;
2976
2977 //printf("CaseRangeStatement::semantic() %s\n", toChars());
2978 if (sw->isFinal)
2979 error("case ranges not allowed in final switch");
2980
2981 first = first->semantic(sc);
2982 first = first->implicitCastTo(sc, sw->condition->type);
2983 first = first->optimize(WANTvalue | WANTinterpret);
2984 dinteger_t fval = first->toInteger();
2985
2986 last = last->semantic(sc);
2987 last = last->implicitCastTo(sc, sw->condition->type);
2988 last = last->optimize(WANTvalue | WANTinterpret);
2989 dinteger_t lval = last->toInteger();
2990
2991 if (lval - fval > 256)
2992 { error("more than 256 cases in case range");
2993 lval = fval + 256;
2994 }
2995
2996 /* This works by replacing the CaseRange with an array of Case's.
2997 *
2998 * case a: .. case b: s;
2999 * =>
3000 * case a:
3001 * [...]
3002 * case b:
3003 * s;
3004 */
3005
3006 Statements *statements = new Statements();
3007 for (dinteger_t i = fval; i <= lval; i++)
3008 {
3009 Statement *s = statement;
3010 if (i != lval)
3011 s = new ExpStatement(loc, NULL);
3012 Expression *e = new IntegerExp(loc, i, first->type);
3013 Statement *cs = new CaseStatement(loc, e, s);
3014 statements->push(cs);
3015 }
3016 Statement *s = new CompoundStatement(loc, statements);
3017 s = s->semantic(sc);
3018 return s;
3019 }
3020
3021 void CaseRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3022 {
3023 buf->writestring("case ");
3024 first->toCBuffer(buf, hgs);
3025 buf->writestring(": .. case ");
3026 last->toCBuffer(buf, hgs);
3027 buf->writenl();
3028 statement->toCBuffer(buf, hgs);
3029 }
3030
3031 #endif
2587 3032
2588 /******************************** DefaultStatement ***************************/ 3033 /******************************** DefaultStatement ***************************/
2589 3034
2590 DefaultStatement::DefaultStatement(Loc loc, Statement *s) 3035 DefaultStatement::DefaultStatement(Loc loc, Statement *s)
2591 : Statement(loc) 3036 : Statement(loc)
2638 int DefaultStatement::blockExit() 3083 int DefaultStatement::blockExit()
2639 { 3084 {
2640 return statement->blockExit(); 3085 return statement->blockExit();
2641 } 3086 }
2642 3087
3088
2643 int DefaultStatement::comeFrom() 3089 int DefaultStatement::comeFrom()
2644 { 3090 {
2645 return TRUE; 3091 return TRUE;
2646 } 3092 }
2647 3093
2675 3121
2676 int GotoDefaultStatement::blockExit() 3122 int GotoDefaultStatement::blockExit()
2677 { 3123 {
2678 return BEgoto; 3124 return BEgoto;
2679 } 3125 }
3126
2680 3127
2681 void GotoDefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3128 void GotoDefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2682 { 3129 {
2683 buf->writestring("goto default;\n"); 3130 buf->writestring("goto default;\n");
2684 } 3131 }
2723 int GotoCaseStatement::blockExit() 3170 int GotoCaseStatement::blockExit()
2724 { 3171 {
2725 return BEgoto; 3172 return BEgoto;
2726 } 3173 }
2727 3174
3175
2728 void GotoCaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3176 void GotoCaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2729 { 3177 {
2730 buf->writestring("goto case"); 3178 buf->writestring("goto case");
2731 if (exp) 3179 if (exp)
2732 { buf->writebyte(' '); 3180 { buf->writebyte(' ');
2745 3193
2746 int SwitchErrorStatement::blockExit() 3194 int SwitchErrorStatement::blockExit()
2747 { 3195 {
2748 return BEthrow; 3196 return BEthrow;
2749 } 3197 }
3198
2750 3199
2751 void SwitchErrorStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3200 void SwitchErrorStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2752 { 3201 {
2753 buf->writestring("SwitchErrorStatement::toCBuffer()"); 3202 buf->writestring("SwitchErrorStatement::toCBuffer()");
2754 buf->writenl(); 3203 buf->writenl();
2839 3288
2840 if (!v || v->isOut() || v->isRef()) 3289 if (!v || v->isOut() || v->isRef())
2841 fd->nrvo_can = 0; 3290 fd->nrvo_can = 0;
2842 else if (fd->nrvo_var == NULL) 3291 else if (fd->nrvo_var == NULL)
2843 { if (!v->isDataseg() && !v->isParameter() && v->toParent2() == fd) 3292 { if (!v->isDataseg() && !v->isParameter() && v->toParent2() == fd)
3293 { //printf("Setting nrvo to %s\n", v->toChars());
2844 fd->nrvo_var = v; 3294 fd->nrvo_var = v;
3295 }
2845 else 3296 else
2846 fd->nrvo_can = 0; 3297 fd->nrvo_can = 0;
2847 } 3298 }
2848 else if (fd->nrvo_var != v) 3299 else if (fd->nrvo_var != v)
2849 fd->nrvo_can = 0; 3300 fd->nrvo_can = 0;
2942 s = new ReturnStatement(0, new VarExp(0, fd->vresult)); 3393 s = new ReturnStatement(0, new VarExp(0, fd->vresult));
2943 sc->fes->cases.push(s); 3394 sc->fes->cases.push(s);
2944 3395
2945 // Construct: { vresult = exp; return cases.dim + 1; } 3396 // Construct: { vresult = exp; return cases.dim + 1; }
2946 exp = new AssignExp(loc, new VarExp(0, fd->vresult), exp); 3397 exp = new AssignExp(loc, new VarExp(0, fd->vresult), exp);
3398 exp->op = TOKconstruct;
2947 exp = exp->semantic(sc); 3399 exp = exp->semantic(sc);
2948 Statement *s1 = new ExpStatement(loc, exp); 3400 Statement *s1 = new ExpStatement(loc, exp);
2949 Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); 3401 Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
2950 s = new CompoundStatement(loc, s1, s2); 3402 s = new CompoundStatement(loc, s1, s2);
2951 } 3403 }
2958 { 3410 {
2959 assert(fd->vresult); 3411 assert(fd->vresult);
2960 VarExp *v = new VarExp(0, fd->vresult); 3412 VarExp *v = new VarExp(0, fd->vresult);
2961 3413
2962 exp = new AssignExp(loc, v, exp); 3414 exp = new AssignExp(loc, v, exp);
3415 exp->op = TOKconstruct;
2963 exp = exp->semantic(sc); 3416 exp = exp->semantic(sc);
2964 } 3417 }
2965 //exp->dump(0); 3418 //exp->dump(0);
2966 //exp->print(); 3419 //exp->print();
2967 exp->checkEscape(); 3420 exp->checkEscape();
2994 return new CompoundStatement(loc, s, gs); 3447 return new CompoundStatement(loc, s, gs);
2995 } 3448 }
2996 return gs; 3449 return gs;
2997 } 3450 }
2998 3451
2999 if (exp && tbret->ty == Tvoid && !fd->isMain()) 3452 if (exp && tbret->ty == Tvoid && !implicit0)
3000 { 3453 {
3001 /* Replace: 3454 /* Replace:
3002 * return exp; 3455 * return exp;
3003 * with: 3456 * with:
3004 * exp; return; 3457 * exp; return;
3005 */ 3458 */
3006 Statement *s = new ExpStatement(loc, exp); 3459 Statement *s = new ExpStatement(loc, exp);
3460 exp = NULL;
3461 s = s->semantic(sc);
3007 loc = 0; 3462 loc = 0;
3008 exp = NULL;
3009 return new CompoundStatement(loc, s, this); 3463 return new CompoundStatement(loc, s, this);
3010 } 3464 }
3011 3465
3012 return this; 3466 return this;
3013 } 3467 }
3017 3471
3018 if (exp && exp->canThrow()) 3472 if (exp && exp->canThrow())
3019 result |= BEthrow; 3473 result |= BEthrow;
3020 return result; 3474 return result;
3021 } 3475 }
3476
3022 3477
3023 void ReturnStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3478 void ReturnStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3024 { 3479 {
3025 buf->printf("return "); 3480 buf->printf("return ");
3026 if (exp) 3481 if (exp)
3110 { 3565 {
3111 //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak); 3566 //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak);
3112 return ident ? BEgoto : BEbreak; 3567 return ident ? BEgoto : BEbreak;
3113 } 3568 }
3114 3569
3570
3115 void BreakStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3571 void BreakStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3116 { 3572 {
3117 buf->writestring("break"); 3573 buf->writestring("break");
3118 if (ident) 3574 if (ident)
3119 { buf->writebyte(' '); 3575 { buf->writebyte(' ');
3211 int ContinueStatement::blockExit() 3667 int ContinueStatement::blockExit()
3212 { 3668 {
3213 return ident ? BEgoto : BEcontinue; 3669 return ident ? BEgoto : BEcontinue;
3214 } 3670 }
3215 3671
3672
3216 void ContinueStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3673 void ContinueStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3217 { 3674 {
3218 buf->writestring("continue"); 3675 buf->writestring("continue");
3219 if (ident) 3676 if (ident)
3220 { buf->writebyte(' '); 3677 { buf->writebyte(' ');
3254 } 3711 }
3255 3712
3256 Statement *SynchronizedStatement::semantic(Scope *sc) 3713 Statement *SynchronizedStatement::semantic(Scope *sc)
3257 { 3714 {
3258 if (exp) 3715 if (exp)
3259 { ClassDeclaration *cd; 3716 {
3260
3261 exp = exp->semantic(sc); 3717 exp = exp->semantic(sc);
3262 exp = resolveProperties(sc, exp); 3718 exp = resolveProperties(sc, exp);
3263 cd = exp->type->isClassHandle(); 3719 ClassDeclaration *cd = exp->type->isClassHandle();
3264 if (!cd) 3720 if (!cd)
3265 error("can only synchronize on class objects, not '%s'", exp->type->toChars()); 3721 error("can only synchronize on class objects, not '%s'", exp->type->toChars());
3266 else if (cd->isInterfaceDeclaration()) 3722 else if (cd->isInterfaceDeclaration())
3267 { Type *t = new TypeIdentifier(0, Id::Object); 3723 { /* Cast the interface to an object, as the object has the monitor,
3724 * not the interface.
3725 */
3726 Type *t = new TypeIdentifier(0, Id::Object);
3268 3727
3269 t = t->semantic(0, sc); 3728 t = t->semantic(0, sc);
3270 exp = new CastExp(loc, exp, t); 3729 exp = new CastExp(loc, exp, t);
3271 exp = exp->semantic(sc); 3730 exp = exp->semantic(sc);
3272 } 3731 }
3273 } 3732
3733 #if 0
3734 /* Rewrite as:
3735 * auto tmp = exp;
3736 * _d_monitorenter(tmp);
3737 * try { body } finally { _d_monitorexit(tmp); }
3738 */
3739 Identifier *id = Lexer::uniqueId("__sync");
3740 ExpInitializer *ie = new ExpInitializer(loc, exp);
3741 VarDeclaration *tmp = new VarDeclaration(loc, exp->type, id, ie);
3742
3743 Statements *cs = new Statements();
3744 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
3745
3746 FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::monitorenter);
3747 Expression *e = new CallExp(loc, new VarExp(loc, fdenter), new VarExp(loc, tmp));
3748 e->type = Type::tvoid; // do not run semantic on e
3749 cs->push(new ExpStatement(loc, e));
3750
3751 FuncDeclaration *fdexit = FuncDeclaration::genCfunc(Type::tvoid, Id::monitorexit);
3752 e = new CallExp(loc, new VarExp(loc, fdexit), new VarExp(loc, tmp));
3753 e->type = Type::tvoid; // do not run semantic on e
3754 Statement *s = new ExpStatement(loc, e);
3755 s = new TryFinallyStatement(loc, body, s);
3756 cs->push(s);
3757
3758 s = new CompoundStatement(loc, cs);
3759 return s->semantic(sc);
3760 #endif
3761 }
3762 #if 0
3763 else
3764 { /* Generate our own critical section, then rewrite as:
3765 * __gshared byte[CriticalSection.sizeof] critsec;
3766 * _d_criticalenter(critsec.ptr);
3767 * try { body } finally { _d_criticalexit(critsec.ptr); }
3768 */
3769 Identifier *id = Lexer::uniqueId("__critsec");
3770 Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + os_critsecsize()));
3771 VarDeclaration *tmp = new VarDeclaration(loc, t, id, NULL);
3772 tmp->storage_class |= STCgshared | STCstatic;
3773
3774 Statements *cs = new Statements();
3775 cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
3776
3777 FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalenter);
3778 Expression *e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr);
3779 e = e->semantic(sc);
3780 e = new CallExp(loc, new VarExp(loc, fdenter), e);
3781 e->type = Type::tvoid; // do not run semantic on e
3782 cs->push(new ExpStatement(loc, e));
3783
3784 FuncDeclaration *fdexit = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalexit);
3785 e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr);
3786 e = e->semantic(sc);
3787 e = new CallExp(loc, new VarExp(loc, fdexit), e);
3788 e->type = Type::tvoid; // do not run semantic on e
3789 Statement *s = new ExpStatement(loc, e);
3790 s = new TryFinallyStatement(loc, body, s);
3791 cs->push(s);
3792
3793 s = new CompoundStatement(loc, cs);
3794 return s->semantic(sc);
3795 }
3796 #endif
3274 if (body) 3797 if (body)
3275 { 3798 {
3276 Statement* oldScopeExit = sc->enclosingScopeExit; 3799 Statement* oldScopeExit = sc->enclosingScopeExit;
3277 sc->enclosingScopeExit = this; 3800 sc->enclosingScopeExit = this;
3278 body = body->semantic(sc); 3801 body = body->semantic(sc);
3298 3821
3299 int SynchronizedStatement::blockExit() 3822 int SynchronizedStatement::blockExit()
3300 { 3823 {
3301 return body ? body->blockExit() : BEfallthru; 3824 return body ? body->blockExit() : BEfallthru;
3302 } 3825 }
3826
3303 3827
3304 void SynchronizedStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3828 void SynchronizedStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3305 { 3829 {
3306 buf->writestring("synchronized"); 3830 buf->writestring("synchronized");
3307 if (exp) 3831 if (exp)
3416 else 3940 else
3417 result |= BEfallthru; 3941 result |= BEfallthru;
3418 return result; 3942 return result;
3419 } 3943 }
3420 3944
3945
3421 /******************************** TryCatchStatement ***************************/ 3946 /******************************** TryCatchStatement ***************************/
3422 3947
3423 TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Array *catches) 3948 TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Array *catches)
3424 : Statement(loc) 3949 : Statement(loc)
3425 { 3950 {
3460 3985
3461 if (c->type->toBasetype()->implicitConvTo(cj->type->toBasetype())) 3986 if (c->type->toBasetype()->implicitConvTo(cj->type->toBasetype()))
3462 error("catch at %s hides catch at %s", sj, si); 3987 error("catch at %s hides catch at %s", sj, si);
3463 } 3988 }
3464 } 3989 }
3990
3991 if (!body || body->isEmpty())
3992 {
3993 return NULL;
3994 }
3465 return this; 3995 return this;
3466 } 3996 }
3467 3997
3468 int TryCatchStatement::hasBreak() 3998 int TryCatchStatement::hasBreak()
3469 { 3999 {
3474 { 4004 {
3475 return TRUE; 4005 return TRUE;
3476 } 4006 }
3477 4007
3478 int TryCatchStatement::blockExit() 4008 int TryCatchStatement::blockExit()
3479 { int result; 4009 {
3480
3481 assert(body); 4010 assert(body);
3482 result = body->blockExit(); 4011 int result = body->blockExit();
3483 4012
3484 for (size_t i = 0; i < catches->dim; i++) 4013 for (size_t i = 0; i < catches->dim; i++)
3485 { 4014 {
3486 Catch *c = (Catch *)catches->data[i]; 4015 Catch *c = (Catch *)catches->data[i];
3487 result |= c->blockExit(); 4016 result |= c->blockExit();
3687 int OnScopeStatement::usesEH() 4216 int OnScopeStatement::usesEH()
3688 { 4217 {
3689 return (tok != TOKon_scope_success); 4218 return (tok != TOKon_scope_success);
3690 } 4219 }
3691 4220
3692 void OnScopeStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally) 4221 void OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
3693 { 4222 {
3694 //printf("OnScopeStatement::scopeCode()\n"); 4223 //printf("OnScopeStatement::scopeCode()\n");
3695 //print(); 4224 //print();
3696 *sentry = NULL; 4225 *sentry = NULL;
3697 *sexception = NULL; 4226 *sexception = NULL;
3768 int ThrowStatement::blockExit() 4297 int ThrowStatement::blockExit()
3769 { 4298 {
3770 return BEthrow; // obviously 4299 return BEthrow; // obviously
3771 } 4300 }
3772 4301
4302
3773 void ThrowStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4303 void ThrowStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3774 { 4304 {
3775 buf->printf("throw "); 4305 buf->printf("throw ");
3776 exp->toCBuffer(buf, hgs); 4306 exp->toCBuffer(buf, hgs);
3777 buf->writeByte(';'); 4307 buf->writeByte(';');
3824 4354
3825 int VolatileStatement::blockExit() 4355 int VolatileStatement::blockExit()
3826 { 4356 {
3827 return statement ? statement->blockExit() : BEfallthru; 4357 return statement ? statement->blockExit() : BEfallthru;
3828 } 4358 }
4359
3829 4360
3830 void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4361 void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3831 { 4362 {
3832 buf->writestring("volatile"); 4363 buf->writestring("volatile");
3833 if (statement) 4364 if (statement)
3890 { 4421 {
3891 //printf("GotoStatement::blockExit(%p)\n", this); 4422 //printf("GotoStatement::blockExit(%p)\n", this);
3892 return BEgoto; 4423 return BEgoto;
3893 } 4424 }
3894 4425
4426
3895 void GotoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4427 void GotoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3896 { 4428 {
3897 buf->writestring("goto "); 4429 buf->writestring("goto ");
3898 buf->writestring(ident->toChars()); 4430 buf->writestring(ident->toChars());
3899 buf->writebyte(';'); 4431 buf->writebyte(';');
3981 { 4513 {
3982 //printf("LabelStatement::blockExit(%p)\n", this); 4514 //printf("LabelStatement::blockExit(%p)\n", this);
3983 return statement ? statement->blockExit() : BEfallthru; 4515 return statement ? statement->blockExit() : BEfallthru;
3984 } 4516 }
3985 4517
4518
3986 int LabelStatement::comeFrom() 4519 int LabelStatement::comeFrom()
3987 { 4520 {
3988 //printf("LabelStatement::comeFrom()\n"); 4521 //printf("LabelStatement::comeFrom()\n");
3989 return TRUE; 4522 return TRUE;
3990 } 4523 }