1: 
   2: // Compiler implementation of the D programming language
   3: // Copyright (c) 1999-2011 by Digital Mars
   4: // All Rights Reserved
   5: // written by Walter Bright
   6: // http://www.digitalmars.com
   7: // License for redistribution is by either the Artistic License
   8: // in artistic.txt, or the GNU General Public License in gnu.txt.
   9: // See the included readme.txt for details.
  10: 
  11: #include <stdio.h>
  12: #include <stdlib.h>
  13: static char __file__[] = __FILE__;      /* for tassert.h                */
  14: #include        "tassert.h"
  15: 
  16: #include "rmem.h"
  17: 
  18: #include "statement.h"
  19: #include "expression.h"
  20: #include "cond.h"
  21: #include "init.h"
  22: #include "staticassert.h"
  23: #include "mtype.h"
  24: #include "scope.h"
  25: #include "declaration.h"
  26: #include "aggregate.h"
  27: #include "id.h"
  28: #include "hdrgen.h"
  29: #include "parse.h"
  30: #include "template.h"
  31: #include "attrib.h"
  32: 
  33: extern int os_critsecsize32();
  34: extern int os_critsecsize64();
  35: 
  36: /******************************** Statement ***************************/
  37: 
  38: Statement::Statement(Loc loc)
  39:     : loc(loc)
  40: {
  41:     // If this is an in{} contract scope statement (skip for determining
  42:     //  inlineStatus of a function body for header content)
  43:     incontract = 0;
  44: }
  45: 
  46: Statement *Statement::syntaxCopy()
  47: {
  48:     assert(0);
  49:     return NULL;
  50: }
  51: 
  52: void Statement::print()
  53: {
  54:     fprintf(stdmsg, "%s\n", toChars());
  55:     fflush(stdmsg);
  56: }
  57: 
  58: char *Statement::toChars()
  59: {   OutBuffer *buf;
  60:     HdrGenState hgs;
  61: 
  62:     buf = new OutBuffer();
  63:     toCBuffer(buf, &hgs);
  64:     return buf->toChars();
  65: }
  66: 
  67: void Statement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  68: {
  69:     buf->printf("Statement::toCBuffer()");
  70:     buf->writenl();
  71: }
  72: 
  73: Statement *Statement::semantic(Scope *sc)
  74: {
  75:     return this;
  76: }
  77: 
  78: Statement *Statement::semanticNoScope(Scope *sc)
  79: {
  80:     //printf("Statement::semanticNoScope() %s\n", toChars());
  81:     Statement *s = this;
  82:     if (!s->isCompoundStatement() && !s->isScopeStatement())
  83:     {
  84:         s = new CompoundStatement(loc, this);           // so scopeCode() gets called
  85:     }
  86:     s = s->semantic(sc);
  87:     return s;
  88: }
  89: 
  90: // Same as semanticNoScope(), but do create a new scope
  91: 
  92: Statement *Statement::semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue)
  93: {
  94:     Scope *scd = sc->push();
  95:     if (sbreak)
  96:         scd->sbreak = sbreak;
  97:     if (scontinue)
  98:         scd->scontinue = scontinue;
  99:     Statement *s = semanticNoScope(scd);
 100:     scd->pop();
 101:     return s;
 102: }
 103: 
 104: void Statement::error(const char *format, ...)
 105: {
 106:     va_list ap;
 107:     va_start(ap, format);
 108:     ::verror(loc, format, ap);
 109:     va_end( ap );
 110: }
 111: 
 112: void Statement::warning(const char *format, ...)
 113: {
 114:     va_list ap;
 115:     va_start(ap, format);
 116:     ::vwarning(loc, format, ap);
 117:     va_end( ap );
 118: }
 119: 
 120: int Statement::hasBreak()
 121: {
 122:     //printf("Statement::hasBreak()\n");
 123:     return FALSE;
 124: }
 125: 
 126: int Statement::hasContinue()
 127: {
 128:     return FALSE;
 129: }
 130: 
 131: // TRUE if statement uses exception handling
 132: 
 133: int Statement::usesEH()
 134: {
 135:     return FALSE;
 136: }
 137: 
 138: /* Only valid after semantic analysis
 139:  * If 'mustNotThrow' is true, generate an error if it throws
 140:  */
 141: int Statement::blockExit(bool mustNotThrow)
 142: {
 143:     printf("Statement::blockExit(%p)\n", this);
 144:     printf("%s\n", toChars());
 145:     assert(0);
 146:     return BEany;
 147: }
 148: 
 149: // TRUE if statement 'comes from' somewhere else, like a goto
 150: 
 151: int Statement::comeFrom()
 152: {
 153:     //printf("Statement::comeFrom()\n");
 154:     return FALSE;
 155: }
 156: 
 157: // Return TRUE if statement has no code in it
 158: int Statement::isEmpty()
 159: {
 160:     //printf("Statement::isEmpty()\n");
 161:     return FALSE;
 162: }
 163: 
 164: Statement *Statement::last()
 165: {
 166:     return this;
 167: }
 168: 
 169: /****************************************
 170:  * If this statement has code that needs to run in a finally clause
 171:  * at the end of the current scope, return that code in the form of
 172:  * a Statement.
 173:  * Output:
 174:  *      *sentry         code executed upon entry to the scope
 175:  *      *sexception     code executed upon exit from the scope via exception
 176:  *      *sfinally       code executed in finally block
 177:  */
 178: 
 179: Statement *Statement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
 180: {
 181:     //printf("Statement::scopeCode()\n");
 182:     //print();
 183:     *sentry = NULL;
 184:     *sexception = NULL;
 185:     *sfinally = NULL;
 186:     return this;
 187: }
 188: 
 189: /*********************************
 190:  * Flatten out the scope by presenting the statement
 191:  * as an array of statements.
 192:  * Returns NULL if no flattening necessary.
 193:  */
 194: 
 195: Statements *Statement::flatten(Scope *sc)
 196: {
 197:     return NULL;
 198: }
 199: 
 200: 
 201: /******************************** PeelStatement ***************************/
 202: 
 203: PeelStatement::PeelStatement(Statement *s)
 204:     : Statement(s->loc)
 205: {
 206:     this->s = s;
 207: }
 208: 
 209: Statement *PeelStatement::semantic(Scope *sc)
 210: {
 211:     /* "peel" off this wrapper, and don't run semantic()
 212:      * on the result.
 213:      */
 214:     return s;
 215: }
 216: 
 217: /******************************** ExpStatement ***************************/
 218: 
 219: ExpStatement::ExpStatement(Loc loc, Expression *exp)
 220:     : Statement(loc)
 221: {
 222:     this->exp = exp;
 223: }
 224: 
 225: ExpStatement::ExpStatement(Loc loc, Dsymbol *declaration)
 226:     : Statement(loc)
 227: {
 228:     this->exp = new DeclarationExp(loc, declaration);
 229: }
 230: 
 231: Statement *ExpStatement::syntaxCopy()
 232: {
 233:     Expression *e = exp ? exp->syntaxCopy() : NULL;
 234:     ExpStatement *es = new ExpStatement(loc, e);
 235:     return es;
 236: }
 237: 
 238: void ExpStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 239: {
 240:     if (exp)
 241:     {   exp->toCBuffer(buf, hgs);
 242:         if (exp->op != TOKdeclaration)
 243:         {   buf->writeByte(';');
 244:             if (!hgs->FLinit.init)
 245:                 buf->writenl();
 246:         }
 247:     }
 248:     else
 249:     {
 250:         buf->writeByte(';');
 251:         if (!hgs->FLinit.init)
 252:             buf->writenl();
 253:     }
 254: }
 255: 
 256: Statement *ExpStatement::semantic(Scope *sc)
 257: {
 258:     if (exp)
 259:     {
 260:         //printf("ExpStatement::semantic() %s\n", exp->toChars());
 261: 
 262: #if 0   // Doesn't work because of difficulty dealing with things like a.b.c!(args).Foo!(args)
 263:         // See if this should be rewritten as a TemplateMixin
 264:         if (exp->op == TOKdeclaration)
 265:         {   DeclarationExp *de = (DeclarationExp *)exp;
 266:             Dsymbol *s = de->declaration;
 267: 
 268:             printf("s: %s %s\n", s->kind(), s->toChars());
 269:             VarDeclaration *v = s->isVarDeclaration();
 270:             if (v)
 271:             {
 272:                 printf("%s, %d\n", v->type->toChars(), v->type->ty);
 273:             }
 274:         }
 275: #endif
 276: 
 277:         exp = exp->semantic(sc);
 278:         exp = exp->addDtorHook(sc);
 279:         exp = resolveProperties(sc, exp);
 280:         exp->checkSideEffect(0);
 281:         exp = exp->optimize(0);
 282:     }
 283:     return this;
 284: }
 285: 
 286: int ExpStatement::blockExit(bool mustNotThrow)
 287: {   int result = BEfallthru;
 288: 
 289:     if (exp)
 290:     {
 291:         if (exp->op == TOKhalt)
 292:             return BEhalt;
 293:         if (exp->op == TOKassert)
 294:         {   AssertExp *a = (AssertExp *)exp;
 295: 
 296:             if (a->e1->isBool(FALSE))   // if it's an assert(0)
 297:                 return BEhalt;
 298:         }
 299:         if (exp->canThrow(mustNotThrow))
 300:             result |= BEthrow;
 301:     }
 302:     return result;
 303: }
 304: 
 305: int ExpStatement::isEmpty()
 306: {
 307:     return exp == NULL;
 308: }
 309: 
 310: Statement *ExpStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
 311: {
 312:     //printf("ExpStatement::scopeCode()\n");
 313:     //print();
 314: 
 315:     *sentry = NULL;
 316:     *sexception = NULL;
 317:     *sfinally = NULL;
 318: 
 319:     if (exp)
 320:     {
 321:         if (exp->op == TOKdeclaration)
 322:         {
 323:             DeclarationExp *de = (DeclarationExp *)(exp);
 324:             VarDeclaration *v = de->declaration->isVarDeclaration();
 325:             if (v && !v->noscope)
 326:             {
 327:                 Expression *e = v->edtor;
 328:                 if (e)
 329:                 {
 330:                     //printf("dtor is: "); e->print();
 331: #if 0
 332:                     if (v->type->toBasetype()->ty == Tstruct)
 333:                     {   /* Need a 'gate' to turn on/off destruction,
 334:                          * in case v gets moved elsewhere.
 335:                          */
 336:                         Identifier *id = Lexer::uniqueId("__runDtor");
 337:                         ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(1));
 338:                         VarDeclaration *rd = new VarDeclaration(loc, Type::tint32, id, ie);
 339:                         *sentry = new ExpStatement(loc, rd);
 340:                         v->rundtor = rd;
 341: 
 342:                         /* Rewrite e as:
 343:                          *  rundtor && e
 344:                          */
 345:                         Expression *ve = new VarExp(loc, v->rundtor);
 346:                         e = new AndAndExp(loc, ve, e);
 347:                         e->type = Type::tbool;
 348:                     }
 349: #endif
 350:                     *sfinally = new DtorExpStatement(loc, e, v);
 351:                 }
 352:                 v->noscope = 1;         // don't add in dtor again
 353:             }
 354:         }
 355:     }
 356:     return this;
 357: }
 358: 
 359: 
 360: /******************************** DtorExpStatement ***************************/
 361: 
 362: DtorExpStatement::DtorExpStatement(Loc loc, Expression *exp, VarDeclaration *v)
 363:     : ExpStatement(loc, exp)
 364: {
 365:     this->var = v;
 366: }
 367: 
 368: Statement *DtorExpStatement::syntaxCopy()
 369: {
 370:     Expression *e = exp ? exp->syntaxCopy() : NULL;
 371:     DtorExpStatement *es = new DtorExpStatement(loc, e, var);
 372:     return es;
 373: }
 374: 
 375: /******************************** CompileStatement ***************************/
 376: 
 377: CompileStatement::CompileStatement(Loc loc, Expression *exp)
 378:     : Statement(loc)
 379: {
 380:     this->exp = exp;
 381: }
 382: 
 383: Statement *CompileStatement::syntaxCopy()
 384: {
 385:     Expression *e = exp->syntaxCopy();
 386:     CompileStatement *es = new CompileStatement(loc, e);
 387:     return es;
 388: }
 389: 
 390: void CompileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 391: {
 392:     buf->writestring("mixin(");
 393:     exp->toCBuffer(buf, hgs);
 394:     buf->writestring(");");
 395:     if (!hgs->FLinit.init)
 396:         buf->writenl();
 397: }
 398: 
 399: Statements *CompileStatement::flatten(Scope *sc)
 400: {
 401:     //printf("CompileStatement::flatten() %s\n", exp->toChars());
 402:     exp = exp->semantic(sc);
 403:     exp = resolveProperties(sc, exp);
 404:     exp = exp->optimize(WANTvalue | WANTinterpret);
 405:     if (exp->op == TOKerror)
 406:         return NULL;
 407:     if (exp->op != TOKstring)
 408:     {   error("argument to mixin must be a string, not (%s)", exp->toChars());
 409:         return NULL;
 410:     }
 411:     StringExp *se = (StringExp *)exp;
 412:     se = se->toUTF8(sc);
 413:     Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
 414:     p.loc = loc;
 415:     p.nextToken();
 416: 
 417:     Statements *a = new Statements();
 418:     while (p.token.value != TOKeof)
 419:     {
 420:         Statement *s = p.parseStatement(PSsemi | PScurlyscope);
 421:         if (s)                  // if no parsing errors
 422:             a->push(s);
 423:     }
 424:     return a;
 425: }
 426: 
 427: Statement *CompileStatement::semantic(Scope *sc)
 428: {
 429:     //printf("CompileStatement::semantic() %s\n", exp->toChars());
 430:     Statements *a = flatten(sc);
 431:     if (!a)
 432:         return NULL;
 433:     Statement *s = new CompoundStatement(loc, a);
 434:     return s->semantic(sc);
 435: }
 436: 
 437: 
 438: /******************************** CompoundStatement ***************************/
 439: 
 440: CompoundStatement::CompoundStatement(Loc loc, Statements *s)
 441:     : Statement(loc)
 442: {
 443:     statements = s;
 444: }
 445: 
 446: CompoundStatement::CompoundStatement(Loc loc, Statement *s1, Statement *s2)
 447:     : Statement(loc)
 448: {
 449:     statements = new Statements();
 450:     statements->reserve(2);
 451:     statements->push(s1);
 452:     statements->push(s2);
 453: }
 454: 
 455: CompoundStatement::CompoundStatement(Loc loc, Statement *s1)
 456:     : Statement(loc)
 457: {
 458:     statements = new Statements();
 459:     statements->push(s1);
 460: }
 461: 
 462: Statement *CompoundStatement::syntaxCopy()
 463: {
 464:     Statements *a = new Statements();
 465:     a->setDim(statements->dim);
 466:     for (size_t i = 0; i < statements->dim; i++)
 467:     {   Statement *s = statements->tdata()[i];
 468:         if (s)
 469:             s = s->syntaxCopy();
 470:         a->tdata()[i] = s;
 471:     }
 472:     CompoundStatement *cs = new CompoundStatement(loc, a);
 473:     return cs;
 474: }
 475: 
 476: 
 477: Statement *CompoundStatement::semantic(Scope *sc)
 478: {   Statement *s;
 479: 
 480:     //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", this, sc);
 481: 
 482: #if 0
 483:     for (size_t i = 0; i < statements->dim; i++)
 484:     {
 485:         s = statements->tdata()[i];
 486:         if (s)
 487:             printf("[%d]: %s", i, s->toChars());
 488:     }
 489: #endif
 490: 
 491:     for (size_t i = 0; i < statements->dim; )
 492:     {
 493:         s = statements->tdata()[i];
 494:         if (s)
 495:         {   Statements *a = s->flatten(sc);
 496: 
 497:             if (a)
 498:             {
 499:                 statements->remove(i);
 500:                 statements->insert(i, a);
 501:                 continue;
 502:             }
 503:             s = s->semantic(sc);
 504:             statements->tdata()[i] = s;
 505:             if (s)
 506:             {
 507:                 Statement *sentry;
 508:                 Statement *sexception;
 509:                 Statement *sfinally;
 510: 
 511:                 statements->tdata()[i] = s->scopeCode(sc, &sentry, &sexception, &sfinally);
 512:                 if (sentry)
 513:                 {
 514:                     sentry = sentry->semantic(sc);
 515:                     statements->insert(i, sentry);
 516:                     i++;
 517:                 }
 518:                 if (sexception)
 519:                 {
 520:                     if (i + 1 == statements->dim && !sfinally)
 521:                     {
 522:                         sexception = sexception->semantic(sc);
 523:                     }
 524:                     else
 525:                     {
 526:                         /* Rewrite:
 527:                          *      s; s1; s2;
 528:                          * As:
 529:                          *      s;
 530:                          *      try { s1; s2; }
 531:                          *      catch (Object __o)
 532:                          *      { sexception; throw __o; }
 533:                          */
 534:                         Statement *body;
 535:                         Statements *a = new Statements();
warning C6246: Local declaration of 'a' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '495' of 'c:\projects\extern\d\dmd\src\statement.c': Lines: 495
536: 537: for (int j = i + 1; j < statements->dim; j++)
warning C4018: '<' : signed/unsigned mismatch
538: { 539: a->push(statements->tdata()[j]); 540: } 541: body = new CompoundStatement(0, a); 542: body = new ScopeStatement(0, body);
warning C6211: Leaking memory 'body' due to an exception. Consider using a local catch block to clean up memory: Lines: 478, 491, 493, 494, 495, 497, 499, 500, 491, 493, 494, 592, 491, 493, 494, 495, 497, 503, 504, 505, 507, 508, 509, 511, 512, 514, 515, 516, 518, 520, 534, 535, 537, 541, 542, 544, 546
543: 544: Identifier *id = Lexer::uniqueId("__o"); 545: 546: Statement *handler = new ThrowStatement(0, new IdentifierExp(0, id)); 547: handler = new CompoundStatement(0, sexception, handler);
warning C6211: Leaking memory 'handler' due to an exception. Consider using a local catch block to clean up memory: Lines: 478, 491, 493, 494, 495, 497, 499, 500, 491, 493, 494, 592, 491, 493, 494, 495, 497, 503, 504, 505, 507, 508, 509, 511, 512, 514, 515, 516, 518, 520, 534, 535, 537, 541, 542, 544, 546, 547, 549
548: 549: Catches *catches = new Catches();
warning C6211: Leaking memory 'catches' due to an exception. Consider using a local catch block to clean up memory: Lines: 478, 491, 493, 494, 495, 497, 499, 500, 491, 493, 494, 592, 491, 493, 494, 495, 497, 503, 504, 505, 507, 508, 509, 511, 512, 514, 515, 516, 518, 520, 534, 535, 537, 541, 542, 544, 546, 547, 549, 550
550: Catch *ctch = new Catch(0, NULL, id, handler); 551: catches->push(ctch); 552: s = new TryCatchStatement(0, body, catches); 553: 554: if (sfinally) 555: s = new TryFinallyStatement(0, s, sfinally); 556: s = s->semantic(sc); 557: statements->setDim(i + 1); 558: statements->push(s); 559: break; 560: } 561: } 562: else if (sfinally) 563: { 564: if (0 && i + 1 == statements->dim) 565: { 566: statements->push(sfinally); 567: } 568: else 569: { 570: /* Rewrite: 571: * s; s1; s2; 572: * As: 573: * s; try { s1; s2; } finally { sfinally; } 574: */ 575: Statement *body; 576: Statements *a = new Statements();
warning C6246: Local declaration of 'a' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '495' of 'c:\projects\extern\d\dmd\src\statement.c': Lines: 495
577: 578: for (int j = i + 1; j < statements->dim; j++)
warning C4018: '<' : signed/unsigned mismatch
579: { 580: a->push(statements->tdata()[j]); 581: } 582: body = new CompoundStatement(0, a); 583: s = new TryFinallyStatement(0, body, sfinally); 584: s = s->semantic(sc); 585: statements->setDim(i + 1); 586: statements->push(s); 587: break; 588: } 589: } 590: } 591: } 592: i++; 593: } 594: if (statements->dim == 1) 595: { 596: return statements->tdata()[0]; 597: } 598: return this; 599: } 600: 601: Statements *CompoundStatement::flatten(Scope *sc) 602: { 603: return statements; 604: } 605: 606: ReturnStatement *CompoundStatement::isReturnStatement() 607: { 608: ReturnStatement *rs = NULL; 609: 610: for (int i = 0; i < statements->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
611: { Statement *s = statements->tdata()[i]; 612: if (s) 613: { 614: rs = s->isReturnStatement(); 615: if (rs) 616: break; 617: } 618: } 619: return rs; 620: } 621: 622: Statement *CompoundStatement::last() 623: { 624: Statement *s = NULL; 625: 626: for (size_t i = statements->dim; i; --i) 627: { s = statements->tdata()[i - 1]; 628: if (s) 629: { 630: s = s->last(); 631: if (s) 632: break; 633: } 634: } 635: return s; 636: } 637: 638: void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 639: { 640: for (int i = 0; i < statements->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
641: { Statement *s = statements->tdata()[i]; 642: if (s) 643: s->toCBuffer(buf, hgs); 644: } 645: } 646: 647: int CompoundStatement::usesEH() 648: { 649: for (int i = 0; i < statements->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
650: { Statement *s = statements->tdata()[i]; 651: if (s && s->usesEH()) 652: return TRUE; 653: } 654: return FALSE; 655: } 656: 657: int CompoundStatement::blockExit(bool mustNotThrow) 658: { 659: //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim); 660: int result = BEfallthru; 661: Statement *slast = NULL; 662: for (size_t i = 0; i < statements->dim; i++) 663: { Statement *s = statements->tdata()[i]; 664: if (s) 665: { 666: //printf("result = x%x\n", result); 667: //printf("%s\n", s->toChars()); 668: if (global.params.warnings && result & BEfallthru && slast) 669: { 670: slast = slast->last(); 671: if (slast && (s->isCaseStatement() || s->isDefaultStatement())) 672: { 673: // Allow if last case/default was empty 674: CaseStatement *sc = slast->isCaseStatement(); 675: DefaultStatement *sd = slast->isDefaultStatement(); 676: if (sc && sc->statement->isEmpty()) 677: ; 678: else if (sd && sd->statement->isEmpty()) 679: ; 680: else 681: s->error("switch case fallthrough - use 'goto %s;' if intended", 682: s->isCaseStatement() ? "case" : "default"); 683: } 684: } 685: 686: if (!(result & BEfallthru) && !s->comeFrom()) 687: { 688: if (s->blockExit(mustNotThrow) != BEhalt && !s->isEmpty()) 689: s->warning("statement is not reachable"); 690: } 691: else 692: { 693: result &= ~BEfallthru; 694: result |= s->blockExit(mustNotThrow); 695: } 696: slast = s; 697: } 698: } 699: return result; 700: } 701: 702: int CompoundStatement::comeFrom() 703: { int comefrom = FALSE; 704: 705: //printf("CompoundStatement::comeFrom()\n"); 706: for (int i = 0; i < statements->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
707: { Statement *s = statements->tdata()[i]; 708: 709: if (!s) 710: continue; 711: 712: comefrom |= s->comeFrom(); 713: } 714: return comefrom; 715: } 716: 717: int CompoundStatement::isEmpty() 718: { 719: for (int i = 0; i < statements->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
720: { Statement *s = statements->tdata()[i]; 721: if (s && !s->isEmpty()) 722: return FALSE; 723: } 724: return TRUE; 725: } 726: 727: 728: /******************************** CompoundDeclarationStatement ***************************/ 729: 730: CompoundDeclarationStatement::CompoundDeclarationStatement(Loc loc, Statements *s) 731: : CompoundStatement(loc, s) 732: { 733: statements = s; 734: } 735: 736: Statement *CompoundDeclarationStatement::syntaxCopy() 737: { 738: Statements *a = new Statements(); 739: a->setDim(statements->dim); 740: for (size_t i = 0; i < statements->dim; i++) 741: { Statement *s = statements->tdata()[i]; 742: if (s) 743: s = s->syntaxCopy(); 744: a->tdata()[i] = s; 745: } 746: CompoundDeclarationStatement *cs = new CompoundDeclarationStatement(loc, a); 747: return cs; 748: } 749: 750: void CompoundDeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 751: { 752: int nwritten = 0; 753: for (int i = 0; i < statements->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
754: { Statement *s = statements->tdata()[i]; 755: ExpStatement *ds; 756: if (s && 757: (ds = s->isExpStatement()) != NULL && 758: ds->exp->op == TOKdeclaration) 759: { 760: DeclarationExp *de = (DeclarationExp *)ds->exp; 761: Declaration *d = de->declaration->isDeclaration(); 762: assert(d); 763: VarDeclaration *v = d->isVarDeclaration(); 764: if (v) 765: { 766: /* This essentially copies the part of VarDeclaration::toCBuffer() 767: * that does not print the type. 768: * Should refactor this. 769: */ 770: if (nwritten) 771: { 772: buf->writeByte(','); 773: buf->writestring(v->ident->toChars()); 774: } 775: else 776: { 777: StorageClassDeclaration::stcToCBuffer(buf, v->storage_class); 778: if (v->type) 779: v->type->toCBuffer(buf, v->ident, hgs); 780: else 781: buf->writestring(v->ident->toChars()); 782: } 783: 784: if (v->init) 785: { buf->writestring(" = "); 786: #if DMDV2 787: ExpInitializer *ie = v->init->isExpInitializer(); 788: if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit)) 789: ((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs); 790: else 791: #endif 792: v->init->toCBuffer(buf, hgs); 793: } 794: } 795: else 796: d->toCBuffer(buf, hgs); 797: nwritten++; 798: } 799: } 800: buf->writeByte(';'); 801: if (!hgs->FLinit.init) 802: buf->writenl(); 803: } 804: 805: /**************************** UnrolledLoopStatement ***************************/ 806: 807: UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s) 808: : Statement(loc) 809: { 810: statements = s; 811: } 812: 813: Statement *UnrolledLoopStatement::syntaxCopy() 814: { 815: Statements *a = new Statements(); 816: a->setDim(statements->dim); 817: for (size_t i = 0; i < statements->dim; i++) 818: { Statement *s = statements->tdata()[i]; 819: if (s) 820: s = s->syntaxCopy(); 821: a->tdata()[i] = s; 822: } 823: UnrolledLoopStatement *cs = new UnrolledLoopStatement(loc, a); 824: return cs; 825: } 826: 827: 828: Statement *UnrolledLoopStatement::semantic(Scope *sc) 829: { 830: //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc); 831: 832: sc->noctor++; 833: Scope *scd = sc->push(); 834: scd->sbreak = this; 835: scd->scontinue = this; 836: 837: for (size_t i = 0; i < statements->dim; i++) 838: { 839: Statement *s = statements->tdata()[i]; 840: if (s) 841: { 842: //printf("[%d]: %s\n", i, s->toChars()); 843: s = s->semantic(scd); 844: statements->tdata()[i] = s; 845: } 846: } 847: 848: scd->pop(); 849: sc->noctor--; 850: return this; 851: } 852: 853: void UnrolledLoopStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 854: { 855: buf->writestring("unrolled {"); 856: buf->writenl(); 857: 858: for (size_t i = 0; i < statements->dim; i++) 859: { Statement *s; 860: 861: s = statements->tdata()[i]; 862: if (s) 863: s->toCBuffer(buf, hgs); 864: } 865: 866: buf->writeByte('}'); 867: buf->writenl(); 868: } 869: 870: int UnrolledLoopStatement::hasBreak() 871: { 872: return TRUE; 873: } 874: 875: int UnrolledLoopStatement::hasContinue() 876: { 877: return TRUE; 878: } 879: 880: int UnrolledLoopStatement::usesEH() 881: { 882: for (size_t i = 0; i < statements->dim; i++) 883: { Statement *s = statements->tdata()[i]; 884: if (s && s->usesEH()) 885: return TRUE; 886: } 887: return FALSE; 888: } 889: 890: int UnrolledLoopStatement::blockExit(bool mustNotThrow) 891: { 892: int result = BEfallthru; 893: for (size_t i = 0; i < statements->dim; i++) 894: { Statement *s = statements->tdata()[i]; 895: if (s) 896: { 897: int r = s->blockExit(mustNotThrow); 898: result |= r & ~(BEbreak | BEcontinue); 899: } 900: } 901: return result; 902: } 903: 904: 905: int UnrolledLoopStatement::comeFrom() 906: { int comefrom = FALSE; 907: 908: //printf("UnrolledLoopStatement::comeFrom()\n"); 909: for (size_t i = 0; i < statements->dim; i++) 910: { Statement *s = statements->tdata()[i]; 911: 912: if (!s) 913: continue; 914: 915: comefrom |= s->comeFrom(); 916: } 917: return comefrom; 918: } 919: 920: 921: /******************************** ScopeStatement ***************************/ 922: 923: ScopeStatement::ScopeStatement(Loc loc, Statement *s) 924: : Statement(loc) 925: { 926: this->statement = s; 927: } 928: 929: Statement *ScopeStatement::syntaxCopy() 930: { 931: Statement *s; 932: 933: s = statement ? statement->syntaxCopy() : NULL; 934: s = new ScopeStatement(loc, s); 935: return s; 936: } 937: 938: 939: Statement *ScopeStatement::semantic(Scope *sc) 940: { ScopeDsymbol *sym; 941: 942: //printf("ScopeStatement::semantic(sc = %p)\n", sc); 943: if (statement) 944: { Statements *a; 945: 946: sym = new ScopeDsymbol(); 947: sym->parent = sc->scopesym; 948: sc = sc->push(sym); 949: 950: a = statement->flatten(sc); 951: if (a) 952: { 953: statement = new CompoundStatement(loc, a); 954: } 955: 956: statement = statement->semantic(sc); 957: if (statement) 958: { 959: Statement *sentry; 960: Statement *sexception; 961: Statement *sfinally; 962: 963: statement = statement->scopeCode(sc, &sentry, &sexception, &sfinally); 964: assert(!sentry); 965: assert(!sexception); 966: if (sfinally) 967: { 968: //printf("adding sfinally\n"); 969: sfinally = sfinally->semantic(sc); 970: statement = new CompoundStatement(loc, statement, sfinally); 971: } 972: } 973: 974: sc->pop(); 975: } 976: return this; 977: } 978: 979: int ScopeStatement::hasBreak() 980: { 981: //printf("ScopeStatement::hasBreak() %s\n", toChars()); 982: return statement ? statement->hasBreak() : FALSE; 983: } 984: 985: int ScopeStatement::hasContinue() 986: { 987: return statement ? statement->hasContinue() : FALSE; 988: } 989: 990: int ScopeStatement::usesEH() 991: { 992: return statement ? statement->usesEH() : FALSE; 993: } 994: 995: int ScopeStatement::blockExit(bool mustNotThrow) 996: { 997: //printf("ScopeStatement::blockExit(%p)\n", statement); 998: return statement ? statement->blockExit(mustNotThrow) : BEfallthru; 999: } 1000: 1001: 1002: int ScopeStatement::comeFrom() 1003: { 1004: //printf("ScopeStatement::comeFrom()\n"); 1005: return statement ? statement->comeFrom() : FALSE; 1006: } 1007: 1008: int ScopeStatement::isEmpty() 1009: { 1010: //printf("ScopeStatement::isEmpty() %d\n", statement ? statement->isEmpty() : TRUE); 1011: return statement ? statement->isEmpty() : TRUE; 1012: } 1013: 1014: void ScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 1015: { 1016: buf->writeByte('{'); 1017: buf->writenl(); 1018: 1019: if (statement) 1020: statement->toCBuffer(buf, hgs); 1021: 1022: buf->writeByte('}'); 1023: buf->writenl(); 1024: } 1025: 1026: /******************************** WhileStatement ***************************/ 1027: 1028: WhileStatement::WhileStatement(Loc loc, Expression *c, Statement *b) 1029: : Statement(loc) 1030: { 1031: condition = c; 1032: body = b; 1033: } 1034: 1035: Statement *WhileStatement::syntaxCopy() 1036: { 1037: WhileStatement *s = new WhileStatement(loc, condition->syntaxCopy(), body ? body->syntaxCopy() : NULL); 1038: return s; 1039: } 1040: 1041: 1042: Statement *WhileStatement::semantic(Scope *sc) 1043: { 1044: /* Rewrite as a for(;condition;) loop 1045: */ 1046: 1047: Statement *s = new ForStatement(loc, NULL, condition, NULL, body); 1048: s = s->semantic(sc); 1049: return s; 1050: } 1051: 1052: int WhileStatement::hasBreak() 1053: { 1054: return TRUE; 1055: } 1056: 1057: int WhileStatement::hasContinue() 1058: { 1059: return TRUE; 1060: } 1061: 1062: int WhileStatement::usesEH() 1063: { 1064: assert(0); 1065: return body ? body->usesEH() : 0; 1066: } 1067: 1068: int WhileStatement::blockExit(bool mustNotThrow) 1069: { 1070: assert(0); 1071: //printf("WhileStatement::blockExit(%p)\n", this); 1072: 1073: int result = BEnone; 1074: if (condition->canThrow(mustNotThrow)) 1075: result |= BEthrow; 1076: if (condition->isBool(TRUE)) 1077: { 1078: if (body) 1079: { result |= body->blockExit(mustNotThrow); 1080: if (result & BEbreak) 1081: result |= BEfallthru; 1082: } 1083: } 1084: else if (condition->isBool(FALSE)) 1085: { 1086: result |= BEfallthru; 1087: } 1088: else 1089: { 1090: if (body) 1091: result |= body->blockExit(mustNotThrow); 1092: result |= BEfallthru; 1093: } 1094: result &= ~(BEbreak | BEcontinue); 1095: return result; 1096: } 1097: 1098: 1099: int WhileStatement::comeFrom() 1100: { 1101: assert(0); 1102: if (body) 1103: return body->comeFrom(); 1104: return FALSE; 1105: } 1106: 1107: void WhileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 1108: { 1109: buf->writestring("while ("); 1110: condition->toCBuffer(buf, hgs); 1111: buf->writebyte(')'); 1112: buf->writenl(); 1113: if (body) 1114: body->toCBuffer(buf, hgs); 1115: } 1116: 1117: /******************************** DoStatement ***************************/ 1118: 1119: DoStatement::DoStatement(Loc loc, Statement *b, Expression *c) 1120: : Statement(loc) 1121: { 1122: body = b; 1123: condition = c; 1124: } 1125: 1126: Statement *DoStatement::syntaxCopy() 1127: { 1128: DoStatement *s = new DoStatement(loc, body ? body->syntaxCopy() : NULL, condition->syntaxCopy()); 1129: return s; 1130: } 1131: 1132: 1133: Statement *DoStatement::semantic(Scope *sc) 1134: { 1135: sc->noctor++; 1136: if (body) 1137: body = body->semanticScope(sc, this, this); 1138: sc->noctor--; 1139: condition = condition->semantic(sc); 1140: condition = resolveProperties(sc, condition); 1141: condition = condition->optimize(WANTvalue); 1142: 1143: condition = condition->checkToBoolean(sc); 1144: 1145: return this; 1146: } 1147: 1148: int DoStatement::hasBreak() 1149: { 1150: return TRUE; 1151: } 1152: 1153: int DoStatement::hasContinue() 1154: { 1155: return TRUE; 1156: } 1157: 1158: int DoStatement::usesEH() 1159: { 1160: return body ? body->usesEH() : 0; 1161: } 1162: 1163: int DoStatement::blockExit(bool mustNotThrow) 1164: { int result; 1165: 1166: if (body) 1167: { result = body->blockExit(mustNotThrow); 1168: if (result == BEbreak) 1169: return BEfallthru; 1170: if (result & BEcontinue) 1171: result |= BEfallthru; 1172: } 1173: else 1174: result = BEfallthru; 1175: if (result & BEfallthru) 1176: { 1177: if (condition->canThrow(mustNotThrow)) 1178: result |= BEthrow; 1179: if (!(result & BEbreak) && condition->isBool(TRUE)) 1180: result &= ~BEfallthru; 1181: } 1182: result &= ~(BEbreak | BEcontinue); 1183: return result; 1184: } 1185: 1186: 1187: int DoStatement::comeFrom() 1188: { 1189: if (body) 1190: return body->comeFrom(); 1191: return FALSE; 1192: } 1193: 1194: void DoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 1195: { 1196: buf->writestring("do"); 1197: buf->writenl(); 1198: if (body) 1199: body->toCBuffer(buf, hgs); 1200: buf->writestring("while ("); 1201: condition->toCBuffer(buf, hgs); 1202: buf->writebyte(')'); 1203: } 1204: 1205: /******************************** ForStatement ***************************/ 1206: 1207: ForStatement::ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body) 1208: : Statement(loc) 1209: { 1210: this->init = init; 1211: this->condition = condition; 1212: this->increment = increment; 1213: this->body = body; 1214: } 1215: 1216: Statement *ForStatement::syntaxCopy() 1217: { 1218: Statement *i = NULL; 1219: if (init) 1220: i = init->syntaxCopy(); 1221: Expression *c = NULL; 1222: if (condition) 1223: c = condition->syntaxCopy(); 1224: Expression *inc = NULL; 1225: if (increment) 1226: inc = increment->syntaxCopy(); 1227: ForStatement *s = new ForStatement(loc, i, c, inc, body->syntaxCopy()); 1228: return s; 1229: } 1230: 1231: Statement *ForStatement::semantic(Scope *sc) 1232: { 1233: ScopeDsymbol *sym = new ScopeDsymbol(); 1234: sym->parent = sc->scopesym; 1235: sc = sc->push(sym); 1236: if (init) 1237: init = init->semantic(sc); 1238: sc->noctor++; 1239: if (condition) 1240: { 1241: condition = condition->semantic(sc); 1242: condition = resolveProperties(sc, condition); 1243: condition = condition->optimize(WANTvalue); 1244: condition = condition->checkToBoolean(sc); 1245: } 1246: if (increment) 1247: { increment = increment->semantic(sc); 1248: increment = resolveProperties(sc, increment); 1249: increment = increment->optimize(0); 1250: } 1251: 1252: sc->sbreak = this; 1253: sc->scontinue = this; 1254: if (body) 1255: body = body->semanticNoScope(sc); 1256: sc->noctor--; 1257: 1258: sc->pop(); 1259: return this; 1260: } 1261: 1262: Statement *ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) 1263: { 1264: //printf("ForStatement::scopeCode()\n"); 1265: //print(); 1266: if (init) 1267: init = init->scopeCode(sc, sentry, sexception, sfinally); 1268: else 1269: Statement::scopeCode(sc, sentry, sexception, sfinally); 1270: return this; 1271: } 1272: 1273: int ForStatement::hasBreak() 1274: { 1275: //printf("ForStatement::hasBreak()\n"); 1276: return TRUE; 1277: } 1278: 1279: int ForStatement::hasContinue() 1280: { 1281: return TRUE; 1282: } 1283: 1284: int ForStatement::usesEH() 1285: { 1286: return (init && init->usesEH()) || body->usesEH(); 1287: } 1288: 1289: int ForStatement::blockExit(bool mustNotThrow) 1290: { int result = BEfallthru; 1291: 1292: if (init) 1293: { result = init->blockExit(mustNotThrow); 1294: if (!(result & BEfallthru)) 1295: return result; 1296: } 1297: if (condition) 1298: { if (condition->canThrow(mustNotThrow)) 1299: result |= BEthrow; 1300: if (condition->isBool(TRUE)) 1301: result &= ~BEfallthru; 1302: else if (condition->isBool(FALSE)) 1303: return result; 1304: } 1305: else 1306: result &= ~BEfallthru; // the body must do the exiting 1307: if (body) 1308: { int r = body->blockExit(mustNotThrow); 1309: if (r & (BEbreak | BEgoto)) 1310: result |= BEfallthru; 1311: result |= r & ~(BEfallthru | BEbreak | BEcontinue); 1312: } 1313: if (increment && increment->canThrow(mustNotThrow)) 1314: result |= BEthrow; 1315: return result; 1316: } 1317: 1318: 1319: int ForStatement::comeFrom() 1320: { 1321: //printf("ForStatement::comeFrom()\n"); 1322: if (body) 1323: { int result = body->comeFrom(); 1324: //printf("result = %d\n", result); 1325: return result; 1326: } 1327: return FALSE; 1328: } 1329: 1330: void ForStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 1331: { 1332: buf->writestring("for ("); 1333: if (init) 1334: { 1335: hgs->FLinit.init++; 1336: init->toCBuffer(buf, hgs); 1337: hgs->FLinit.init--; 1338: } 1339: else 1340: buf->writebyte(';'); 1341: if (condition) 1342: { buf->writebyte(' '); 1343: condition->toCBuffer(buf, hgs); 1344: } 1345: buf->writebyte(';'); 1346: if (increment) 1347: { buf->writebyte(' '); 1348: increment->toCBuffer(buf, hgs); 1349: } 1350: buf->writebyte(')'); 1351: buf->writenl(); 1352: buf->writebyte('{'); 1353: buf->writenl(); 1354: body->toCBuffer(buf, hgs); 1355: buf->writebyte('}'); 1356: buf->writenl(); 1357: } 1358: 1359: /******************************** ForeachStatement ***************************/ 1360: 1361: ForeachStatement::ForeachStatement(Loc loc, enum TOK op, Parameters *arguments, 1362: Expression *aggr, Statement *body) 1363: : Statement(loc) 1364: { 1365: this->op = op; 1366: this->arguments = arguments; 1367: this->aggr = aggr; 1368: this->body = body; 1369: 1370: this->key = NULL; 1371: this->value = NULL; 1372: 1373: this->func = NULL; 1374: 1375: this->cases = NULL; 1376: this->gotos = NULL; 1377: } 1378: 1379: Statement *ForeachStatement::syntaxCopy() 1380: { 1381: Parameters *args = Parameter::arraySyntaxCopy(arguments); 1382: Expression *exp = aggr->syntaxCopy(); 1383: ForeachStatement *s = new ForeachStatement(loc, op, args, exp, 1384: body ? body->syntaxCopy() : NULL); 1385: return s; 1386: } 1387: 1388: Statement *ForeachStatement::semantic(Scope *sc) 1389: { 1390: //printf("ForeachStatement::semantic() %p\n", this); 1391: ScopeDsymbol *sym; 1392: Statement *s = this; 1393: size_t dim = arguments->dim; 1394: TypeAArray *taa = NULL; 1395: Dsymbol *sapply = NULL; 1396: 1397: Type *tn = NULL; 1398: Type *tnv = NULL; 1399: 1400: func = sc->func; 1401: if (func->fes) 1402: func = func->fes->func; 1403: 1404: aggr = aggr->semantic(sc); 1405: aggr = resolveProperties(sc, aggr); 1406: aggr = aggr->optimize(WANTvalue); 1407: if (!aggr->type) 1408: { 1409: error("invalid foreach aggregate %s", aggr->toChars()); 1410: return this; 1411: } 1412: 1413: inferApplyArgTypes(op, arguments, aggr); 1414: 1415: /* Check for inference errors 1416: */ 1417: if (dim != arguments->dim) 1418: { 1419: //printf("dim = %d, arguments->dim = %d\n", dim, arguments->dim); 1420: error("cannot uniquely infer foreach argument types"); 1421: return this; 1422: } 1423: 1424: Type *tab = aggr->type->toBasetype(); 1425: 1426: if (tab->ty == Ttuple) // don't generate new scope for tuple loops 1427: { 1428: if (dim < 1 || dim > 2) 1429: { 1430: error("only one (value) or two (key,value) arguments for tuple foreach"); 1431: return s; 1432: } 1433: 1434: TypeTuple *tuple = (TypeTuple *)tab; 1435: Statements *statements = new Statements();
warning C6211: Leaking memory 'statements' due to an exception. Consider using a local catch block to clean up memory: Lines: 1391, 1392, 1393, 1394, 1395, 1397, 1398, 1400, 1401, 1402, 1404, 1405, 1406, 1407, 1413, 1417, 1424, 1426, 1428, 1434, 1435, 1437, 1438, 1439, 1440, 1441, 1449, 1450, 1451, 1452, 1453, 1454, 1457, 1458
1436: //printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars()); 1437: size_t n; 1438: TupleExp *te = NULL; 1439: if (aggr->op == TOKtuple) // expression tuple 1440: { te = (TupleExp *)aggr; 1441: n = te->exps->dim; 1442: } 1443: else if (aggr->op == TOKtype) // type tuple 1444: { 1445: n = Parameter::dim(tuple->arguments); 1446: } 1447: else 1448: assert(0); 1449: for (size_t j = 0; j < n; j++) 1450: { size_t k = (op == TOKforeach) ? j : n - 1 - j; 1451: Expression *e; 1452: Type *t; 1453: if (te) 1454: e = te->exps->tdata()[k]; 1455: else 1456: t = Parameter::getNth(tuple->arguments, k)->type; 1457: Parameter *arg = arguments->tdata()[0]; 1458: Statements *st = new Statements();
warning C6211: Leaking memory 'st' due to an exception. Consider using a local catch block to clean up memory: Lines: 1391, 1392, 1393, 1394, 1395, 1397, 1398, 1400, 1401, 1402, 1404, 1405, 1406, 1407, 1413, 1417, 1424, 1426, 1428, 1434, 1435, 1437, 1438, 1439, 1440, 1441, 1449, 1450, 1451, 1452, 1453, 1454, 1457, 1458, 1460, 1483, 1484, 1485, 1486, 1487, 1488, 1494, 1495
1459: 1460: if (dim == 2) 1461: { // Declare key 1462: if (arg->storageClass & (STCout | STCref | STClazy)) 1463: error("no storage class for key %s", arg->ident->toChars()); 1464: TY keyty = arg->type->ty; 1465: if (keyty != Tint32 && keyty != Tuns32) 1466: { 1467: if (global.params.is64bit) 1468: { 1469: if (keyty != Tint64 && keyty != Tuns64) 1470: error("foreach: key type must be int or uint, long or ulong, not %s", arg->type->toChars()); 1471: } 1472: else 1473: error("foreach: key type must be int or uint, not %s", arg->type->toChars()); 1474: } 1475: Initializer *ie = new ExpInitializer(0, new IntegerExp(k)); 1476: VarDeclaration *var = new VarDeclaration(loc, arg->type, arg->ident, ie); 1477: var->storage_class |= STCmanifest; 1478: DeclarationExp *de = new DeclarationExp(loc, var); 1479: st->push(new ExpStatement(loc, de)); 1480: arg = arguments->tdata()[1]; // value 1481: } 1482: // Declare value 1483: if (arg->storageClass & (STCout | STCref | STClazy)) 1484: error("no storage class for value %s", arg->ident->toChars()); 1485: Dsymbol *var; 1486: if (te) 1487: { Type *tb = e->type->toBasetype(); 1488: if ((tb->ty == Tfunction || tb->ty == Tsarray) && e->op == TOKvar) 1489: { VarExp *ve = (VarExp *)e; 1490: var = new AliasDeclaration(loc, arg->ident, ve->var); 1491: } 1492: else 1493: { 1494: arg->type = e->type; 1495: Initializer *ie = new ExpInitializer(0, e); 1496: VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie); 1497: if (e->isConst() || e->op == TOKstring) 1498: v->storage_class |= STCconst; 1499: var = v; 1500: } 1501: } 1502: else 1503: { 1504: var = new AliasDeclaration(loc, arg->ident, t); 1505: } 1506: DeclarationExp *de = new DeclarationExp(loc, var); 1507: st->push(new ExpStatement(loc, de)); 1508: 1509: st->push(body->syntaxCopy()); 1510: s = new CompoundStatement(loc, st); 1511: s = new ScopeStatement(loc, s); 1512: statements->push(s); 1513: } 1514: 1515: s = new UnrolledLoopStatement(loc, statements); 1516: s = s->semantic(sc); 1517: return s; 1518: } 1519: 1520: sym = new ScopeDsymbol(); 1521: sym->parent = sc->scopesym; 1522: sc = sc->push(sym); 1523: 1524: sc->noctor++; 1525: 1526: Lagain: 1527: Identifier *idapply = (op == TOKforeach_reverse) 1528: ? Id::applyReverse : Id::apply; 1529: sapply = NULL; 1530: switch (tab->ty) 1531: { 1532: case Tarray: 1533: case Tsarray: 1534: if (!checkForArgTypes()) 1535: return this; 1536: 1537: if (dim < 1 || dim > 2) 1538: { 1539: error("only one or two arguments for array foreach"); 1540: break; 1541: } 1542: 1543: /* Look for special case of parsing char types out of char type 1544: * array. 1545: */ 1546: tn = tab->nextOf()->toBasetype(); 1547: if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar) 1548: { Parameter *arg; 1549: 1550: int i = (dim == 1) ? 0 : 1; // index of value 1551: arg = arguments->tdata()[i]; 1552: arg->type = arg->type->semantic(loc, sc); 1553: tnv = arg->type->toBasetype(); 1554: if (tnv->ty != tn->ty && 1555: (tnv->ty == Tchar || tnv->ty == Twchar || tnv->ty == Tdchar)) 1556: { 1557: if (arg->storageClass & STCref) 1558: error("foreach: value of UTF conversion cannot be ref"); 1559: if (dim == 2) 1560: { arg = arguments->tdata()[0]; 1561: if (arg->storageClass & STCref) 1562: error("foreach: key cannot be ref"); 1563: } 1564: goto Lapply; 1565: } 1566: } 1567: 1568: for (size_t i = 0; i < dim; i++) 1569: { // Declare args 1570: Parameter *arg = arguments->tdata()[i]; 1571: Type *argtype = arg->type->semantic(loc, sc); 1572: VarDeclaration *var; 1573: 1574: var = new VarDeclaration(loc, argtype, arg->ident, NULL); 1575: var->storage_class |= STCforeach; 1576: var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR); 1577: if (var->storage_class & (STCref | STCout)) 1578: var->storage_class |= STCnodtor; 1579: if (dim == 2 && i == 0) 1580: { key = var; 1581: //var->storage_class |= STCfinal; 1582: } 1583: else 1584: { 1585: value = var; 1586: /* Reference to immutable data should be marked as const 1587: */ 1588: if (var->storage_class & STCref && !tn->isMutable()) 1589: { 1590: var->storage_class |= STCconst; 1591: } 1592: } 1593: #if 0 1594: DeclarationExp *de = new DeclarationExp(loc, var); 1595: de->semantic(sc); 1596: #endif 1597: } 1598: 1599: #if 1 1600: { 1601: /* Convert to a ForStatement 1602: * foreach (key, value; a) body => 1603: * for (T[] tmp = a[], size_t key; key < tmp.length; ++key) 1604: * { T value = tmp[k]; body } 1605: * 1606: * foreach_reverse (key, value; a) body => 1607: * for (T[] tmp = a[], size_t key = tmp.length; key--; ) 1608: * { T value = tmp[k]; body } 1609: */ 1610: Identifier *id = Lexer::uniqueId("__aggr"); 1611: ExpInitializer *ie = new ExpInitializer(loc, new SliceExp(loc, aggr, NULL, NULL)); 1612: VarDeclaration *tmp = new VarDeclaration(loc, tab->nextOf()->arrayOf(), id, ie); 1613: 1614: Expression *tmp_length = new DotIdExp(loc, new VarExp(loc, tmp), Id::length); 1615: 1616: if (!key) 1617: { 1618: Identifier *id = Lexer::uniqueId("__key");
warning C6246: Local declaration of 'id' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '1610' of 'c:\projects\extern\d\dmd\src\statement.c': Lines: 1610
1619: key = new VarDeclaration(loc, Type::tsize_t, id, NULL); 1620: } 1621: if (op == TOKforeach_reverse) 1622: key->init = new ExpInitializer(loc, tmp_length); 1623: else 1624: key->init = new ExpInitializer(loc, new IntegerExp(0)); 1625: 1626: Statements *cs = new Statements(); 1627: cs->push(new ExpStatement(loc, tmp)); 1628: cs->push(new ExpStatement(loc, key)); 1629: Statement *forinit = new CompoundDeclarationStatement(loc, cs); 1630: 1631: Expression *cond; 1632: if (op == TOKforeach_reverse) 1633: // key-- 1634: cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key)); 1635: else 1636: // key < tmp.length 1637: cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), tmp_length); 1638: 1639: Expression *increment = NULL; 1640: if (op == TOKforeach) 1641: // key += 1 1642: increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1)); 1643: 1644: // T value = tmp[key]; 1645: value->init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, key))); 1646: Statement *ds = new ExpStatement(loc, value); 1647: 1648: body = new CompoundStatement(loc, ds, body); 1649: 1650: ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body); 1651: s = fs->semantic(sc); 1652: break; 1653: } 1654: #else 1655: if (tab->nextOf()->implicitConvTo(value->type) < MATCHconst) 1656: { 1657: if (aggr->op == TOKstring) 1658: aggr = aggr->implicitCastTo(sc, value->type->arrayOf()); 1659: else 1660: error("foreach: %s is not an array of %s", 1661: tab->toChars(), value->type->toChars()); 1662: } 1663: 1664: if (key) 1665: { 1666: if (key->type->ty != Tint32 && key->type->ty != Tuns32) 1667: { 1668: if (global.params.is64bit) 1669: { 1670: if (key->type->ty != Tint64 && key->type->ty != Tuns64) 1671: error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars()); 1672: } 1673: else 1674: error("foreach: key type must be int or uint, not %s", key->type->toChars()); 1675: } 1676: 1677: if (key->storage_class & (STCout | STCref)) 1678: error("foreach: key cannot be out or ref"); 1679: } 1680: 1681: sc->sbreak = this; 1682: sc->scontinue = this; 1683: body = body->semantic(sc); 1684: break; 1685: #endif 1686: 1687: case Taarray: 1688: if (!checkForArgTypes()) 1689: return this; 1690: 1691: taa = (TypeAArray *)tab; 1692: if (dim < 1 || dim > 2) 1693: { 1694: error("only one or two arguments for associative array foreach"); 1695: break; 1696: } 1697: #if SARRAYVALUE 1698: /* This only works if Key or Value is a static array. 1699: */ 1700: tab = taa->getImpl()->type; 1701: goto Lagain; 1702: #else 1703: if (op == TOKforeach_reverse) 1704: { 1705: error("no reverse iteration on associative arrays"); 1706: } 1707: goto Lapply; 1708: #endif 1709: case Tclass: 1710: case Tstruct: 1711: #if DMDV2 1712: /* Prefer using opApply, if it exists 1713: */ 1714: if (dim != 1) // only one argument allowed with ranges 1715: goto Lapply; 1716: 1717: sapply = search_function((AggregateDeclaration *)tab->toDsymbol(sc), idapply); 1718: if (sapply) 1719: goto Lapply; 1720: 1721: { /* Look for range iteration, i.e. the properties 1722: * .empty, .next, .retreat, .head and .rear 1723: * foreach (e; aggr) { ... } 1724: * translates to: 1725: * for (auto __r = aggr[]; !__r.empty; __r.next) 1726: * { auto e = __r.head; 1727: * ... 1728: * } 1729: */ 1730: AggregateDeclaration *ad = (tab->ty == Tclass) 1731: ? (AggregateDeclaration *)((TypeClass *)tab)->sym 1732: : (AggregateDeclaration *)((TypeStruct *)tab)->sym; 1733: Identifier *idhead; 1734: Identifier *idnext; 1735: if (op == TOKforeach) 1736: { idhead = Id::Fhead; 1737: idnext = Id::Fnext; 1738: } 1739: else 1740: { idhead = Id::Ftoe; 1741: idnext = Id::Fretreat; 1742: } 1743: Dsymbol *shead = search_function(ad, idhead); 1744: if (!shead) 1745: goto Lapply; 1746: 1747: /* Generate a temporary __r and initialize it with the aggregate. 1748: */ 1749: Identifier *id = Identifier::generateId("__r"); 1750: Expression *rinit = new SliceExp(loc, aggr, NULL, NULL); 1751: rinit = rinit->trySemantic(sc); 1752: if (!rinit) // if application of [] failed 1753: rinit = aggr; 1754: VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, rinit)); 1755: // r->semantic(sc); 1756: //printf("r: %s, init: %s\n", r->toChars(), r->init->toChars()); 1757: Statement *init = new ExpStatement(loc, r); 1758: //printf("init: %s\n", init->toChars()); 1759: 1760: // !__r.empty 1761: Expression *e = new VarExp(loc, r); 1762: e = new DotIdExp(loc, e, Id::Fempty); 1763: Expression *condition = new NotExp(loc, e); 1764: 1765: // __r.next 1766: e = new VarExp(loc, r); 1767: Expression *increment = new CallExp(loc, new DotIdExp(loc, e, idnext)); 1768: 1769: /* Declaration statement for e: 1770: * auto e = __r.idhead; 1771: */ 1772: e = new VarExp(loc, r); 1773: Expression *einit = new DotIdExp(loc, e, idhead); 1774: // einit = einit->semantic(sc); 1775: Parameter *arg = arguments->tdata()[0]; 1776: VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit)); 1777: ve->storage_class |= STCforeach; 1778: ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR); 1779: 1780: DeclarationExp *de = new DeclarationExp(loc, ve); 1781: 1782: Statement *body = new CompoundStatement(loc, 1783: new ExpStatement(loc, de), this->body); 1784: 1785: s = new ForStatement(loc, init, condition, increment, body); 1786: #if 0 1787: printf("init: %s\n", init->toChars()); 1788: printf("condition: %s\n", condition->toChars()); 1789: printf("increment: %s\n", increment->toChars()); 1790: printf("body: %s\n", body->toChars()); 1791: #endif 1792: s = s->semantic(sc); 1793: break; 1794: } 1795: #endif 1796: case Tdelegate: 1797: Lapply: 1798: { 1799: Expression *ec; 1800: Expression *e; 1801: Parameter *a; 1802: 1803: if (!checkForArgTypes()) 1804: { body = body->semanticNoScope(sc); 1805: return this; 1806: } 1807: 1808: Type *tret = func->type->nextOf(); 1809: 1810: // Need a variable to hold value from any return statements in body. 1811: if (!sc->func->vresult && tret && tret != Type::tvoid) 1812: { 1813: VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL); 1814: v->noscope = 1; 1815: v->semantic(sc); 1816: if (!sc->insert(v)) 1817: assert(0); 1818: v->parent = sc->func; 1819: sc->func->vresult = v; 1820: } 1821: 1822: /* Turn body into the function literal: 1823: * int delegate(ref T arg) { body } 1824: */ 1825: Parameters *args = new Parameters(); 1826: for (size_t i = 0; i < dim; i++) 1827: { Parameter *arg = arguments->tdata()[i]; 1828: Identifier *id; 1829: 1830: arg->type = arg->type->semantic(loc, sc); 1831: if (arg->storageClass & STCref) 1832: id = arg->ident; 1833: else 1834: { // Make a copy of the ref argument so it isn't 1835: // a reference. 1836: 1837: id = Lexer::uniqueId("__applyArg", i); 1838: Initializer *ie = new ExpInitializer(0, new IdentifierExp(0, id)); 1839: VarDeclaration *v = new VarDeclaration(0, arg->type, arg->ident, ie); 1840: s = new ExpStatement(0, v); 1841: body = new CompoundStatement(loc, s, body); 1842: } 1843: a = new Parameter(STCref, arg->type, id, NULL); 1844: args->push(a); 1845: } 1846: Type *t = new TypeFunction(args, Type::tint32, 0, LINKd); 1847: cases = new Statements(); 1848: gotos = new CompoundStatements(); 1849: FuncLiteralDeclaration *fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this); 1850: fld->fbody = body; 1851: Expression *flde = new FuncExp(loc, fld); 1852: flde = flde->semantic(sc); 1853: fld->tookAddressOf = 0; 1854: 1855: // Resolve any forward referenced goto's 1856: for (size_t i = 0; i < gotos->dim; i++) 1857: { CompoundStatement *cs = gotos->tdata()[i]; 1858: GotoStatement *gs = (GotoStatement *)cs->statements->tdata()[0]; 1859: 1860: if (!gs->label->statement) 1861: { // 'Promote' it to this scope, and replace with a return 1862: cases->push(gs); 1863: s = new ReturnStatement(0, new IntegerExp(cases->dim + 1)); 1864: cs->statements->tdata()[0] = s; 1865: } 1866: } 1867: 1868: if (taa) 1869: { 1870: // Check types 1871: Parameter *arg = arguments->tdata()[0]; 1872: if (dim == 2) 1873: { 1874: if (arg->storageClass & STCref) 1875: error("foreach: index cannot be ref"); 1876: if (!arg->type->equals(taa->index)) 1877: error("foreach: index must be type %s, not %s", taa->index->toChars(), arg->type->toChars()); 1878: arg = arguments->tdata()[1]; 1879: } 1880: if (!arg->type->equals(taa->nextOf())) 1881: error("foreach: value must be type %s, not %s", taa->nextOf()->toChars(), arg->type->toChars()); 1882: 1883: /* Call: 1884: * _aaApply(aggr, keysize, flde) 1885: */ 1886: FuncDeclaration *fdapply; 1887: if (dim == 2) 1888: fdapply = FuncDeclaration::genCfunc(Type::tindex, "_aaApply2"); 1889: else 1890: fdapply = FuncDeclaration::genCfunc(Type::tindex, "_aaApply"); 1891: ec = new VarExp(0, fdapply); 1892: Expressions *exps = new Expressions(); 1893: exps->push(aggr); 1894: size_t keysize = taa->index->size();
warning C4244: 'initializing' : conversion from 'd_uns64' to 'size_t', possible loss of data
1895: keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1); 1896: exps->push(new IntegerExp(0, keysize, Type::tsize_t)); 1897: exps->push(flde); 1898: e = new CallExp(loc, ec, exps); 1899: e->type = Type::tindex; // don't run semantic() on e 1900: } 1901: else if (tab->ty == Tarray || tab->ty == Tsarray) 1902: { 1903: /* Call: 1904: * _aApply(aggr, flde) 1905: */ 1906: static char fntab[9][3] = 1907: { "cc","cw","cd", 1908: "wc","cc","wd", 1909: "dc","dw","dd" 1910: }; 1911: char fdname[7+1+2+ sizeof(dim)*3 + 1]; 1912: int flag; 1913: 1914: switch (tn->ty) 1915: { 1916: case Tchar: flag = 0; break; 1917: case Twchar: flag = 3; break; 1918: case Tdchar: flag = 6; break; 1919: default: assert(0); 1920: } 1921: switch (tnv->ty) 1922: { 1923: case Tchar: flag += 0; break; 1924: case Twchar: flag += 1; break; 1925: case Tdchar: flag += 2; break; 1926: default: assert(0); 1927: } 1928: const char *r = (op == TOKforeach_reverse) ? "R" : ""; 1929: int j = sprintf(fdname, "_aApply%s%.*s%zd", r, 2, fntab[flag], dim);
warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
warning C6271: Extra argument passed to 'sprintf': parameter '6' is not used by the format string
1930: assert(j < sizeof(fdname)); 1931: FuncDeclaration *fdapply = FuncDeclaration::genCfunc(Type::tindex, fdname); 1932: 1933: ec = new VarExp(0, fdapply); 1934: Expressions *exps = new Expressions(); 1935: if (tab->ty == Tsarray) 1936: aggr = aggr->castTo(sc, tn->arrayOf()); 1937: exps->push(aggr); 1938: exps->push(flde); 1939: e = new CallExp(loc, ec, exps); 1940: e->type = Type::tindex; // don't run semantic() on e 1941: } 1942: else if (tab->ty == Tdelegate) 1943: { 1944: /* Call: 1945: * aggr(flde) 1946: */ 1947: Expressions *exps = new Expressions(); 1948: exps->push(flde); 1949: if (aggr->op == TOKdelegate && 1950: ((DelegateExp *)aggr)->func->isNested()) 1951: // See Bugzilla 3560 1952: e = new CallExp(loc, ((DelegateExp *)aggr)->e1, exps); 1953: else 1954: e = new CallExp(loc, aggr, exps); 1955: e = e->semantic(sc); 1956: if (e->type != Type::tint32) 1957: error("opApply() function for %s must return an int", tab->toChars()); 1958: } 1959: else 1960: { 1961: assert(tab->ty == Tstruct || tab->ty == Tclass); 1962: Expressions *exps = new Expressions(); 1963: if (!sapply) 1964: sapply = search_function((AggregateDeclaration *)tab->toDsymbol(sc), idapply); 1965: #if 0 1966: TemplateDeclaration *td; 1967: if (sapply && 1968: (td = sapply->isTemplateDeclaration()) != NULL) 1969: { /* Call: 1970: * aggr.apply!(fld)() 1971: */ 1972: Objects *tiargs = new Objects(); 1973: tiargs->push(fld); 1974: ec = new DotTemplateInstanceExp(loc, aggr, idapply, tiargs); 1975: } 1976: else 1977: #endif 1978: { 1979: /* Call: 1980: * aggr.apply(flde) 1981: */ 1982: ec = new DotIdExp(loc, aggr, idapply); 1983: exps->push(flde); 1984: } 1985: e = new CallExp(loc, ec, exps); 1986: e = e->semantic(sc); 1987: if (e->type != Type::tint32) 1988: error("opApply() function for %s must return an int", tab->toChars()); 1989: } 1990: 1991: if (!cases->dim) 1992: // Easy case, a clean exit from the loop 1993: s = new ExpStatement(loc, e); 1994: else 1995: { // Construct a switch statement around the return value 1996: // of the apply function. 1997: Statements *a = new Statements();
warning C6246: Local declaration of 'a' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '1801' of 'c:\projects\extern\d\dmd\src\statement.c': Lines: 1801
1998: 1999: // default: break; takes care of cases 0 and 1 2000: s = new BreakStatement(0, NULL); 2001: s = new DefaultStatement(0, s); 2002: a->push(s); 2003: 2004: // cases 2... 2005: for (int i = 0; i < cases->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
2006: { 2007: s = cases->tdata()[i]; 2008: s = new CaseStatement(0, new IntegerExp(i + 2), s); 2009: a->push(s); 2010: } 2011: 2012: s = new CompoundStatement(loc, a); 2013: s = new SwitchStatement(loc, e, s, FALSE); 2014: s = s->semantic(sc); 2015: } 2016: break; 2017: } 2018: case Terror: 2019: s = NULL; 2020: break; 2021: 2022: default: 2023: error("foreach: %s is not an aggregate type", aggr->type->toChars()); 2024: s = NULL; // error recovery 2025: break; 2026: } 2027: sc->noctor--; 2028: sc->pop(); 2029: return s; 2030: } 2031: 2032: bool ForeachStatement::checkForArgTypes() 2033: { bool result = TRUE; 2034: 2035: for (size_t i = 0; i < arguments->dim; i++) 2036: { Parameter *arg = arguments->tdata()[i]; 2037: if (!arg->type) 2038: { 2039: error("cannot infer type for %s", arg->ident->toChars()); 2040: arg->type = Type::terror; 2041: result = FALSE; 2042: } 2043: } 2044: return result; 2045: } 2046: 2047: int ForeachStatement::hasBreak() 2048: { 2049: return TRUE; 2050: } 2051: 2052: int ForeachStatement::hasContinue() 2053: { 2054: return TRUE; 2055: } 2056: 2057: int ForeachStatement::usesEH() 2058: { 2059: return body->usesEH(); 2060: } 2061: 2062: int ForeachStatement::blockExit(bool mustNotThrow) 2063: { int result = BEfallthru; 2064: 2065: if (aggr->canThrow(mustNotThrow)) 2066: result |= BEthrow; 2067: 2068: if (body) 2069: { 2070: result |= body->blockExit(mustNotThrow) & ~(BEbreak | BEcontinue); 2071: } 2072: return result; 2073: } 2074: 2075: 2076: int ForeachStatement::comeFrom() 2077: { 2078: if (body) 2079: return body->comeFrom(); 2080: return FALSE; 2081: } 2082: 2083: void ForeachStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2084: { 2085: buf->writestring(Token::toChars(op)); 2086: buf->writestring(" ("); 2087: for (int i = 0; i < arguments->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
2088: { 2089: Parameter *a = arguments->tdata()[i]; 2090: if (i) 2091: buf->writestring(", "); 2092: if (a->storageClass & STCref) 2093: buf->writestring((global.params.Dversion == 1) 2094: ? (char*)"inout " : (char*)"ref "); 2095: if (a->type) 2096: a->type->toCBuffer(buf, a->ident, hgs); 2097: else 2098: buf->writestring(a->ident->toChars()); 2099: } 2100: buf->writestring("; "); 2101: aggr->toCBuffer(buf, hgs); 2102: buf->writebyte(')'); 2103: buf->writenl(); 2104: buf->writebyte('{'); 2105: buf->writenl(); 2106: if (body) 2107: body->toCBuffer(buf, hgs); 2108: buf->writebyte('}'); 2109: buf->writenl(); 2110: } 2111: 2112: /**************************** ForeachRangeStatement ***************************/ 2113: 2114: #if DMDV2 2115: 2116: ForeachRangeStatement::ForeachRangeStatement(Loc loc, enum TOK op, Parameter *arg, 2117: Expression *lwr, Expression *upr, Statement *body) 2118: : Statement(loc) 2119: { 2120: this->op = op; 2121: this->arg = arg; 2122: this->lwr = lwr; 2123: this->upr = upr; 2124: this->body = body; 2125: 2126: this->key = NULL; 2127: } 2128: 2129: Statement *ForeachRangeStatement::syntaxCopy() 2130: { 2131: ForeachRangeStatement *s = new ForeachRangeStatement(loc, op, 2132: arg->syntaxCopy(), 2133: lwr->syntaxCopy(), 2134: upr->syntaxCopy(), 2135: body ? body->syntaxCopy() : NULL); 2136: return s; 2137: } 2138: 2139: Statement *ForeachRangeStatement::semantic(Scope *sc) 2140: { 2141: //printf("ForeachRangeStatement::semantic() %p\n", this); 2142: ScopeDsymbol *sym;
warning C4101: 'sym' : unreferenced local variable
2143: Statement *s = this; 2144: 2145: lwr = lwr->semantic(sc); 2146: lwr = resolveProperties(sc, lwr); 2147: lwr = lwr->optimize(WANTvalue); 2148: if (!lwr->type) 2149: { 2150: error("invalid range lower bound %s", lwr->toChars()); 2151: return this; 2152: } 2153: 2154: upr = upr->semantic(sc); 2155: upr = resolveProperties(sc, upr); 2156: upr = upr->optimize(WANTvalue); 2157: if (!upr->type) 2158: { 2159: error("invalid range upper bound %s", upr->toChars()); 2160: return this; 2161: } 2162: 2163: if (arg->type) 2164: { 2165: arg->type = arg->type->semantic(loc, sc); 2166: lwr = lwr->implicitCastTo(sc, arg->type); 2167: upr = upr->implicitCastTo(sc, arg->type); 2168: } 2169: else 2170: { 2171: /* Must infer types from lwr and upr 2172: */ 2173: Type *tlwr = lwr->type->toBasetype(); 2174: if (tlwr->ty == Tstruct || tlwr->ty == Tclass) 2175: { 2176: /* Just picking the first really isn't good enough. 2177: */ 2178: arg->type = lwr->type->mutableOf(); 2179: } 2180: else 2181: { 2182: AddExp ea(loc, lwr, upr); 2183: Expression *e = ea.typeCombine(sc); 2184: arg->type = ea.type->mutableOf(); 2185: lwr = ea.e1; 2186: upr = ea.e2; 2187: } 2188: } 2189: #if 1 2190: /* Convert to a for loop: 2191: * foreach (key; lwr .. upr) => 2192: * for (auto key = lwr, auto tmp = upr; key < tmp; ++key) 2193: * 2194: * foreach_reverse (key; lwr .. upr) => 2195: * for (auto tmp = lwr, auto key = upr; key-- > tmp;) 2196: */ 2197: 2198: ExpInitializer *ie = new ExpInitializer(loc, (op == TOKforeach) ? lwr : upr); 2199: key = new VarDeclaration(loc, arg->type, arg->ident, ie); 2200: 2201: Identifier *id = Lexer::uniqueId("__limit"); 2202: ie = new ExpInitializer(loc, (op == TOKforeach) ? upr : lwr); 2203: VarDeclaration *tmp = new VarDeclaration(loc, arg->type, id, ie);
warning C6211: Leaking memory 'tmp' due to an exception. Consider using a local catch block to clean up memory: Lines: 2142, 2143, 2145, 2146, 2147, 2148, 2154, 2155, 2156, 2157, 2163, 2165, 2166, 2167, 2198, 2199, 2201, 2202, 2203, 2205
2204: 2205: Statements *cs = new Statements();
warning C6211: Leaking memory 'cs' due to an exception. Consider using a local catch block to clean up memory: Lines: 2142, 2143, 2145, 2146, 2147, 2148, 2154, 2155, 2156, 2157, 2163, 2165, 2166, 2167, 2198, 2199, 2201, 2202, 2203, 2205, 2207, 2214
2206: // Keep order of evaluation as lwr, then upr 2207: if (op == TOKforeach) 2208: { 2209: cs->push(new ExpStatement(loc, key)); 2210: cs->push(new ExpStatement(loc, tmp)); 2211: } 2212: else 2213: { 2214: cs->push(new ExpStatement(loc, tmp)); 2215: cs->push(new ExpStatement(loc, key)); 2216: } 2217: Statement *forinit = new CompoundDeclarationStatement(loc, cs);
warning C6211: Leaking memory 'forinit' due to an exception. Consider using a local catch block to clean up memory: Lines: 2142, 2143, 2145, 2146, 2147, 2148, 2154, 2155, 2156, 2157, 2163, 2165, 2166, 2167, 2198, 2199, 2201, 2202, 2203, 2205, 2207, 2214, 2215, 2217, 2219, 2220, 2232, 2234
2218: 2219: Expression *cond; 2220: if (op == TOKforeach_reverse) 2221: { 2222: cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key)); 2223: if (arg->type->isscalar()) 2224: // key-- > tmp 2225: cond = new CmpExp(TOKgt, loc, cond, new VarExp(loc, tmp)); 2226: else 2227: // key-- != tmp 2228: cond = new EqualExp(TOKnotequal, loc, cond, new VarExp(loc, tmp)); 2229: } 2230: else 2231: { 2232: if (arg->type->isscalar()) 2233: // key < tmp 2234: cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), new VarExp(loc, tmp));
warning C6211: Leaking memory 'cond' due to an exception. Consider using a local catch block to clean up memory: Lines: 2142, 2143, 2145, 2146, 2147, 2148, 2154, 2155, 2156, 2157, 2163, 2165, 2166, 2167, 2198, 2199, 2201, 2202, 2203, 2205, 2207, 2209, 2210, 2217, 2219, 2220, 2232, 2234, 2240, 2241, 2244
2235: else 2236: // key != tmp 2237: cond = new EqualExp(TOKnotequal, loc, new VarExp(loc, key), new VarExp(loc, tmp)); 2238: } 2239: 2240: Expression *increment = NULL; 2241: if (op == TOKforeach) 2242: // key += 1 2243: //increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1)); 2244: increment = new PreExp(TOKpreplusplus, loc, new VarExp(loc, key)); 2245: 2246: ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body); 2247: s = fs->semantic(sc); 2248: return s; 2249: #else 2250: if (!arg->type->isscalar()) 2251: error("%s is not a scalar type", arg->type->toChars()); 2252: 2253: sym = new ScopeDsymbol(); 2254: sym->parent = sc->scopesym; 2255: sc = sc->push(sym); 2256: 2257: sc->noctor++; 2258: 2259: key = new VarDeclaration(loc, arg->type, arg->ident, NULL); 2260: DeclarationExp *de = new DeclarationExp(loc, key); 2261: de->semantic(sc); 2262: 2263: if (key->storage_class) 2264: error("foreach range: key cannot have storage class"); 2265: 2266: sc->sbreak = this; 2267: sc->scontinue = this; 2268: body = body->semantic(sc); 2269: 2270: sc->noctor--; 2271: sc->pop(); 2272: return s; 2273: #endif 2274: } 2275: 2276: int ForeachRangeStatement::hasBreak() 2277: { 2278: return TRUE; 2279: } 2280: 2281: int ForeachRangeStatement::hasContinue() 2282: { 2283: return TRUE; 2284: } 2285: 2286: int ForeachRangeStatement::usesEH() 2287: { 2288: assert(0); 2289: return body->usesEH(); 2290: } 2291: 2292: int ForeachRangeStatement::blockExit(bool mustNotThrow) 2293: { 2294: assert(0); 2295: int result = BEfallthru; 2296: 2297: if (lwr && lwr->canThrow(mustNotThrow)) 2298: result |= BEthrow; 2299: else if (upr && upr->canThrow(mustNotThrow)) 2300: result |= BEthrow; 2301: 2302: if (body) 2303: { 2304: result |= body->blockExit(mustNotThrow) & ~(BEbreak | BEcontinue); 2305: } 2306: return result; 2307: } 2308: 2309: 2310: int ForeachRangeStatement::comeFrom() 2311: { 2312: assert(0); 2313: if (body) 2314: return body->comeFrom(); 2315: return FALSE; 2316: } 2317: 2318: void ForeachRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2319: { 2320: buf->writestring(Token::toChars(op)); 2321: buf->writestring(" ("); 2322: 2323: if (arg->type) 2324: arg->type->toCBuffer(buf, arg->ident, hgs); 2325: else 2326: buf->writestring(arg->ident->toChars()); 2327: 2328: buf->writestring("; "); 2329: lwr->toCBuffer(buf, hgs); 2330: buf->writestring(" .. "); 2331: upr->toCBuffer(buf, hgs); 2332: buf->writebyte(')'); 2333: buf->writenl(); 2334: buf->writebyte('{'); 2335: buf->writenl(); 2336: if (body) 2337: body->toCBuffer(buf, hgs); 2338: buf->writebyte('}'); 2339: buf->writenl(); 2340: } 2341: 2342: #endif 2343: 2344: /******************************** IfStatement ***************************/ 2345: 2346: IfStatement::IfStatement(Loc loc, Parameter *arg, Expression *condition, Statement *ifbody, Statement *elsebody) 2347: : Statement(loc) 2348: { 2349: this->arg = arg; 2350: this->condition = condition; 2351: this->ifbody = ifbody; 2352: this->elsebody = elsebody; 2353: this->match = NULL; 2354: } 2355: 2356: Statement *IfStatement::syntaxCopy() 2357: { 2358: Statement *i = NULL; 2359: if (ifbody) 2360: i = ifbody->syntaxCopy(); 2361: 2362: Statement *e = NULL; 2363: if (elsebody) 2364: e = elsebody->syntaxCopy(); 2365: 2366: Parameter *a = arg ? arg->syntaxCopy() : NULL; 2367: IfStatement *s = new IfStatement(loc, a, condition->syntaxCopy(), i, e); 2368: return s; 2369: } 2370: 2371: Statement *IfStatement::semantic(Scope *sc) 2372: { 2373: // Evaluate at runtime 2374: unsigned cs0 = sc->callSuper; 2375: unsigned cs1; 2376: 2377: Scope *scd; 2378: if (arg) 2379: { /* Declare arg, which we will set to be the 2380: * result of condition. 2381: */ 2382: ScopeDsymbol *sym = new ScopeDsymbol(); 2383: sym->parent = sc->scopesym; 2384: scd = sc->push(sym); 2385: 2386: match = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, condition)); 2387: match->parent = sc->func; 2388: 2389: DeclarationExp *de = new DeclarationExp(loc, match);
warning C6211: Leaking memory 'de' due to an exception. Consider using a local catch block to clean up memory: Lines: 2374, 2375, 2377, 2378, 2382, 2383, 2384, 2386, 2387, 2389, 2390
2390: VarExp *ve = new VarExp(0, match); 2391: condition = new CommaExp(loc, de, ve); 2392: condition = condition->semantic(scd); 2393: 2394: if (match->edtor) 2395: { 2396: Statement *sdtor = new ExpStatement(loc, match->edtor); 2397: sdtor = new OnScopeStatement(loc, TOKon_scope_exit, sdtor); 2398: ifbody = new CompoundStatement(loc, sdtor, ifbody); 2399: match->noscope = 1; 2400: } 2401: } 2402: else 2403: { 2404: condition = condition->semantic(sc); 2405: condition = condition->addDtorHook(sc); 2406: condition = resolveProperties(sc, condition); 2407: scd = sc->push(); 2408: } 2409: 2410: // Convert to boolean after declaring arg so this works: 2411: // if (S arg = S()) {} 2412: // where S is a struct that defines opCast!bool. 2413: condition = condition->checkToBoolean(sc); 2414: 2415: // If we can short-circuit evaluate the if statement, don't do the 2416: // semantic analysis of the skipped code. 2417: // This feature allows a limited form of conditional compilation. 2418: condition = condition->optimize(WANTflags); 2419: ifbody = ifbody->semanticNoScope(scd); 2420: scd->pop(); 2421: 2422: cs1 = sc->callSuper; 2423: sc->callSuper = cs0; 2424: if (elsebody) 2425: elsebody = elsebody->semanticScope(sc, NULL, NULL); 2426: sc->mergeCallSuper(loc, cs1); 2427: 2428: return this; 2429: } 2430: 2431: int IfStatement::usesEH() 2432: { 2433: return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH()); 2434: } 2435: 2436: int IfStatement::blockExit(bool mustNotThrow) 2437: { 2438: //printf("IfStatement::blockExit(%p)\n", this); 2439: 2440: int result = BEnone; 2441: if (condition->canThrow(mustNotThrow)) 2442: result |= BEthrow; 2443: if (condition->isBool(TRUE)) 2444: { 2445: if (ifbody) 2446: result |= ifbody->blockExit(mustNotThrow); 2447: else 2448: result |= BEfallthru; 2449: } 2450: else if (condition->isBool(FALSE)) 2451: { 2452: if (elsebody) 2453: result |= elsebody->blockExit(mustNotThrow); 2454: else 2455: result |= BEfallthru; 2456: } 2457: else 2458: { 2459: if (ifbody) 2460: result |= ifbody->blockExit(mustNotThrow); 2461: else 2462: result |= BEfallthru; 2463: if (elsebody) 2464: result |= elsebody->blockExit(mustNotThrow); 2465: else 2466: result |= BEfallthru; 2467: } 2468: //printf("IfStatement::blockExit(%p) = x%x\n", this, result); 2469: return result; 2470: } 2471: 2472: 2473: void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2474: { 2475: buf->writestring("if ("); 2476: if (arg) 2477: { 2478: if (arg->type) 2479: arg->type->toCBuffer(buf, arg->ident, hgs); 2480: else 2481: { buf->writestring("auto "); 2482: buf->writestring(arg->ident->toChars()); 2483: } 2484: buf->writestring(" = "); 2485: } 2486: condition->toCBuffer(buf, hgs); 2487: buf->writebyte(')'); 2488: buf->writenl(); 2489: ifbody->toCBuffer(buf, hgs); 2490: if (elsebody) 2491: { buf->writestring("else"); 2492: buf->writenl(); 2493: elsebody->toCBuffer(buf, hgs); 2494: } 2495: } 2496: 2497: /******************************** ConditionalStatement ***************************/ 2498: 2499: ConditionalStatement::ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody) 2500: : Statement(loc) 2501: { 2502: this->condition = condition; 2503: this->ifbody = ifbody; 2504: this->elsebody = elsebody; 2505: } 2506: 2507: Statement *ConditionalStatement::syntaxCopy() 2508: { 2509: Statement *e = NULL; 2510: if (elsebody) 2511: e = elsebody->syntaxCopy(); 2512: ConditionalStatement *s = new ConditionalStatement(loc, 2513: condition->syntaxCopy(), ifbody->syntaxCopy(), e); 2514: return s; 2515: } 2516: 2517: Statement *ConditionalStatement::semantic(Scope *sc) 2518: { 2519: //printf("ConditionalStatement::semantic()\n"); 2520: 2521: // If we can short-circuit evaluate the if statement, don't do the 2522: // semantic analysis of the skipped code. 2523: // This feature allows a limited form of conditional compilation. 2524: if (condition->include(sc, NULL)) 2525: { 2526: DebugCondition *dc = condition->isDebugCondition(); 2527: if (dc) 2528: { 2529: sc = sc->push(); 2530: sc->flags |= SCOPEdebug; 2531: ifbody = ifbody->semantic(sc); 2532: sc->pop(); 2533: } 2534: else 2535: ifbody = ifbody->semantic(sc); 2536: return ifbody; 2537: } 2538: else 2539: { 2540: if (elsebody) 2541: elsebody = elsebody->semantic(sc); 2542: return elsebody; 2543: } 2544: } 2545: 2546: Statements *ConditionalStatement::flatten(Scope *sc) 2547: { 2548: Statement *s; 2549: 2550: //printf("ConditionalStatement::flatten()\n"); 2551: if (condition->include(sc, NULL)) 2552: { 2553: DebugCondition *dc = condition->isDebugCondition(); 2554: if (dc) 2555: s = new DebugStatement(loc, ifbody);
warning C6211: Leaking memory 's' due to an exception. Consider using a local catch block to clean up memory: Lines: 2548, 2551, 2553, 2554, 2555, 2562
2556: else 2557: s = ifbody; 2558: } 2559: else 2560: s = elsebody; 2561: 2562: Statements *a = new Statements(); 2563: a->push(s); 2564: return a; 2565: } 2566: 2567: int ConditionalStatement::usesEH() 2568: { 2569: return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH()); 2570: } 2571: 2572: int ConditionalStatement::blockExit(bool mustNotThrow) 2573: { 2574: int result = ifbody->blockExit(mustNotThrow); 2575: if (elsebody) 2576: result |= elsebody->blockExit(mustNotThrow); 2577: return result; 2578: } 2579: 2580: void ConditionalStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2581: { 2582: condition->toCBuffer(buf, hgs); 2583: buf->writenl(); 2584: buf->writeByte('{'); 2585: buf->writenl(); 2586: if (ifbody) 2587: ifbody->toCBuffer(buf, hgs); 2588: buf->writeByte('}'); 2589: buf->writenl(); 2590: if (elsebody) 2591: { 2592: buf->writestring("else"); 2593: buf->writenl(); 2594: buf->writeByte('{'); 2595: buf->writenl(); 2596: elsebody->toCBuffer(buf, hgs); 2597: buf->writeByte('}'); 2598: buf->writenl(); 2599: } 2600: buf->writenl(); 2601: } 2602: 2603: 2604: /******************************** PragmaStatement ***************************/ 2605: 2606: PragmaStatement::PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body) 2607: : Statement(loc) 2608: { 2609: this->ident = ident; 2610: this->args = args; 2611: this->body = body; 2612: } 2613: 2614: Statement *PragmaStatement::syntaxCopy() 2615: { 2616: Statement *b = NULL; 2617: if (body) 2618: b = body->syntaxCopy(); 2619: PragmaStatement *s = new PragmaStatement(loc, 2620: ident, Expression::arraySyntaxCopy(args), b); 2621: return s; 2622: } 2623: 2624: Statement *PragmaStatement::semantic(Scope *sc) 2625: { // Should be merged with PragmaDeclaration 2626: //printf("PragmaStatement::semantic() %s\n", toChars()); 2627: //printf("body = %p\n", body); 2628: if (ident == Id::msg) 2629: { 2630: if (args) 2631: { 2632: for (size_t i = 0; i < args->dim; i++) 2633: { 2634: Expression *e = args->tdata()[i]; 2635: 2636: e = e->semantic(sc); 2637: e = e->optimize(WANTvalue | WANTinterpret); 2638: if (e->op == TOKstring) 2639: { 2640: StringExp *se = (StringExp *)e; 2641: fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string); 2642: } 2643: else 2644: fprintf(stdmsg, "%s", e->toChars()); 2645: } 2646: fprintf(stdmsg, "\n"); 2647: } 2648: } 2649: else if (ident == Id::lib) 2650: { 2651: #if 1 2652: /* Should this be allowed? 2653: */ 2654: error("pragma(lib) not allowed as statement"); 2655: #else 2656: if (!args || args->dim != 1) 2657: error("string expected for library name"); 2658: else 2659: { 2660: Expression *e = args->tdata()[0]; 2661: 2662: e = e->semantic(sc); 2663: e = e->optimize(WANTvalue | WANTinterpret); 2664: args->tdata()[0] = e; 2665: if (e->op != TOKstring) 2666: error("string expected for library name, not '%s'", e->toChars()); 2667: else if (global.params.verbose) 2668: { 2669: StringExp *se = (StringExp *)e; 2670: char *name = (char *)mem.malloc(se->len + 1); 2671: memcpy(name, se->string, se->len); 2672: name[se->len] = 0; 2673: printf("library %s\n", name); 2674: mem.free(name); 2675: } 2676: } 2677: #endif 2678: } 2679: #if DMDV2 2680: else if (ident == Id::startaddress) 2681: { 2682: if (!args || args->dim != 1) 2683: error("function name expected for start address"); 2684: else 2685: { 2686: Expression *e = args->tdata()[0]; 2687: e = e->semantic(sc); 2688: e = e->optimize(WANTvalue | WANTinterpret); 2689: args->tdata()[0] = e; 2690: Dsymbol *sa = getDsymbol(e); 2691: if (!sa || !sa->isFuncDeclaration()) 2692: error("function name expected for start address, not '%s'", e->toChars()); 2693: if (body) 2694: { 2695: body = body->semantic(sc); 2696: } 2697: return this; 2698: } 2699: } 2700: #endif 2701: else 2702: error("unrecognized pragma(%s)", ident->toChars()); 2703: 2704: if (body) 2705: { 2706: body = body->semantic(sc); 2707: } 2708: return body; 2709: } 2710: 2711: int PragmaStatement::usesEH() 2712: { 2713: return body && body->usesEH(); 2714: } 2715: 2716: int PragmaStatement::blockExit(bool mustNotThrow) 2717: { 2718: int result = BEfallthru; 2719: #if 0 // currently, no code is generated for Pragma's, so it's just fallthru 2720: if (arrayExpressionCanThrow(args)) 2721: result |= BEthrow; 2722: if (body) 2723: result |= body->blockExit(mustNotThrow); 2724: #endif 2725: return result; 2726: } 2727: 2728: 2729: void PragmaStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2730: { 2731: buf->writestring("pragma ("); 2732: buf->writestring(ident->toChars()); 2733: if (args && args->dim) 2734: { 2735: buf->writestring(", "); 2736: argsToCBuffer(buf, args, hgs); 2737: } 2738: buf->writeByte(')'); 2739: if (body) 2740: { 2741: buf->writenl(); 2742: buf->writeByte('{'); 2743: buf->writenl(); 2744: 2745: body->toCBuffer(buf, hgs); 2746: 2747: buf->writeByte('}'); 2748: buf->writenl(); 2749: } 2750: else 2751: { 2752: buf->writeByte(';'); 2753: buf->writenl(); 2754: } 2755: } 2756: 2757: 2758: /******************************** StaticAssertStatement ***************************/ 2759: 2760: StaticAssertStatement::StaticAssertStatement(StaticAssert *sa) 2761: : Statement(sa->loc) 2762: { 2763: this->sa = sa; 2764: } 2765: 2766: Statement *StaticAssertStatement::syntaxCopy() 2767: { 2768: StaticAssertStatement *s = new StaticAssertStatement((StaticAssert *)sa->syntaxCopy(NULL)); 2769: return s; 2770: } 2771: 2772: Statement *StaticAssertStatement::semantic(Scope *sc) 2773: { 2774: sa->semantic2(sc); 2775: return NULL; 2776: } 2777: 2778: int StaticAssertStatement::blockExit(bool mustNotThrow) 2779: { 2780: return BEfallthru; 2781: } 2782: 2783: void StaticAssertStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2784: { 2785: sa->toCBuffer(buf, hgs); 2786: } 2787: 2788: 2789: /******************************** SwitchStatement ***************************/ 2790: 2791: SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b, bool isFinal) 2792: : Statement(loc) 2793: { 2794: this->condition = c; 2795: this->body = b; 2796: this->isFinal = isFinal; 2797: sdefault = NULL; 2798: tf = NULL; 2799: cases = NULL; 2800: hasNoDefault = 0; 2801: hasVars = 0; 2802: } 2803: 2804: Statement *SwitchStatement::syntaxCopy() 2805: { 2806: SwitchStatement *s = new SwitchStatement(loc, 2807: condition->syntaxCopy(), body->syntaxCopy(), isFinal); 2808: return s; 2809: } 2810: 2811: Statement *SwitchStatement::semantic(Scope *sc) 2812: { 2813: //printf("SwitchStatement::semantic(%p)\n", this); 2814: tf = sc->tf; 2815: assert(!cases); // ensure semantic() is only run once 2816: condition = condition->semantic(sc); 2817: condition = resolveProperties(sc, condition); 2818: if (condition->type->isString()) 2819: { 2820: // If it's not an array, cast it to one 2821: if (condition->type->ty != Tarray) 2822: { 2823: condition = condition->implicitCastTo(sc, condition->type->nextOf()->arrayOf()); 2824: } 2825: condition->type = condition->type->constOf(); 2826: } 2827: else 2828: { condition = condition->integralPromotions(sc); 2829: condition->checkIntegral(); 2830: } 2831: condition = condition->optimize(WANTvalue); 2832: 2833: sc = sc->push(); 2834: sc->sbreak = this; 2835: sc->sw = this; 2836: 2837: cases = new CaseStatements(); 2838: sc->noctor++; // BUG: should use Scope::mergeCallSuper() for each case instead 2839: body = body->semantic(sc); 2840: sc->noctor--; 2841: 2842: // Resolve any goto case's with exp 2843: for (int i = 0; i < gotoCases.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
2844: { 2845: GotoCaseStatement *gcs = gotoCases.tdata()[i]; 2846: 2847: if (!gcs->exp) 2848: { 2849: gcs->error("no case statement following goto case;"); 2850: break; 2851: } 2852: 2853: for (Scope *scx = sc; scx; scx = scx->enclosing) 2854: { 2855: if (!scx->sw) 2856: continue; 2857: for (int j = 0; j < scx->sw->cases->dim; j++)
warning C4018: '<' : signed/unsigned mismatch
2858: { 2859: CaseStatement *cs = scx->sw->cases->tdata()[j]; 2860: 2861: if (cs->exp->equals(gcs->exp)) 2862: { 2863: gcs->cs = cs; 2864: goto Lfoundcase; 2865: } 2866: } 2867: } 2868: gcs->error("case %s not found", gcs->exp->toChars()); 2869: 2870: Lfoundcase: 2871: ; 2872: } 2873: 2874: if (!sc->sw->sdefault && !isFinal) 2875: { hasNoDefault = 1; 2876: 2877: if (!global.params.useDeprecated) 2878: error("non-final switch statement without a default is deprecated"); 2879: 2880: // Generate runtime error if the default is hit 2881: Statements *a = new Statements();
warning C6211: Leaking memory 'a' due to an exception. Consider using a local catch block to clean up memory: Lines: 2814, 2815, 2816, 2817, 2818, 2821, 2825, 2831, 2833, 2834, 2835, 2837, 2838, 2839, 2840, 2843, 2874, 2875, 2877, 2878, 2881, 2882, 2883, 2885, 2886
2882: CompoundStatement *cs; 2883: Statement *s; 2884: 2885: if (global.params.useSwitchError) 2886: s = new SwitchErrorStatement(loc);
warning C6211: Leaking memory 's' due to an exception. Consider using a local catch block to clean up memory: Lines: 2814, 2815, 2816, 2817, 2818, 2821, 2825, 2831, 2833, 2834, 2835, 2837, 2838, 2839, 2840, 2843, 2874, 2875, 2877, 2878, 2881, 2882, 2883, 2885, 2886, 2892, 2893, 2894
2887: else 2888: { Expression *e = new HaltExp(loc); 2889: s = new ExpStatement(loc, e); 2890: } 2891: 2892: a->reserve(4); 2893: a->push(body); 2894: a->push(new BreakStatement(loc, NULL)); 2895: sc->sw->sdefault = new DefaultStatement(loc, s); 2896: a->push(sc->sw->sdefault); 2897: cs = new CompoundStatement(loc, a); 2898: body = cs; 2899: } 2900: 2901: #if DMDV2 2902: if (isFinal) 2903: { Type *t = condition->type; 2904: while (t->ty == Ttypedef) 2905: { // Don't use toBasetype() because that will skip past enums 2906: t = ((TypeTypedef *)t)->sym->basetype; 2907: } 2908: if (condition->type->ty == Tenum) 2909: { TypeEnum *te = (TypeEnum *)condition->type; 2910: EnumDeclaration *ed = te->toDsymbol(sc)->isEnumDeclaration(); 2911: assert(ed); 2912: size_t dim = ed->members->dim; 2913: for (size_t i = 0; i < dim; i++) 2914: { 2915: EnumMember *em = ed->members->tdata()[i]->isEnumMember(); 2916: if (em) 2917: { 2918: for (size_t j = 0; j < cases->dim; j++) 2919: { CaseStatement *cs = cases->tdata()[j]; 2920: if (cs->exp->equals(em->value)) 2921: goto L1; 2922: } 2923: error("enum member %s not represented in final switch", em->toChars()); 2924: } 2925: L1: 2926: ; 2927: } 2928: } 2929: } 2930: #endif 2931: 2932: sc->pop(); 2933: return this; 2934: } 2935: 2936: int SwitchStatement::hasBreak() 2937: { 2938: return TRUE; 2939: } 2940: 2941: int SwitchStatement::usesEH() 2942: { 2943: return body ? body->usesEH() : 0; 2944: } 2945: 2946: int SwitchStatement::blockExit(bool mustNotThrow) 2947: { int result = BEnone; 2948: if (condition->canThrow(mustNotThrow)) 2949: result |= BEthrow; 2950: 2951: if (body) 2952: { result |= body->blockExit(mustNotThrow); 2953: if (result & BEbreak) 2954: { result |= BEfallthru; 2955: result &= ~BEbreak; 2956: } 2957: } 2958: else 2959: result |= BEfallthru; 2960: 2961: return result; 2962: } 2963: 2964: 2965: void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 2966: { 2967: buf->writestring(isFinal ? "final switch (" : "switch ("); 2968: condition->toCBuffer(buf, hgs); 2969: buf->writebyte(')'); 2970: buf->writenl(); 2971: if (body) 2972: { 2973: if (!body->isScopeStatement()) 2974: { buf->writebyte('{'); 2975: buf->writenl(); 2976: body->toCBuffer(buf, hgs); 2977: buf->writebyte('}'); 2978: buf->writenl(); 2979: } 2980: else 2981: { 2982: body->toCBuffer(buf, hgs); 2983: } 2984: } 2985: } 2986: 2987: /******************************** CaseStatement ***************************/ 2988: 2989: CaseStatement::CaseStatement(Loc loc, Expression *exp, Statement *s) 2990: : Statement(loc) 2991: { 2992: this->exp = exp; 2993: this->statement = s; 2994: index = 0; 2995: cblock = NULL; 2996: } 2997: 2998: Statement *CaseStatement::syntaxCopy() 2999: { 3000: CaseStatement *s = new CaseStatement(loc, exp->syntaxCopy(), statement->syntaxCopy()); 3001: return s; 3002: } 3003: 3004: Statement *CaseStatement::semantic(Scope *sc) 3005: { SwitchStatement *sw = sc->sw; 3006: 3007: //printf("CaseStatement::semantic() %s\n", toChars()); 3008: exp = exp->semantic(sc); 3009: if (sw) 3010: { 3011: exp = exp->implicitCastTo(sc, sw->condition->type); 3012: exp = exp->optimize(WANTvalue); 3013: 3014: /* This is where variables are allowed as case expressions. 3015: */ 3016: if (exp->op == TOKvar) 3017: { VarExp *ve = (VarExp *)exp; 3018: VarDeclaration *v = ve->var->isVarDeclaration(); 3019: Type *t = exp->type->toBasetype(); 3020: if (v && (t->isintegral() || t->ty == Tclass)) 3021: { /* Flag that we need to do special code generation 3022: * for this, i.e. generate a sequence of if-then-else 3023: */ 3024: sw->hasVars = 1; 3025: if (sw->isFinal) 3026: error("case variables not allowed in final switch statements"); 3027: goto L1; 3028: } 3029: } 3030: else 3031: exp = exp->optimize(WANTvalue | WANTinterpret); 3032: 3033: if (exp->op != TOKstring && exp->op != TOKint64 && exp->op != TOKerror) 3034: { 3035: error("case must be a string or an integral constant, not %s", exp->toChars()); 3036: exp = new IntegerExp(0); 3037: } 3038: 3039: L1: 3040: for (int i = 0; i < sw->cases->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
3041: { 3042: CaseStatement *cs = sw->cases->tdata()[i]; 3043: 3044: //printf("comparing '%s' with '%s'\n", exp->toChars(), cs->exp->toChars()); 3045: if (cs->exp->equals(exp)) 3046: { error("duplicate case %s in switch statement", exp->toChars()); 3047: break; 3048: } 3049: } 3050: 3051: sw->cases->push(this); 3052: 3053: // Resolve any goto case's with no exp to this case statement 3054: for (int i = 0; i < sw->gotoCases.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
3055: { 3056: GotoCaseStatement *gcs = sw->gotoCases.tdata()[i]; 3057: 3058: if (!gcs->exp) 3059: { 3060: gcs->cs = this; 3061: sw->gotoCases.remove(i); // remove from array 3062: } 3063: } 3064: 3065: if (sc->sw->tf != sc->tf) 3066: error("switch and case are in different finally blocks"); 3067: } 3068: else 3069: error("case not in switch statement"); 3070: statement = statement->semantic(sc); 3071: return this; 3072: } 3073: 3074: int CaseStatement::compare(Object *obj) 3075: { 3076: // Sort cases so we can do an efficient lookup 3077: CaseStatement *cs2 = (CaseStatement *)(obj); 3078: 3079: return exp->compare(cs2->exp); 3080: } 3081: 3082: int CaseStatement::usesEH() 3083: { 3084: return statement->usesEH(); 3085: } 3086: 3087: int CaseStatement::blockExit(bool mustNotThrow) 3088: { 3089: return statement->blockExit(mustNotThrow); 3090: } 3091: 3092: 3093: int CaseStatement::comeFrom() 3094: { 3095: return TRUE; 3096: } 3097: 3098: void CaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3099: { 3100: buf->writestring("case "); 3101: exp->toCBuffer(buf, hgs); 3102: buf->writebyte(':'); 3103: buf->writenl(); 3104: statement->toCBuffer(buf, hgs); 3105: } 3106: 3107: /******************************** CaseRangeStatement ***************************/ 3108: 3109: #if DMDV2 3110: 3111: CaseRangeStatement::CaseRangeStatement(Loc loc, Expression *first, 3112: Expression *last, Statement *s) 3113: : Statement(loc) 3114: { 3115: this->first = first; 3116: this->last = last; 3117: this->statement = s; 3118: } 3119: 3120: Statement *CaseRangeStatement::syntaxCopy() 3121: { 3122: CaseRangeStatement *s = new CaseRangeStatement(loc, 3123: first->syntaxCopy(), last->syntaxCopy(), statement->syntaxCopy()); 3124: return s; 3125: } 3126: 3127: Statement *CaseRangeStatement::semantic(Scope *sc) 3128: { SwitchStatement *sw = sc->sw; 3129: 3130: //printf("CaseRangeStatement::semantic() %s\n", toChars()); 3131: if (sw->isFinal) 3132: error("case ranges not allowed in final switch"); 3133: 3134: first = first->semantic(sc); 3135: first = first->implicitCastTo(sc, sw->condition->type); 3136: first = first->optimize(WANTvalue | WANTinterpret); 3137: 3138: 3139: last = last->semantic(sc); 3140: last = last->implicitCastTo(sc, sw->condition->type); 3141: last = last->optimize(WANTvalue | WANTinterpret); 3142: 3143: if (first->op == TOKerror || last->op == TOKerror) 3144: return statement ? statement->semantic(sc) : NULL; 3145: 3146: uinteger_t fval = first->toInteger(); 3147: uinteger_t lval = last->toInteger(); 3148: 3149: 3150: if ( (first->type->isunsigned() && fval > lval) || 3151: (!first->type->isunsigned() && (sinteger_t)fval > (sinteger_t)lval)) 3152: { 3153: error("first case %s is greater than last case %s", 3154: first->toChars(), last->toChars()); 3155: lval = fval; 3156: } 3157: 3158: if (lval - fval > 256) 3159: { error("had %llu cases which is more than 256 cases in case range", lval - fval); 3160: lval = fval + 256; 3161: } 3162: 3163: /* This works by replacing the CaseRange with an array of Case's. 3164: * 3165: * case a: .. case b: s; 3166: * => 3167: * case a: 3168: * [...] 3169: * case b: 3170: * s; 3171: */ 3172: 3173: Statements *statements = new Statements();
warning C6211: Leaking memory 'statements' due to an exception. Consider using a local catch block to clean up memory: Lines: 3128, 3131, 3132, 3134, 3135, 3136, 3139, 3140, 3141, 3143, 3146, 3147, 3150, 3158, 3173, 3174, 3176, 3177, 3179
3174: for (uinteger_t i = fval; i != lval + 1; i++) 3175: { 3176: Statement *s = statement; 3177: if (i != lval) // if not last case 3178: s = new ExpStatement(loc, (Expression *)NULL); 3179: Expression *e = new IntegerExp(loc, i, first->type); 3180: Statement *cs = new CaseStatement(loc, e, s); 3181: statements->push(cs); 3182: } 3183: Statement *s = new CompoundStatement(loc, statements); 3184: s = s->semantic(sc); 3185: return s; 3186: } 3187: 3188: void CaseRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3189: { 3190: buf->writestring("case "); 3191: first->toCBuffer(buf, hgs); 3192: buf->writestring(": .. case "); 3193: last->toCBuffer(buf, hgs); 3194: buf->writebyte(':'); 3195: buf->writenl(); 3196: statement->toCBuffer(buf, hgs); 3197: } 3198: 3199: #endif 3200: 3201: /******************************** DefaultStatement ***************************/ 3202: 3203: DefaultStatement::DefaultStatement(Loc loc, Statement *s) 3204: : Statement(loc) 3205: { 3206: this->statement = s; 3207: #if IN_GCC 3208: + cblock = NULL; 3209: #endif 3210: } 3211: 3212: Statement *DefaultStatement::syntaxCopy() 3213: { 3214: DefaultStatement *s = new DefaultStatement(loc, statement->syntaxCopy()); 3215: return s; 3216: } 3217: 3218: Statement *DefaultStatement::semantic(Scope *sc) 3219: { 3220: //printf("DefaultStatement::semantic()\n"); 3221: if (sc->sw) 3222: { 3223: if (sc->sw->sdefault) 3224: { 3225: error("switch statement already has a default"); 3226: } 3227: sc->sw->sdefault = this; 3228: 3229: if (sc->sw->tf != sc->tf) 3230: error("switch and default are in different finally blocks"); 3231: 3232: if (sc->sw->isFinal) 3233: error("default statement not allowed in final switch statement"); 3234: } 3235: else 3236: error("default not in switch statement"); 3237: statement = statement->semantic(sc); 3238: return this; 3239: } 3240: 3241: int DefaultStatement::usesEH() 3242: { 3243: return statement->usesEH(); 3244: } 3245: 3246: int DefaultStatement::blockExit(bool mustNotThrow) 3247: { 3248: return statement->blockExit(mustNotThrow); 3249: } 3250: 3251: 3252: int DefaultStatement::comeFrom() 3253: { 3254: return TRUE; 3255: } 3256: 3257: void DefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3258: { 3259: buf->writestring("default:\n"); 3260: statement->toCBuffer(buf, hgs); 3261: } 3262: 3263: /******************************** GotoDefaultStatement ***************************/ 3264: 3265: GotoDefaultStatement::GotoDefaultStatement(Loc loc) 3266: : Statement(loc) 3267: { 3268: sw = NULL; 3269: } 3270: 3271: Statement *GotoDefaultStatement::syntaxCopy() 3272: { 3273: GotoDefaultStatement *s = new GotoDefaultStatement(loc); 3274: return s; 3275: } 3276: 3277: Statement *GotoDefaultStatement::semantic(Scope *sc) 3278: { 3279: sw = sc->sw; 3280: if (!sw) 3281: error("goto default not in switch statement"); 3282: return this; 3283: } 3284: 3285: int GotoDefaultStatement::blockExit(bool mustNotThrow) 3286: { 3287: return BEgoto; 3288: } 3289: 3290: 3291: void GotoDefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3292: { 3293: buf->writestring("goto default;\n"); 3294: } 3295: 3296: /******************************** GotoCaseStatement ***************************/ 3297: 3298: GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp) 3299: : Statement(loc) 3300: { 3301: cs = NULL; 3302: this->exp = exp; 3303: } 3304: 3305: Statement *GotoCaseStatement::syntaxCopy() 3306: { 3307: Expression *e = exp ? exp->syntaxCopy() : NULL; 3308: GotoCaseStatement *s = new GotoCaseStatement(loc, e); 3309: return s; 3310: } 3311: 3312: Statement *GotoCaseStatement::semantic(Scope *sc) 3313: { 3314: if (exp) 3315: exp = exp->semantic(sc); 3316: 3317: if (!sc->sw) 3318: error("goto case not in switch statement"); 3319: else 3320: { 3321: sc->sw->gotoCases.push(this); 3322: if (exp) 3323: { 3324: exp = exp->implicitCastTo(sc, sc->sw->condition->type); 3325: exp = exp->optimize(WANTvalue); 3326: } 3327: } 3328: return this; 3329: } 3330: 3331: int GotoCaseStatement::blockExit(bool mustNotThrow) 3332: { 3333: return BEgoto; 3334: } 3335: 3336: 3337: void GotoCaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3338: { 3339: buf->writestring("goto case"); 3340: if (exp) 3341: { buf->writebyte(' '); 3342: exp->toCBuffer(buf, hgs); 3343: } 3344: buf->writebyte(';'); 3345: buf->writenl(); 3346: } 3347: 3348: /******************************** SwitchErrorStatement ***************************/ 3349: 3350: SwitchErrorStatement::SwitchErrorStatement(Loc loc) 3351: : Statement(loc) 3352: { 3353: } 3354: 3355: int SwitchErrorStatement::blockExit(bool mustNotThrow) 3356: { 3357: // Switch errors are non-recoverable 3358: return BEhalt; 3359: } 3360: 3361: 3362: void SwitchErrorStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3363: { 3364: buf->writestring("SwitchErrorStatement::toCBuffer()"); 3365: buf->writenl(); 3366: } 3367: 3368: /******************************** ReturnStatement ***************************/ 3369: 3370: ReturnStatement::ReturnStatement(Loc loc, Expression *exp) 3371: : Statement(loc) 3372: { 3373: this->exp = exp; 3374: } 3375: 3376: Statement *ReturnStatement::syntaxCopy() 3377: { 3378: Expression *e = NULL; 3379: if (exp) 3380: e = exp->syntaxCopy(); 3381: ReturnStatement *s = new ReturnStatement(loc, e); 3382: return s; 3383: } 3384: 3385: Statement *ReturnStatement::semantic(Scope *sc) 3386: { 3387: //printf("ReturnStatement::semantic() %s\n", toChars()); 3388: 3389: FuncDeclaration *fd = sc->parent->isFuncDeclaration(); 3390: Scope *scx = sc; 3391: int implicit0 = 0; 3392: 3393: if (sc->fes) 3394: { 3395: // Find scope of function foreach is in 3396: for (; 1; scx = scx->enclosing) 3397: { 3398: assert(scx); 3399: if (scx->func != fd) 3400: { fd = scx->func; // fd is now function enclosing foreach 3401: break; 3402: } 3403: } 3404: } 3405: 3406: Type *tret = fd->type->nextOf(); 3407: if (fd->tintro) 3408: /* We'll be implicitly casting the return expression to tintro 3409: */ 3410: tret = fd->tintro->nextOf(); 3411: Type *tbret = NULL; 3412: 3413: if (tret) 3414: tbret = tret->toBasetype(); 3415: 3416: // main() returns 0, even if it returns void 3417: if (!exp && (!tbret || tbret->ty == Tvoid) && fd->isMain()) 3418: { implicit0 = 1; 3419: exp = new IntegerExp(0); 3420: } 3421: 3422: if (sc->incontract || scx->incontract) 3423: error("return statements cannot be in contracts"); 3424: if (sc->tf || scx->tf) 3425: error("return statements cannot be in finally, scope(exit) or scope(success) bodies"); 3426: 3427: if (fd->isCtorDeclaration()) 3428: { 3429: // Constructors implicitly do: 3430: // return this; 3431: if (exp && exp->op != TOKthis) 3432: error("cannot return expression from constructor"); 3433: exp = new ThisExp(0); 3434: exp->type = tret; 3435: } 3436: 3437: if (!exp) 3438: fd->nrvo_can = 0; 3439: 3440: if (exp) 3441: { 3442: fd->hasReturnExp |= 1; 3443: 3444: exp = exp->semantic(sc); 3445: exp = resolveProperties(sc, exp); 3446: if (!((TypeFunction *)fd->type)->isref) 3447: exp = exp->optimize(WANTvalue); 3448: 3449: if (fd->nrvo_can && exp->op == TOKvar) 3450: { VarExp *ve = (VarExp *)exp; 3451: VarDeclaration *v = ve->var->isVarDeclaration(); 3452: 3453: if (((TypeFunction *)fd->type)->isref) 3454: // Function returns a reference 3455: fd->nrvo_can = 0; 3456: else if (!v || v->isOut() || v->isRef()) 3457: fd->nrvo_can = 0; 3458: // else if (tbret->ty == Tstruct && ((TypeStruct *)tbret)->sym->dtor) 3459: // // Struct being returned has destructors 3460: // fd->nrvo_can = 0; 3461: else if (fd->nrvo_var == NULL) 3462: { if (!v->isDataseg() && !v->isParameter() && v->toParent2() == fd) 3463: { //printf("Setting nrvo to %s\n", v->toChars()); 3464: fd->nrvo_var = v; 3465: } 3466: else 3467: fd->nrvo_can = 0; 3468: } 3469: else if (fd->nrvo_var != v) 3470: fd->nrvo_can = 0; 3471: } 3472: else 3473: fd->nrvo_can = 0; 3474: 3475: if (fd->returnLabel && tbret->ty != Tvoid) 3476: { 3477: } 3478: else if (fd->inferRetType) 3479: { TypeFunction *tf = (TypeFunction *)fd->type; 3480: assert(tf->ty == Tfunction); 3481: Type *tfret = tf->nextOf(); 3482: if (tfret) 3483: { 3484: if (tfret != Type::terror && !exp->type->equals(tfret)) 3485: error("mismatched function return type inference of %s and %s", 3486: exp->type->toChars(), tfret->toChars()); 3487: 3488: /* The "refness" is determined by the first return statement, 3489: * not all of them. This means: 3490: * return 3; return x; // ok, x can be a value 3491: * return x; return 3; // error, 3 is not an lvalue 3492: */ 3493: } 3494: else 3495: { 3496: if (tf->isref) 3497: { /* Determine "refness" of function return: 3498: * if it's an lvalue, return by ref, else return by value 3499: */ 3500: if (exp->isLvalue()) 3501: { 3502: /* Return by ref 3503: * (but first ensure it doesn't fail the "check for 3504: * escaping reference" test) 3505: */ 3506: unsigned errors = global.errors; 3507: global.gag++; 3508: exp->checkEscapeRef(); 3509: global.gag--; 3510: if (errors != global.errors) 3511: { tf->isref = FALSE; // return by value 3512: global.errors = errors; 3513: } 3514: } 3515: else 3516: tf->isref = FALSE; // return by value 3517: } 3518: tf->next = exp->type; 3519: fd->type = tf->semantic(loc, sc); 3520: if (!fd->tintro) 3521: { tret = fd->type->nextOf(); 3522: tbret = tret->toBasetype(); 3523: } 3524: } 3525: } 3526: else if (tbret->ty != Tvoid) 3527: { 3528: exp = exp->implicitCastTo(sc, tret); 3529: if (!((TypeFunction *)fd->type)->isref) 3530: exp = exp->optimize(WANTvalue); 3531: } 3532: } 3533: else if (fd->inferRetType) 3534: { 3535: if (fd->type->nextOf()) 3536: { 3537: if (fd->type->nextOf()->ty != Tvoid) 3538: error("mismatched function return type inference of void and %s", 3539: fd->type->nextOf()->toChars()); 3540: } 3541: else 3542: { 3543: ((TypeFunction *)fd->type)->next = Type::tvoid; 3544: fd->type = fd->type->semantic(loc, sc); 3545: if (!fd->tintro) 3546: { tret = Type::tvoid; 3547: tbret = tret; 3548: } 3549: } 3550: } 3551: else if (tbret->ty != Tvoid) // if non-void return 3552: error("return expression expected"); 3553: 3554: if (sc->fes) 3555: { 3556: Statement *s; 3557: 3558: if (exp && !implicit0) 3559: { 3560: exp = exp->implicitCastTo(sc, tret); 3561: } 3562: if (!exp || exp->op == TOKint64 || exp->op == TOKfloat64 || 3563: exp->op == TOKimaginary80 || exp->op == TOKcomplex80 || 3564: exp->op == TOKthis || exp->op == TOKsuper || exp->op == TOKnull || 3565: exp->op == TOKstring) 3566: { 3567: sc->fes->cases->push(this); 3568: // Construct: return cases->dim+1; 3569: s = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1)); 3570: } 3571: else if (fd->type->nextOf()->toBasetype() == Type::tvoid) 3572: { 3573: s = new ReturnStatement(0, NULL); 3574: sc->fes->cases->push(s); 3575: 3576: // Construct: { exp; return cases->dim + 1; } 3577: Statement *s1 = new ExpStatement(loc, exp); 3578: Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1)); 3579: s = new CompoundStatement(loc, s1, s2); 3580: } 3581: else 3582: { 3583: // Construct: return vresult; 3584: if (!fd->vresult) 3585: { // Declare vresult 3586: VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL); 3587: v->noscope = 1; 3588: v->storage_class |= STCresult; 3589: v->semantic(scx); 3590: if (!scx->insert(v)) 3591: assert(0); 3592: v->parent = fd; 3593: fd->vresult = v; 3594: } 3595: 3596: s = new ReturnStatement(0, new VarExp(0, fd->vresult)); 3597: sc->fes->cases->push(s); 3598: 3599: // Construct: { vresult = exp; return cases->dim + 1; } 3600: exp = new ConstructExp(loc, new VarExp(0, fd->vresult), exp); 3601: exp = exp->semantic(sc); 3602: Statement *s1 = new ExpStatement(loc, exp); 3603: Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1)); 3604: s = new CompoundStatement(loc, s1, s2); 3605: } 3606: return s; 3607: } 3608: 3609: if (exp) 3610: { 3611: if (((TypeFunction *)fd->type)->isref && !fd->isCtorDeclaration()) 3612: { // Function returns a reference 3613: if (tbret->isMutable()) 3614: exp = exp->modifiableLvalue(sc, exp); 3615: else 3616: exp = exp->toLvalue(sc, exp); 3617: 3618: exp->checkEscapeRef(); 3619: } 3620: else 3621: { 3622: //exp->dump(0); 3623: //exp->print(); 3624: exp->checkEscape(); 3625: } 3626: 3627: if (fd->returnLabel && tbret->ty != Tvoid) 3628: { 3629: assert(fd->vresult); 3630: VarExp *v = new VarExp(0, fd->vresult); 3631: 3632: exp = new ConstructExp(loc, v, exp); 3633: exp = exp->semantic(sc); 3634: } 3635: } 3636: 3637: /* BUG: need to issue an error on: 3638: * this 3639: * { if (x) return; 3640: * super(); 3641: * } 3642: */ 3643: 3644: if (sc->callSuper & CSXany_ctor && 3645: !(sc->callSuper & (CSXthis_ctor | CSXsuper_ctor))) 3646: error("return without calling constructor"); 3647: 3648: sc->callSuper |= CSXreturn; 3649: 3650: // See if all returns are instead to be replaced with a goto returnLabel; 3651: if (fd->returnLabel) 3652: { 3653: GotoStatement *gs = new GotoStatement(loc, Id::returnLabel);
warning C6211: Leaking memory 'gs' due to an exception. Consider using a local catch block to clean up memory: Lines: 3389, 3390, 3391, 3393, 3406, 3407, 3410, 3411, 3413, 3414, 3417, 3418, 3419, 3422, 3424, 3427, 3431, 3433, 3434, 3437, 3440, 3442, 3444, 3445, 3446, 3447, 3449, 3473, 3475, 3478, 3479, 3480, 3481, 3482, 3484, 3554, 3609, 3611, 3624, 3627, 3644, 3648, 3651, 3653, 3655, 3656, 3660
3654: 3655: gs->label = fd->returnLabel; 3656: if (exp) 3657: { /* Replace: return exp; 3658: * with: exp; goto returnLabel; 3659: */ 3660: Statement *s = new ExpStatement(0, exp); 3661: return new CompoundStatement(loc, s, gs); 3662: } 3663: return gs; 3664: } 3665: 3666: if (exp && tbret->ty == Tvoid && !implicit0)
warning C6011: Dereferencing NULL pointer 'tbret': Lines: 3389, 3390, 3391, 3393, 3406, 3407, 3410, 3411, 3413, 3414, 3417, 3418, 3419, 3422, 3424, 3427, 3431, 3433, 3434, 3437, 3440, 3442, 3444, 3445, 3446, 3447, 3449, 3473, 3475, 3478, 3479, 3480, 3481, 3482, 3484, 3554, 3609, 3611, 3624, 3627, 3644, 3648, 3651, 3666
3667: { 3668: /* Replace: 3669: * return exp; 3670: * with: 3671: * exp; return; 3672: */ 3673: Statement *s = new ExpStatement(loc, exp); 3674: exp = NULL; 3675: s = s->semantic(sc); 3676: return new CompoundStatement(loc, s, this); 3677: } 3678: 3679: if (exp) 3680: { if (exp->op == TOKcall) 3681: valueNoDtor(exp); 3682: else 3683: { 3684: Expression *e = exp->isTemp(); 3685: if (e) 3686: exp = e; // don't need temporary 3687: } 3688: } 3689: 3690: return this; 3691: } 3692: 3693: int ReturnStatement::blockExit(bool mustNotThrow) 3694: { int result = BEreturn; 3695: 3696: if (exp && exp->canThrow(mustNotThrow)) 3697: result |= BEthrow; 3698: return result; 3699: } 3700: 3701: 3702: void ReturnStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3703: { 3704: buf->printf("return "); 3705: if (exp) 3706: exp->toCBuffer(buf, hgs); 3707: buf->writeByte(';'); 3708: buf->writenl(); 3709: } 3710: 3711: /******************************** BreakStatement ***************************/ 3712: 3713: BreakStatement::BreakStatement(Loc loc, Identifier *ident) 3714: : Statement(loc) 3715: { 3716: this->ident = ident; 3717: } 3718: 3719: Statement *BreakStatement::syntaxCopy() 3720: { 3721: BreakStatement *s = new BreakStatement(loc, ident); 3722: return s; 3723: } 3724: 3725: Statement *BreakStatement::semantic(Scope *sc) 3726: { 3727: //printf("BreakStatement::semantic()\n"); 3728: // If: 3729: // break Identifier; 3730: if (ident) 3731: { 3732: Scope *scx; 3733: FuncDeclaration *thisfunc = sc->func; 3734: 3735: for (scx = sc; scx; scx = scx->enclosing) 3736: { 3737: LabelStatement *ls; 3738: 3739: if (scx->func != thisfunc) // if in enclosing function 3740: { 3741: if (sc->fes) // if this is the body of a foreach 3742: { 3743: /* Post this statement to the fes, and replace 3744: * it with a return value that caller will put into 3745: * a switch. Caller will figure out where the break 3746: * label actually is. 3747: * Case numbers start with 2, not 0, as 0 is continue 3748: * and 1 is break. 3749: */ 3750: Statement *s; 3751: sc->fes->cases->push(this); 3752: s = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1)); 3753: return s; 3754: } 3755: break; // can't break to it 3756: } 3757: 3758: ls = scx->slabel; 3759: if (ls && ls->ident == ident) 3760: { 3761: Statement *s = ls->statement; 3762: 3763: if (!s->hasBreak()) 3764: error("label '%s' has no break", ident->toChars()); 3765: if (ls->tf != sc->tf) 3766: error("cannot break out of finally block"); 3767: return this; 3768: } 3769: } 3770: error("enclosing label '%s' for break not found", ident->toChars()); 3771: } 3772: else if (!sc->sbreak) 3773: { 3774: if (sc->fes) 3775: { Statement *s; 3776: 3777: // Replace break; with return 1; 3778: s = new ReturnStatement(0, new IntegerExp(1)); 3779: return s; 3780: } 3781: error("break is not inside a loop or switch"); 3782: } 3783: return this; 3784: } 3785: 3786: int BreakStatement::blockExit(bool mustNotThrow) 3787: { 3788: //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak); 3789: return ident ? BEgoto : BEbreak; 3790: } 3791: 3792: 3793: void BreakStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3794: { 3795: buf->writestring("break"); 3796: if (ident) 3797: { buf->writebyte(' '); 3798: buf->writestring(ident->toChars()); 3799: } 3800: buf->writebyte(';'); 3801: buf->writenl(); 3802: } 3803: 3804: /******************************** ContinueStatement ***************************/ 3805: 3806: ContinueStatement::ContinueStatement(Loc loc, Identifier *ident) 3807: : Statement(loc) 3808: { 3809: this->ident = ident; 3810: } 3811: 3812: Statement *ContinueStatement::syntaxCopy() 3813: { 3814: ContinueStatement *s = new ContinueStatement(loc, ident); 3815: return s; 3816: } 3817: 3818: Statement *ContinueStatement::semantic(Scope *sc) 3819: { 3820: //printf("ContinueStatement::semantic() %p\n", this); 3821: if (ident) 3822: { 3823: Scope *scx; 3824: FuncDeclaration *thisfunc = sc->func; 3825: 3826: for (scx = sc; scx; scx = scx->enclosing) 3827: { 3828: LabelStatement *ls; 3829: 3830: if (scx->func != thisfunc) // if in enclosing function 3831: { 3832: if (sc->fes) // if this is the body of a foreach 3833: { 3834: for (; scx; scx = scx->enclosing) 3835: { 3836: ls = scx->slabel; 3837: if (ls && ls->ident == ident && ls->statement == sc->fes) 3838: { 3839: // Replace continue ident; with return 0; 3840: return new ReturnStatement(0, new IntegerExp(0)); 3841: } 3842: } 3843: 3844: /* Post this statement to the fes, and replace 3845: * it with a return value that caller will put into 3846: * a switch. Caller will figure out where the break 3847: * label actually is. 3848: * Case numbers start with 2, not 0, as 0 is continue 3849: * and 1 is break. 3850: */ 3851: Statement *s; 3852: sc->fes->cases->push(this); 3853: s = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1)); 3854: return s; 3855: } 3856: break; // can't continue to it 3857: } 3858: 3859: ls = scx->slabel; 3860: if (ls && ls->ident == ident) 3861: { 3862: Statement *s = ls->statement; 3863: 3864: if (!s->hasContinue()) 3865: error("label '%s' has no continue", ident->toChars()); 3866: if (ls->tf != sc->tf) 3867: error("cannot continue out of finally block"); 3868: return this; 3869: } 3870: } 3871: error("enclosing label '%s' for continue not found", ident->toChars()); 3872: } 3873: else if (!sc->scontinue) 3874: { 3875: if (sc->fes) 3876: { Statement *s; 3877: 3878: // Replace continue; with return 0; 3879: s = new ReturnStatement(0, new IntegerExp(0)); 3880: return s; 3881: } 3882: error("continue is not inside a loop"); 3883: } 3884: return this; 3885: } 3886: 3887: int ContinueStatement::blockExit(bool mustNotThrow) 3888: { 3889: return ident ? BEgoto : BEcontinue; 3890: } 3891: 3892: 3893: void ContinueStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 3894: { 3895: buf->writestring("continue"); 3896: if (ident) 3897: { buf->writebyte(' '); 3898: buf->writestring(ident->toChars()); 3899: } 3900: buf->writebyte(';'); 3901: buf->writenl(); 3902: } 3903: 3904: /******************************** SynchronizedStatement ***************************/ 3905: 3906: SynchronizedStatement::SynchronizedStatement(Loc loc, Expression *exp, Statement *body) 3907: : Statement(loc) 3908: { 3909: this->exp = exp; 3910: this->body = body; 3911: this->esync = NULL; 3912: } 3913: 3914: SynchronizedStatement::SynchronizedStatement(Loc loc, elem *esync, Statement *body) 3915: : Statement(loc) 3916: { 3917: this->exp = NULL; 3918: this->body = body; 3919: this->esync = esync; 3920: } 3921: 3922: Statement *SynchronizedStatement::syntaxCopy() 3923: { 3924: Expression *e = exp ? exp->syntaxCopy() : NULL; 3925: SynchronizedStatement *s = new SynchronizedStatement(loc, e, body ? body->syntaxCopy() : NULL); 3926: return s; 3927: } 3928: 3929: Statement *SynchronizedStatement::semantic(Scope *sc) 3930: { 3931: if (exp) 3932: { 3933: exp = exp->semantic(sc); 3934: exp = resolveProperties(sc, exp); 3935: ClassDeclaration *cd = exp->type->isClassHandle(); 3936: if (!cd) 3937: error("can only synchronize on class objects, not '%s'", exp->type->toChars()); 3938: else if (cd->isInterfaceDeclaration()) 3939: { /* Cast the interface to an object, as the object has the monitor, 3940: * not the interface. 3941: */ 3942: Type *t = new TypeIdentifier(0, Id::Object);
warning C6211: Leaking memory 't' due to an exception. Consider using a local catch block to clean up memory: Lines: 3931, 3933, 3934, 3935, 3936, 3938, 3942, 3944, 3945
3943: 3944: t = t->semantic(0, sc); 3945: exp = new CastExp(loc, exp, t); 3946: exp = exp->semantic(sc); 3947: } 3948: 3949: #if 1 3950: /* Rewrite as: 3951: * auto tmp = exp; 3952: * _d_monitorenter(tmp); 3953: * try { body } finally { _d_monitorexit(tmp); } 3954: */ 3955: Identifier *id = Lexer::uniqueId("__sync"); 3956: ExpInitializer *ie = new ExpInitializer(loc, exp); 3957: VarDeclaration *tmp = new VarDeclaration(loc, exp->type, id, ie);
warning C6211: Leaking memory 'tmp' due to an exception. Consider using a local catch block to clean up memory: Lines: 3931, 3933, 3934, 3935, 3936, 3937, 3955, 3956, 3957, 3959
3958: 3959: Statements *cs = new Statements();
warning C6211: Leaking memory 'cs' due to an exception. Consider using a local catch block to clean up memory: Lines: 3931, 3933, 3934, 3935, 3936, 3937, 3955, 3956, 3957, 3959, 3960
3960: cs->push(new ExpStatement(loc, tmp)); 3961: 3962: FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::monitorenter); 3963: Expression *e = new CallExp(loc, new VarExp(loc, fdenter), new VarExp(loc, tmp)); 3964: e->type = Type::tvoid; // do not run semantic on e 3965: cs->push(new ExpStatement(loc, e)); 3966: 3967: FuncDeclaration *fdexit = FuncDeclaration::genCfunc(Type::tvoid, Id::monitorexit); 3968: e = new CallExp(loc, new VarExp(loc, fdexit), new VarExp(loc, tmp)); 3969: e->type = Type::tvoid; // do not run semantic on e 3970: Statement *s = new ExpStatement(loc, e); 3971: s = new TryFinallyStatement(loc, body, s); 3972: cs->push(s); 3973: 3974: s = new CompoundStatement(loc, cs); 3975: return s->semantic(sc); 3976: #endif 3977: } 3978: #if 1 3979: else 3980: { /* Generate our own critical section, then rewrite as: 3981: * __gshared byte[CriticalSection.sizeof] critsec; 3982: * _d_criticalenter(critsec.ptr); 3983: * try { body } finally { _d_criticalexit(critsec.ptr); } 3984: */ 3985: Identifier *id = Lexer::uniqueId("__critsec"); 3986: Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + (global.params.is64bit ? os_critsecsize64() : os_critsecsize32()))); 3987: VarDeclaration *tmp = new VarDeclaration(loc, t, id, NULL); 3988: tmp->storage_class |= STCgshared | STCstatic; 3989: 3990: Statements *cs = new Statements(); 3991: cs->push(new ExpStatement(loc, tmp)); 3992: 3993: FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalenter); 3994: Expression *e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr);
warning C6211: Leaking memory 'e' due to an exception. Consider using a local catch block to clean up memory: Lines: 3931, 3985, 3986, 3987, 3988, 3990, 3991, 3993, 3994, 3995, 3996
3995: e = e->semantic(sc); 3996: e = new CallExp(loc, new VarExp(loc, fdenter), e); 3997: e->type = Type::tvoid; // do not run semantic on e 3998: cs->push(new ExpStatement(loc, e)); 3999: 4000: FuncDeclaration *fdexit = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalexit); 4001: e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr); 4002: e = e->semantic(sc); 4003: e = new CallExp(loc, new VarExp(loc, fdexit), e); 4004: e->type = Type::tvoid; // do not run semantic on e 4005: Statement *s = new ExpStatement(loc, e); 4006: s = new TryFinallyStatement(loc, body, s); 4007: cs->push(s); 4008: 4009: s = new CompoundStatement(loc, cs); 4010: return s->semantic(sc); 4011: } 4012: #endif 4013: if (body) 4014: body = body->semantic(sc); 4015: return this; 4016: } 4017: 4018: int SynchronizedStatement::hasBreak() 4019: { 4020: return FALSE; //TRUE; 4021: } 4022: 4023: int SynchronizedStatement::hasContinue() 4024: { 4025: return FALSE; //TRUE; 4026: } 4027: 4028: int SynchronizedStatement::usesEH() 4029: { 4030: return TRUE; 4031: } 4032: 4033: int SynchronizedStatement::blockExit(bool mustNotThrow) 4034: { 4035: return body ? body->blockExit(mustNotThrow) : BEfallthru; 4036: } 4037: 4038: 4039: void SynchronizedStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4040: { 4041: buf->writestring("synchronized"); 4042: if (exp) 4043: { buf->writebyte('('); 4044: exp->toCBuffer(buf, hgs); 4045: buf->writebyte(')'); 4046: } 4047: if (body) 4048: { 4049: buf->writebyte(' '); 4050: body->toCBuffer(buf, hgs); 4051: } 4052: } 4053: 4054: /******************************** WithStatement ***************************/ 4055: 4056: WithStatement::WithStatement(Loc loc, Expression *exp, Statement *body) 4057: : Statement(loc) 4058: { 4059: this->exp = exp; 4060: this->body = body; 4061: wthis = NULL; 4062: } 4063: 4064: Statement *WithStatement::syntaxCopy() 4065: { 4066: WithStatement *s = new WithStatement(loc, exp->syntaxCopy(), body ? body->syntaxCopy() : NULL); 4067: return s; 4068: } 4069: 4070: Statement *WithStatement::semantic(Scope *sc) 4071: { ScopeDsymbol *sym; 4072: Initializer *init; 4073: 4074: //printf("WithStatement::semantic()\n"); 4075: exp = exp->semantic(sc); 4076: exp = resolveProperties(sc, exp); 4077: if (exp->op == TOKerror) 4078: return NULL; 4079: if (exp->op == TOKimport) 4080: { ScopeExp *es = (ScopeExp *)exp; 4081: 4082: sym = es->sds; 4083: } 4084: else if (exp->op == TOKtype) 4085: { TypeExp *es = (TypeExp *)exp; 4086: 4087: Dsymbol *s = es->type->toDsymbol(sc); 4088: sym = s ? s->isScopeDsymbol() : NULL; 4089: if (!sym) 4090: { error("with type %s has no members", es->toChars()); 4091: if (body) 4092: body = body->semantic(sc); 4093: return this; 4094: } 4095: } 4096: else 4097: { Type *t = exp->type; 4098: 4099: assert(t); 4100: t = t->toBasetype(); 4101: if (t->isClassHandle()) 4102: { 4103: init = new ExpInitializer(loc, exp); 4104: wthis = new VarDeclaration(loc, exp->type, Id::withSym, init); 4105: wthis->semantic(sc); 4106: 4107: sym = new WithScopeSymbol(this); 4108: sym->parent = sc->scopesym; 4109: } 4110: else if (t->ty == Tstruct) 4111: { 4112: Expression *e = exp->addressOf(sc); 4113: init = new ExpInitializer(loc, e); 4114: wthis = new VarDeclaration(loc, e->type, Id::withSym, init); 4115: wthis->semantic(sc); 4116: sym = new WithScopeSymbol(this); 4117: sym->parent = sc->scopesym; 4118: } 4119: else 4120: { error("with expressions must be class objects, not '%s'", exp->type->toChars()); 4121: return NULL; 4122: } 4123: } 4124: sc = sc->push(sym); 4125: 4126: if (body) 4127: body = body->semantic(sc); 4128: 4129: sc->pop(); 4130: 4131: return this; 4132: } 4133: 4134: void WithStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4135: { 4136: buf->writestring("with ("); 4137: exp->toCBuffer(buf, hgs); 4138: buf->writestring(")\n"); 4139: if (body) 4140: body->toCBuffer(buf, hgs); 4141: } 4142: 4143: int WithStatement::usesEH() 4144: { 4145: return body ? body->usesEH() : 0; 4146: } 4147: 4148: int WithStatement::blockExit(bool mustNotThrow) 4149: { 4150: int result = BEnone; 4151: if (exp->canThrow(mustNotThrow)) 4152: result = BEthrow; 4153: if (body) 4154: result |= body->blockExit(mustNotThrow); 4155: else 4156: result |= BEfallthru; 4157: return result; 4158: } 4159: 4160: 4161: /******************************** TryCatchStatement ***************************/ 4162: 4163: TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Catches *catches) 4164: : Statement(loc) 4165: { 4166: this->body = body; 4167: this->catches = catches; 4168: } 4169: 4170: Statement *TryCatchStatement::syntaxCopy() 4171: { 4172: Catches *a = new Catches(); 4173: a->setDim(catches->dim); 4174: for (int i = 0; i < a->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
4175: { Catch *c; 4176: 4177: c = catches->tdata()[i]; 4178: c = c->syntaxCopy(); 4179: a->tdata()[i] = c; 4180: } 4181: TryCatchStatement *s = new TryCatchStatement(loc, body->syntaxCopy(), a); 4182: return s; 4183: } 4184: 4185: Statement *TryCatchStatement::semantic(Scope *sc) 4186: { 4187: body = body->semanticScope(sc, NULL /*this*/, NULL); 4188: 4189: /* Even if body is NULL, still do semantic analysis on catches 4190: */ 4191: for (size_t i = 0; i < catches->dim; i++) 4192: { Catch *c = catches->tdata()[i]; 4193: c->semantic(sc); 4194: 4195: // Determine if current catch 'hides' any previous catches 4196: for (size_t j = 0; j < i; j++) 4197: { Catch *cj = catches->tdata()[j]; 4198: char *si = c->loc.toChars(); 4199: char *sj = cj->loc.toChars(); 4200: 4201: if (c->type->toBasetype()->implicitConvTo(cj->type->toBasetype())) 4202: error("catch at %s hides catch at %s", sj, si); 4203: } 4204: } 4205: 4206: if (!body || body->isEmpty()) 4207: { 4208: return NULL; 4209: } 4210: return this; 4211: } 4212: 4213: int TryCatchStatement::hasBreak() 4214: { 4215: return FALSE; //TRUE; 4216: } 4217: 4218: int TryCatchStatement::usesEH() 4219: { 4220: return TRUE; 4221: } 4222: 4223: int TryCatchStatement::blockExit(bool mustNotThrow) 4224: { 4225: assert(body); 4226: int result = body->blockExit(false); 4227: 4228: int catchresult = 0; 4229: for (size_t i = 0; i < catches->dim; i++) 4230: { 4231: Catch *c = catches->tdata()[i]; 4232: if (c->type == Type::terror) 4233: continue; 4234: 4235: catchresult |= c->blockExit(mustNotThrow); 4236: 4237: /* If we're catching Object, then there is no throwing 4238: */ 4239: Identifier *id = c->type->toBasetype()->isClassHandle()->ident; 4240: if (id == Id::Object || id == Id::Throwable || id == Id::Exception) 4241: { 4242: result &= ~BEthrow; 4243: } 4244: } 4245: if (mustNotThrow && (result & BEthrow)) 4246: { 4247: body->blockExit(mustNotThrow); // now explain why this is nothrow 4248: } 4249: return result | catchresult; 4250: } 4251: 4252: 4253: void TryCatchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4254: { 4255: buf->writestring("try"); 4256: buf->writenl(); 4257: if (body) 4258: body->toCBuffer(buf, hgs); 4259: for (size_t i = 0; i < catches->dim; i++) 4260: { 4261: Catch *c = catches->tdata()[i]; 4262: c->toCBuffer(buf, hgs); 4263: } 4264: } 4265: 4266: /******************************** Catch ***************************/ 4267: 4268: Catch::Catch(Loc loc, Type *t, Identifier *id, Statement *handler) 4269: { 4270: //printf("Catch(%s, loc = %s)\n", id->toChars(), loc.toChars()); 4271: this->loc = loc; 4272: this->type = t; 4273: this->ident = id; 4274: this->handler = handler; 4275: var = NULL; 4276: } 4277: 4278: Catch *Catch::syntaxCopy() 4279: { 4280: Catch *c = new Catch(loc, 4281: (type ? type->syntaxCopy() : NULL), 4282: ident, 4283: (handler ? handler->syntaxCopy() : NULL)); 4284: return c; 4285: } 4286: 4287: void Catch::semantic(Scope *sc) 4288: { ScopeDsymbol *sym; 4289: 4290: //printf("Catch::semantic(%s)\n", ident->toChars()); 4291: 4292: #ifndef IN_GCC 4293: if (sc->tf) 4294: { 4295: /* This is because the _d_local_unwind() gets the stack munged 4296: * up on this. The workaround is to place any try-catches into 4297: * a separate function, and call that. 4298: * To fix, have the compiler automatically convert the finally 4299: * body into a nested function. 4300: */ 4301: error(loc, "cannot put catch statement inside finally block"); 4302: } 4303: #endif 4304: 4305: sym = new ScopeDsymbol(); 4306: sym->parent = sc->scopesym; 4307: sc = sc->push(sym); 4308: 4309: if (!type) 4310: type = new TypeIdentifier(0, Id::Throwable); 4311: type = type->semantic(loc, sc); 4312: ClassDeclaration *cd = type->toBasetype()->isClassHandle(); 4313: if (!cd || ((cd != ClassDeclaration::throwable) && !ClassDeclaration::throwable->isBaseOf(cd, NULL))) 4314: { 4315: if (type != Type::terror) 4316: { error(loc, "can only catch class objects derived from Throwable, not '%s'", type->toChars()); 4317: type = Type::terror; 4318: } 4319: } 4320: else if (sc->func && 4321: !sc->intypeof && 4322: cd != ClassDeclaration::exception && 4323: !ClassDeclaration::exception->isBaseOf(cd, NULL) && 4324: sc->func->setUnsafe()) 4325: { 4326: error(loc, "can only catch class objects derived from Exception in @safe code, not '%s'", type->toChars()); 4327: type = Type::terror; 4328: } 4329: else if (ident) 4330: { 4331: var = new VarDeclaration(loc, type, ident, NULL); 4332: var->parent = sc->parent; 4333: sc->insert(var); 4334: } 4335: handler = handler->semantic(sc); 4336: 4337: sc->pop(); 4338: } 4339: 4340: int Catch::blockExit(bool mustNotThrow) 4341: { 4342: return handler ? handler->blockExit(mustNotThrow) : BEfallthru; 4343: } 4344: 4345: void Catch::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4346: { 4347: buf->writestring("catch"); 4348: if (type) 4349: { buf->writebyte('('); 4350: type->toCBuffer(buf, ident, hgs); 4351: buf->writebyte(')'); 4352: } 4353: buf->writenl(); 4354: buf->writebyte('{'); 4355: buf->writenl(); 4356: if (handler) 4357: handler->toCBuffer(buf, hgs); 4358: buf->writebyte('}'); 4359: buf->writenl(); 4360: } 4361: 4362: /****************************** TryFinallyStatement ***************************/ 4363: 4364: TryFinallyStatement::TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody) 4365: : Statement(loc) 4366: { 4367: this->body = body; 4368: this->finalbody = finalbody; 4369: } 4370: 4371: Statement *TryFinallyStatement::syntaxCopy() 4372: { 4373: TryFinallyStatement *s = new TryFinallyStatement(loc, 4374: body->syntaxCopy(), finalbody->syntaxCopy()); 4375: return s; 4376: } 4377: 4378: Statement *TryFinallyStatement::semantic(Scope *sc) 4379: { 4380: //printf("TryFinallyStatement::semantic()\n"); 4381: body = body->semantic(sc); 4382: sc = sc->push(); 4383: sc->tf = this; 4384: sc->sbreak = NULL; 4385: sc->scontinue = NULL; // no break or continue out of finally block 4386: finalbody = finalbody->semanticNoScope(sc); 4387: sc->pop(); 4388: if (!body) 4389: return finalbody; 4390: if (!finalbody) 4391: return body; 4392: if (body->blockExit(false) == BEfallthru) 4393: { Statement *s = new CompoundStatement(loc, body, finalbody); 4394: return s; 4395: } 4396: return this; 4397: } 4398: 4399: void TryFinallyStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4400: { 4401: buf->printf("try\n{\n"); 4402: body->toCBuffer(buf, hgs); 4403: buf->printf("}\nfinally\n{\n"); 4404: finalbody->toCBuffer(buf, hgs); 4405: buf->writeByte('}'); 4406: buf->writenl(); 4407: } 4408: 4409: int TryFinallyStatement::hasBreak() 4410: { 4411: return FALSE; //TRUE; 4412: } 4413: 4414: int TryFinallyStatement::hasContinue() 4415: { 4416: return FALSE; //TRUE; 4417: } 4418: 4419: int TryFinallyStatement::usesEH() 4420: { 4421: return TRUE; 4422: } 4423: 4424: int TryFinallyStatement::blockExit(bool mustNotThrow) 4425: { 4426: if (body) 4427: return body->blockExit(mustNotThrow); 4428: return BEfallthru; 4429: } 4430: 4431: 4432: /****************************** OnScopeStatement ***************************/ 4433: 4434: OnScopeStatement::OnScopeStatement(Loc loc, TOK tok, Statement *statement) 4435: : Statement(loc) 4436: { 4437: this->tok = tok; 4438: this->statement = statement; 4439: } 4440: 4441: Statement *OnScopeStatement::syntaxCopy() 4442: { 4443: OnScopeStatement *s = new OnScopeStatement(loc, 4444: tok, statement->syntaxCopy()); 4445: return s; 4446: } 4447: 4448: Statement *OnScopeStatement::semantic(Scope *sc) 4449: { 4450: /* semantic is called on results of scopeCode() */ 4451: return this; 4452: } 4453: 4454: int OnScopeStatement::blockExit(bool mustNotThrow) 4455: { // At this point, this statement is just an empty placeholder 4456: return BEfallthru; 4457: } 4458: 4459: void OnScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4460: { 4461: buf->writestring(Token::toChars(tok)); 4462: buf->writebyte(' '); 4463: statement->toCBuffer(buf, hgs); 4464: } 4465: 4466: int OnScopeStatement::usesEH() 4467: { 4468: return 1; 4469: } 4470: 4471: Statement *OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) 4472: { 4473: //printf("OnScopeStatement::scopeCode()\n"); 4474: //print(); 4475: *sentry = NULL; 4476: *sexception = NULL; 4477: *sfinally = NULL; 4478: switch (tok) 4479: { 4480: case TOKon_scope_exit: 4481: *sfinally = statement; 4482: break; 4483: 4484: case TOKon_scope_failure: 4485: *sexception = statement; 4486: break; 4487: 4488: case TOKon_scope_success: 4489: { 4490: /* Create: 4491: * sentry: bool x = false; 4492: * sexception: x = true; 4493: * sfinally: if (!x) statement; 4494: */ 4495: Identifier *id = Lexer::uniqueId("__os"); 4496: 4497: ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(0, 0, Type::tbool)); 4498: VarDeclaration *v = new VarDeclaration(loc, Type::tbool, id, ie); 4499: *sentry = new ExpStatement(loc, v); 4500: 4501: Expression *e = new IntegerExp(0, 1, Type::tbool); 4502: e = new AssignExp(0, new VarExp(0, v), e); 4503: *sexception = new ExpStatement(0, e); 4504: 4505: e = new VarExp(0, v); 4506: e = new NotExp(0, e); 4507: *sfinally = new IfStatement(0, NULL, e, statement, NULL); 4508: 4509: break; 4510: } 4511: 4512: default: 4513: assert(0); 4514: } 4515: return NULL; 4516: } 4517: 4518: /******************************** ThrowStatement ***************************/ 4519: 4520: ThrowStatement::ThrowStatement(Loc loc, Expression *exp) 4521: : Statement(loc) 4522: { 4523: this->exp = exp; 4524: } 4525: 4526: Statement *ThrowStatement::syntaxCopy() 4527: { 4528: ThrowStatement *s = new ThrowStatement(loc, exp->syntaxCopy()); 4529: return s; 4530: } 4531: 4532: Statement *ThrowStatement::semantic(Scope *sc) 4533: { 4534: //printf("ThrowStatement::semantic()\n"); 4535: 4536: FuncDeclaration *fd = sc->parent->isFuncDeclaration(); 4537: fd->hasReturnExp |= 2; 4538: 4539: #if DMDV1 4540: // See bugzilla 3388. Should this be or not? 4541: if (sc->incontract) 4542: error("Throw statements cannot be in contracts"); 4543: #endif 4544: exp = exp->semantic(sc); 4545: exp = resolveProperties(sc, exp); 4546: if (exp->op == TOKerror) 4547: return this; 4548: ClassDeclaration *cd = exp->type->toBasetype()->isClassHandle(); 4549: if (!cd || ((cd != ClassDeclaration::throwable) && !ClassDeclaration::throwable->isBaseOf(cd, NULL))) 4550: error("can only throw class objects derived from Throwable, not type %s", exp->type->toChars()); 4551: 4552: return this; 4553: } 4554: 4555: int ThrowStatement::blockExit(bool mustNotThrow) 4556: { 4557: if (mustNotThrow) 4558: error("%s is thrown but not caught", exp->type->toChars()); 4559: return BEthrow; // obviously 4560: } 4561: 4562: 4563: void ThrowStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4564: { 4565: buf->printf("throw "); 4566: exp->toCBuffer(buf, hgs); 4567: buf->writeByte(';'); 4568: buf->writenl(); 4569: } 4570: 4571: /******************************** VolatileStatement **************************/ 4572: 4573: VolatileStatement::VolatileStatement(Loc loc, Statement *statement) 4574: : Statement(loc) 4575: { 4576: this->statement = statement; 4577: } 4578: 4579: Statement *VolatileStatement::syntaxCopy() 4580: { 4581: VolatileStatement *s = new VolatileStatement(loc, 4582: statement ? statement->syntaxCopy() : NULL); 4583: return s; 4584: } 4585: 4586: Statement *VolatileStatement::semantic(Scope *sc) 4587: { 4588: if (statement) 4589: statement = statement->semantic(sc); 4590: return this; 4591: } 4592: 4593: Statements *VolatileStatement::flatten(Scope *sc) 4594: { 4595: Statements *a; 4596: 4597: a = statement ? statement->flatten(sc) : NULL; 4598: if (a) 4599: { for (int i = 0; i < a->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
4600: { Statement *s = a->tdata()[i]; 4601: 4602: s = new VolatileStatement(loc, s); 4603: a->tdata()[i] = s; 4604: } 4605: } 4606: 4607: return a; 4608: } 4609: 4610: int VolatileStatement::blockExit(bool mustNotThrow) 4611: { 4612: return statement ? statement->blockExit(mustNotThrow) : BEfallthru; 4613: } 4614: 4615: 4616: void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4617: { 4618: buf->writestring("volatile"); 4619: if (statement) 4620: { if (statement->isScopeStatement()) 4621: buf->writenl(); 4622: else 4623: buf->writebyte(' '); 4624: statement->toCBuffer(buf, hgs); 4625: } 4626: } 4627: 4628: 4629: /******************************** DebugStatement **************************/ 4630: 4631: DebugStatement::DebugStatement(Loc loc, Statement *statement) 4632: : Statement(loc) 4633: { 4634: this->statement = statement; 4635: } 4636: 4637: Statement *DebugStatement::syntaxCopy() 4638: { 4639: DebugStatement *s = new DebugStatement(loc, 4640: statement ? statement->syntaxCopy() : NULL); 4641: return s; 4642: } 4643: 4644: Statement *DebugStatement::semantic(Scope *sc) 4645: { 4646: if (statement) 4647: { 4648: sc = sc->push(); 4649: sc->flags |= SCOPEdebug; 4650: statement = statement->semantic(sc); 4651: sc->pop(); 4652: } 4653: return statement; 4654: } 4655: 4656: Statements *DebugStatement::flatten(Scope *sc) 4657: { 4658: Statements *a = statement ? statement->flatten(sc) : NULL; 4659: if (a) 4660: { for (size_t i = 0; i < a->dim; i++) 4661: { Statement *s = a->tdata()[i]; 4662: 4663: s = new DebugStatement(loc, s); 4664: a->tdata()[i] = s; 4665: } 4666: } 4667: 4668: return a; 4669: } 4670: 4671: void DebugStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4672: { 4673: if (statement) 4674: { 4675: statement->toCBuffer(buf, hgs); 4676: } 4677: } 4678: 4679: 4680: /******************************** GotoStatement ***************************/ 4681: 4682: GotoStatement::GotoStatement(Loc loc, Identifier *ident) 4683: : Statement(loc) 4684: { 4685: this->ident = ident; 4686: this->label = NULL; 4687: this->tf = NULL; 4688: } 4689: 4690: Statement *GotoStatement::syntaxCopy() 4691: { 4692: GotoStatement *s = new GotoStatement(loc, ident); 4693: return s; 4694: } 4695: 4696: Statement *GotoStatement::semantic(Scope *sc) 4697: { FuncDeclaration *fd = sc->parent->isFuncDeclaration(); 4698: 4699: //printf("GotoStatement::semantic()\n"); 4700: tf = sc->tf; 4701: label = fd->searchLabel(ident); 4702: if (!label->statement && sc->fes) 4703: { 4704: /* Either the goto label is forward referenced or it 4705: * is in the function that the enclosing foreach is in. 4706: * Can't know yet, so wrap the goto in a compound statement 4707: * so we can patch it later, and add it to a 'look at this later' 4708: * list. 4709: */ 4710: Statements *a = new Statements(); 4711: CompoundStatement *s; 4712: 4713: a->push(this); 4714: s = new CompoundStatement(loc, a); 4715: sc->fes->gotos->push(s); // 'look at this later' list 4716: return s; 4717: } 4718: if (label->statement && label->statement->tf != sc->tf) 4719: error("cannot goto in or out of finally block"); 4720: return this; 4721: } 4722: 4723: int GotoStatement::blockExit(bool mustNotThrow) 4724: { 4725: //printf("GotoStatement::blockExit(%p)\n", this); 4726: return BEgoto; 4727: } 4728: 4729: 4730: void GotoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4731: { 4732: buf->writestring("goto "); 4733: buf->writestring(ident->toChars()); 4734: buf->writebyte(';'); 4735: buf->writenl(); 4736: } 4737: 4738: /******************************** LabelStatement ***************************/ 4739: 4740: LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement) 4741: : Statement(loc) 4742: { 4743: this->ident = ident; 4744: this->statement = statement; 4745: this->tf = NULL; 4746: this->lblock = NULL; 4747: this->fwdrefs = NULL; 4748: } 4749: 4750: Statement *LabelStatement::syntaxCopy() 4751: { 4752: LabelStatement *s = new LabelStatement(loc, ident, statement->syntaxCopy()); 4753: return s; 4754: } 4755: 4756: Statement *LabelStatement::semantic(Scope *sc) 4757: { LabelDsymbol *ls; 4758: FuncDeclaration *fd = sc->parent->isFuncDeclaration(); 4759: 4760: //printf("LabelStatement::semantic()\n"); 4761: ls = fd->searchLabel(ident); 4762: if (ls->statement) 4763: error("Label '%s' already defined", ls->toChars()); 4764: else 4765: ls->statement = this; 4766: tf = sc->tf; 4767: sc = sc->push(); 4768: sc->scopesym = sc->enclosing->scopesym; 4769: sc->callSuper |= CSXlabel; 4770: sc->slabel = this; 4771: if (statement) 4772: statement = statement->semanticNoScope(sc); 4773: sc->pop(); 4774: return this; 4775: } 4776: 4777: Statements *LabelStatement::flatten(Scope *sc) 4778: { 4779: Statements *a = NULL; 4780: 4781: if (statement) 4782: { 4783: a = statement->flatten(sc); 4784: if (a) 4785: { 4786: if (!a->dim) 4787: { 4788: a->push(new ExpStatement(loc, (Expression *)NULL)); 4789: } 4790: Statement *s = a->tdata()[0]; 4791: 4792: s = new LabelStatement(loc, ident, s); 4793: a->tdata()[0] = s; 4794: } 4795: } 4796: 4797: return a; 4798: } 4799: 4800: 4801: int LabelStatement::usesEH() 4802: { 4803: return statement ? statement->usesEH() : FALSE; 4804: } 4805: 4806: int LabelStatement::blockExit(bool mustNotThrow) 4807: { 4808: //printf("LabelStatement::blockExit(%p)\n", this); 4809: return statement ? statement->blockExit(mustNotThrow) : BEfallthru; 4810: } 4811: 4812: 4813: int LabelStatement::comeFrom() 4814: { 4815: //printf("LabelStatement::comeFrom()\n"); 4816: return TRUE; 4817: } 4818: 4819: void LabelStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4820: { 4821: buf->writestring(ident->toChars()); 4822: buf->writebyte(':'); 4823: buf->writenl(); 4824: if (statement) 4825: statement->toCBuffer(buf, hgs); 4826: } 4827: 4828: 4829: /******************************** LabelDsymbol ***************************/ 4830: 4831: LabelDsymbol::LabelDsymbol(Identifier *ident) 4832: : Dsymbol(ident) 4833: { 4834: statement = NULL; 4835: #if IN_GCC 4836: asmLabelNum = 0; 4837: #endif 4838: } 4839: 4840: LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()? 4841: { 4842: return this; 4843: } 4844: 4845: 4846: /************************ AsmStatement ***************************************/ 4847: 4848: AsmStatement::AsmStatement(Loc loc, Token *tokens) 4849: : Statement(loc) 4850: { 4851: this->tokens = tokens; 4852: asmcode = NULL; 4853: asmalign = 0; 4854: refparam = FALSE; 4855: naked = FALSE; 4856: regs = 0; 4857: } 4858: 4859: Statement *AsmStatement::syntaxCopy() 4860: { 4861: return new AsmStatement(loc, tokens); 4862: } 4863: 4864: 4865: 4866: int AsmStatement::comeFrom() 4867: { 4868: return TRUE; 4869: } 4870: 4871: int AsmStatement::blockExit(bool mustNotThrow) 4872: { 4873: if (mustNotThrow) 4874: error("asm statements are assumed to throw", toChars()); 4875: // Assume the worst 4876: return BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt; 4877: } 4878: 4879: void AsmStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4880: { 4881: buf->writestring("asm { "); 4882: Token *t = tokens; 4883: while (t) 4884: { 4885: buf->writestring(t->toChars()); 4886: if (t->next && 4887: t->value != TOKmin && 4888: t->value != TOKcomma && 4889: t->next->value != TOKcomma && 4890: t->value != TOKlbracket && 4891: t->next->value != TOKlbracket && 4892: t->next->value != TOKrbracket && 4893: t->value != TOKlparen && 4894: t->next->value != TOKlparen && 4895: t->next->value != TOKrparen && 4896: t->value != TOKdot && 4897: t->next->value != TOKdot) 4898: { 4899: buf->writebyte(' '); 4900: } 4901: t = t->next; 4902: } 4903: buf->writestring("; }"); 4904: buf->writenl(); 4905: } 4906: 4907: /************************ ImportStatement ***************************************/ 4908: 4909: ImportStatement::ImportStatement(Loc loc, Dsymbols *imports) 4910: : Statement(loc) 4911: { 4912: this->imports = imports; 4913: } 4914: 4915: Statement *ImportStatement::syntaxCopy() 4916: { 4917: Dsymbols *m = new Dsymbols(); 4918: m->setDim(imports->dim); 4919: for (int i = 0; i < imports->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
4920: { Dsymbol *s = imports->tdata()[i]; 4921: m->tdata()[i] = s->syntaxCopy(NULL); 4922: } 4923: return new ImportStatement(loc, m); 4924: } 4925: 4926: Statement *ImportStatement::semantic(Scope *sc) 4927: { 4928: for (int i = 0; i < imports->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
4929: { Dsymbol *s = imports->tdata()[i]; 4930: s->semantic(sc); 4931: sc->insert(s); 4932: } 4933: return this; 4934: } 4935: 4936: int ImportStatement::blockExit(bool mustNotThrow) 4937: { 4938: return BEfallthru; 4939: } 4940: 4941: int ImportStatement::isEmpty() 4942: { 4943: return TRUE; 4944: } 4945: 4946: void ImportStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 4947: { 4948: for (int i = 0; i < imports->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
4949: { Dsymbol *s = imports->tdata()[i]; 4950: s->toCBuffer(buf, hgs); 4951: } 4952: } 4953: