1: // Compiler implementation of the D programming language
   2: // Copyright (c) 1999-2011 by Digital Mars
   3: // All Rights Reserved
   4: // written by Walter Bright
   5: // http://www.digitalmars.com
   6: // License for redistribution is by either the Artistic License
   7: // in artistic.txt, or the GNU General Public License in gnu.txt.
   8: // See the included readme.txt for details.
   9: 
  10: #include <stdio.h>
  11: #include <stdlib.h>
  12: static char __file__[] = __FILE__;      /* for tassert.h                */
  13: #include        "tassert.h"
  14: 
  15: #include "rmem.h"
  16: 
  17: #include "statement.h"
  18: #include "expression.h"
  19: #include "cond.h"
  20: #include "init.h"
  21: #include "staticassert.h"
  22: #include "mtype.h"
  23: #include "scope.h"
  24: #include "declaration.h"
  25: #include "aggregate.h"
  26: #include "id.h"
  27: #include "utf.h"
  28: 
  29: #define LOG     0
  30: #define LOGASSIGN 0
  31: 
  32: struct InterState
  33: {
  34:     InterState *caller;         // calling function's InterState
  35:     FuncDeclaration *fd;        // function being interpreted
  36:     VarDeclarations vars;              // variables used in this function
  37:     Statement *start;           // if !=NULL, start execution at this statement
  38:     Statement *gotoTarget;      /* target of EXP_GOTO_INTERPRET result; also
  39:                                  * target of labelled EXP_BREAK_INTERPRET or
  40:                                  * EXP_CONTINUE_INTERPRET. (NULL if no label).
  41:                                  */
  42:     Expression *localThis;      // value of 'this', or NULL if none
  43:     bool awaitingLvalueReturn;  // Support for ref return values:
  44:            // Any return to this function should return an lvalue.
  45:     InterState();
  46: };
  47: 
  48: InterState::InterState()
  49: {
  50:     memset(this, 0, sizeof(InterState));
  51: }
  52: 
  53: Expression * resolveReferences(Expression *e, Expression *thisval, bool *isReference = NULL);
  54: Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal);
  55: VarDeclaration *findParentVar(Expression *e, Expression *thisval);
  56: void addVarToInterstate(InterState *istate, VarDeclaration *v);
  57: bool needToCopyLiteral(Expression *expr);
  58: Expression *copyLiteral(Expression *e);
  59: Expression *paintTypeOntoLiteral(Type *type, Expression *lit);
  60: bool evaluateIfBuiltin(Expression **result, InterState *istate,
  61:     FuncDeclaration *fd, Expressions *arguments, Expression *pthis);
  62: 
  63: 
  64: // Used for debugging only
  65: void showCtfeExpr(Expression *e, int level = 0)
  66: {
  67:     for (int i = level; i>0; --i) printf(" ");
  68:     Expressions *elements = NULL;
  69:     // We need the struct definition to detect block assignment
  70:     StructDeclaration *sd = NULL;
  71:     if (e->op == TOKstructliteral) {
  72:         elements = ((StructLiteralExp *)e)->elements;
  73:         sd = ((StructLiteralExp *)e)->sd;
  74:         printf("STRUCT type = %s %p :\n", e->type->toChars(), e);
  75:     }
  76:     else if (e->op == TOKarrayliteral)
  77:     {
  78:         elements = ((ArrayLiteralExp *)e)->elements;
  79:         printf("ARRAY LITERAL type=%s %p:\n", e->type->toChars(), e);
  80:     }
  81:     else if (e->op == TOKassocarrayliteral)
  82:     {
  83:         printf("AA LITERAL type=%s %p:\n", e->type->toChars(), e);
  84:     }
  85:     else if (e->op == TOKstring)
  86:     {
  87:         printf("STRING %s %p\n", e->toChars(), ((StringExp *)e)->string);
  88:     }
  89:     else if (e->op == TOKslice)
  90:     {
  91:         printf("SLICE %p: %s\n", e, e->toChars());
  92:         showCtfeExpr(((SliceExp *)e)->e1, level + 1);
  93:     }
  94:     else if (e->op == TOKvar)
  95:     {
  96:         printf("VAR %p %s\n", e, e->toChars());
  97:         VarDeclaration *v = ((VarExp *)e)->var->isVarDeclaration();
  98:         if (v && v->getValue())
  99:             showCtfeExpr(v->getValue(), level + 1);
 100:     }
 101:     else printf("VALUE %p: %s\n", e, e->toChars());
 102: 
 103:     if (elements)
 104:     {
 105:         for (size_t i = 0; i < elements->dim; i++)
 106:         {   Expression *z = elements->tdata()[i];
 107:             if (sd)
 108:             {
 109:                 Dsymbol *s = sd->fields.tdata()[i];
 110:                 VarDeclaration *v = s->isVarDeclaration();
 111:                 assert(v);
 112:                 // If it is a void assignment, use the default initializer
 113:                 if (!z) {
 114:                     for (int i = level; i>0; --i) printf(" ");
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '105' of 'c:\projects\extern\d\dmd\src\interpret.c': Lines: 105
115: printf(" field:void\n"); 116: continue; 117: } 118: if ((v->type->ty != z->type->ty) && v->type->ty == Tsarray) 119: { 120: for (int i = level; --i;) printf(" ");
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '105' of 'c:\projects\extern\d\dmd\src\interpret.c': Lines: 105
121: printf(" field: block initalized static array\n"); 122: continue; 123: } 124: } 125: showCtfeExpr(z, level + 1); 126: } 127: } 128: } 129: 130: /************************************* 131: * Attempt to interpret a function given the arguments. 132: * Input: 133: * istate state for calling function (NULL if none) 134: * arguments function arguments 135: * thisarg 'this', if a needThis() function, NULL if not. 136: * 137: * Return result expression if successful, NULL if not. 138: */ 139: 140: Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments, Expression *thisarg) 141: { 142: #if LOG 143: printf("\n********\nFuncDeclaration::interpret(istate = %p) %s\n", istate, toChars()); 144: printf("cantInterpret = %d, semanticRun = %d\n", cantInterpret, semanticRun); 145: #endif 146: if (global.errors) 147: return NULL; 148: 149: if (cantInterpret || semanticRun == PASSsemantic3) 150: return NULL; 151: 152: if (semanticRun < PASSsemantic3 && scope) 153: { 154: int olderrors = global.errors; 155: semantic3(scope); 156: if (olderrors != global.errors) // if errors compiling this function 157: return NULL; 158: } 159: if (semanticRun < PASSsemantic3done) 160: return NULL; 161: 162: Type *tb = type->toBasetype(); 163: assert(tb->ty == Tfunction); 164: TypeFunction *tf = (TypeFunction *)tb; 165: Type *tret = tf->next->toBasetype(); 166: if (tf->varargs && arguments && 167: ((parameters && arguments->dim != parameters->dim) || (!parameters && arguments->dim))) 168: { cantInterpret = 1; 169: error("C-style variadic functions are not yet implemented in CTFE"); 170: return NULL; 171: } 172: 173: InterState istatex; 174: istatex.caller = istate; 175: istatex.fd = this; 176: istatex.localThis = thisarg; 177: 178: Expressions vsave; // place to save previous parameter values 179: size_t dim = 0; 180: if (needThis() && !thisarg) 181: { // error, no this. Prevent segfault. 182: error("need 'this' to access member %s", toChars()); 183: return NULL; 184: } 185: if (thisarg && !istate) 186: { // Check that 'this' aleady has a value 187: if (thisarg->interpret(istate) == EXP_CANT_INTERPRET) 188: return NULL; 189: } 190: if (arguments) 191: { 192: dim = arguments->dim; 193: assert(!dim || (parameters && (parameters->dim == dim))); 194: vsave.setDim(dim); 195: 196: /* Evaluate all the arguments to the function, 197: * store the results in eargs[] 198: */ 199: Expressions eargs; 200: eargs.setDim(dim); 201: 202: for (size_t i = 0; i < dim; i++) 203: { Expression *earg = arguments->tdata()[i]; 204: Parameter *arg = Parameter::getNth(tf->parameters, i); 205: 206: if (arg->storageClass & (STCout | STCref)) 207: { 208: if (!istate && (arg->storageClass & STCout)) 209: { // initializing an out parameter involves writing to it. 210: earg->error("global %s cannot be passed as an 'out' parameter at compile time", earg->toChars()); 211: return NULL; 212: } 213: // Convert all reference arguments into lvalue references 214: earg = earg->interpret(istate, ctfeNeedLvalueRef); 215: if (earg == EXP_CANT_INTERPRET) 216: return NULL; 217: } 218: else if (arg->storageClass & STClazy) 219: { 220: } 221: else 222: { /* Value parameters 223: */ 224: Type *ta = arg->type->toBasetype(); 225: if (ta->ty == Tsarray && earg->op == TOKaddress) 226: { 227: /* Static arrays are passed by a simple pointer. 228: * Skip past this to get at the actual arg. 229: */ 230: earg = ((AddrExp *)earg)->e1; 231: } 232: earg = earg->interpret(istate); 233: if (earg == EXP_CANT_INTERPRET) 234: return NULL; 235: } 236: eargs.tdata()[i] = earg; 237: } 238: 239: for (size_t i = 0; i < dim; i++) 240: { Expression *earg = eargs.tdata()[i]; 241: Parameter *arg = Parameter::getNth(tf->parameters, i); 242: VarDeclaration *v = parameters->tdata()[i]; 243: vsave.tdata()[i] = v->getValue(); 244: #if LOG 245: printf("arg[%d] = %s\n", i, earg->toChars()); 246: #endif 247: if (arg->storageClass & (STCout | STCref) && earg->op==TOKvar) 248: { 249: VarExp *ve = (VarExp *)earg; 250: VarDeclaration *v2 = ve->var->isVarDeclaration(); 251: if (!v2) 252: { 253: error("cannot interpret %s as a ref parameter", ve->toChars()); 254: return NULL; 255: } 256: v->setValueWithoutChecking(earg); 257: /* Don't restore the value of v2 upon function return 258: */ 259: for (size_t i = 0; i < (istate ? istate->vars.dim : 0); i++)
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '239' of 'c:\projects\extern\d\dmd\src\interpret.c': Lines: 239
260: { VarDeclaration *vx = istate->vars.tdata()[i]; 261: if (vx == v2) 262: { istate->vars.tdata()[i] = NULL; 263: break; 264: } 265: } 266: } 267: else 268: { // Value parameters and non-trivial references 269: v->setValueWithoutChecking(earg); 270: } 271: #if LOG || LOGASSIGN 272: printf("interpreted arg[%d] = %s\n", i, earg->toChars()); 273: showCtfeExpr(earg); 274: #endif 275: } 276: } 277: // Don't restore the value of 'this' upon function return 278: if (needThis() && istate) 279: { 280: VarDeclaration *thisvar = findParentVar(thisarg, istate->localThis); 281: if (!thisvar) // it's a reference. Find which variable it refers to. 282: thisvar = findParentVar(thisarg->interpret(istate), istate->localThis); 283: for (size_t i = 0; i < istate->vars.dim; i++) 284: { VarDeclaration *v = istate->vars.tdata()[i]; 285: if (v == thisvar) 286: { istate->vars.tdata()[i] = NULL; 287: break; 288: } 289: } 290: } 291: 292: /* Save the values of the local variables used 293: */ 294: Expressions valueSaves; 295: if (istate) 296: { 297: //printf("saving local variables...\n"); 298: valueSaves.setDim(istate->vars.dim); 299: for (size_t i = 0; i < istate->vars.dim; i++) 300: { VarDeclaration *v = istate->vars.tdata()[i]; 301: bool isParentVar = false; 302: /* Nested functions only restore their own local variables 303: * (not variables in the parent function) 304: */ 305: if (v && (!isNested() || v->parent == this)) 306: { 307: //printf("\tsaving [%d] %s = %s\n", i, v->toChars(), v->getValue() ? v->getValue()->toChars() : ""); 308: valueSaves.tdata()[i] = v->getValue(); 309: v->setValueNull(); 310: } 311: } 312: } 313: 314: Expression *e = NULL; 315: while (1) 316: { 317: e = fbody->interpret(&istatex); 318: if (e == EXP_CANT_INTERPRET) 319: { 320: #if LOG 321: printf("function body failed to interpret\n"); 322: #endif 323: e = NULL; 324: } 325: 326: /* This is how we deal with a recursive statement AST 327: * that has arbitrary goto statements in it. 328: * Bubble up a 'result' which is the target of the goto 329: * statement, then go recursively down the AST looking 330: * for that statement, then execute starting there. 331: */ 332: if (e == EXP_GOTO_INTERPRET) 333: { 334: istatex.start = istatex.gotoTarget; // set starting statement 335: istatex.gotoTarget = NULL; 336: } 337: else 338: break; 339: } 340: assert(e != EXP_CONTINUE_INTERPRET && e != EXP_BREAK_INTERPRET); 341: 342: /* Restore the parameter values 343: */ 344: for (size_t i = 0; i < dim; i++) 345: { 346: VarDeclaration *v = parameters->tdata()[i]; 347: v->setValueWithoutChecking(vsave.tdata()[i]); 348: } 349: /* Clear __result. (Bug 6049). 350: */ 351: if (vresult) 352: vresult->setValueNull(); 353: 354: if (istate) 355: { 356: /* Restore the variable values 357: */ 358: //printf("restoring local variables...\n"); 359: for (size_t i = 0; i < istate->vars.dim; i++) 360: { VarDeclaration *v = istate->vars.tdata()[i]; 361: /* Nested functions only restore their own local variables 362: * (not variables in the parent function) 363: */ 364: if (v && (!isNested() || v->parent == this)) 365: { v->setValueWithoutChecking(valueSaves.tdata()[i]); 366: //printf("\trestoring [%d] %s = %s\n", i, v->toChars(), v->getValue() ? v->getValue()->toChars() : ""); 367: } 368: } 369: } 370: return e; 371: } 372: 373: /******************************** Statement ***************************/ 374: 375: #define START() \ 376: if (istate->start) \ 377: { if (istate->start != this) \ 378: return NULL; \ 379: istate->start = NULL; \ 380: } 381: 382: /*********************************** 383: * Interpret the statement. 384: * Returns: 385: * NULL continue to next statement 386: * EXP_CANT_INTERPRET cannot interpret statement at compile time 387: * !NULL expression from return statement 388: */ 389: 390: Expression *Statement::interpret(InterState *istate) 391: { 392: #if LOG 393: printf("Statement::interpret()\n"); 394: #endif 395: START() 396: error("Statement %s cannot be interpreted at compile time", this->toChars()); 397: return EXP_CANT_INTERPRET; 398: } 399: 400: Expression *ExpStatement::interpret(InterState *istate) 401: { 402: #if LOG 403: printf("ExpStatement::interpret(%s)\n", exp ? exp->toChars() : ""); 404: #endif 405: START() 406: if (exp) 407: { 408: Expression *e = exp->interpret(istate, ctfeNeedNothing); 409: if (e == EXP_CANT_INTERPRET) 410: { 411: //printf("-ExpStatement::interpret(): %p\n", e); 412: return EXP_CANT_INTERPRET; 413: } 414: } 415: return NULL; 416: } 417: 418: Expression *CompoundStatement::interpret(InterState *istate) 419: { Expression *e = NULL; 420: 421: #if LOG 422: printf("CompoundStatement::interpret()\n"); 423: #endif 424: if (istate->start == this) 425: istate->start = NULL; 426: if (statements) 427: { 428: for (size_t i = 0; i < statements->dim; i++) 429: { Statement *s = statements->tdata()[i]; 430: 431: if (s) 432: { 433: e = s->interpret(istate); 434: if (e) 435: break; 436: } 437: } 438: } 439: #if LOG 440: printf("-CompoundStatement::interpret() %p\n", e); 441: #endif 442: return e; 443: } 444: 445: Expression *UnrolledLoopStatement::interpret(InterState *istate) 446: { Expression *e = NULL; 447: 448: #if LOG 449: printf("UnrolledLoopStatement::interpret()\n"); 450: #endif 451: if (istate->start == this) 452: istate->start = NULL; 453: if (statements) 454: { 455: for (size_t i = 0; i < statements->dim; i++) 456: { Statement *s = statements->tdata()[i]; 457: 458: e = s->interpret(istate); 459: if (e == EXP_CANT_INTERPRET) 460: break; 461: if (e == EXP_CONTINUE_INTERPRET) 462: { 463: if (istate->gotoTarget && istate->gotoTarget != this) 464: break; // continue at higher level 465: istate->gotoTarget = NULL; 466: e = NULL; 467: continue; 468: } 469: if (e == EXP_BREAK_INTERPRET) 470: { 471: if (!istate->gotoTarget || istate->gotoTarget == this) 472: { 473: istate->gotoTarget = NULL; 474: e = NULL; 475: } // else break at a higher level 476: break; 477: } 478: if (e) 479: break; 480: } 481: } 482: return e; 483: } 484: 485: // For CTFE only. Returns true if 'e' is TRUE or a non-null pointer. 486: int isTrueBool(Expression *e) 487: { 488: return e->isBool(TRUE) || (e->type->ty == Tpointer && e->op != TOKnull); 489: } 490: 491: Expression *IfStatement::interpret(InterState *istate) 492: { 493: #if LOG 494: printf("IfStatement::interpret(%s)\n", condition->toChars()); 495: #endif 496: 497: if (istate->start == this) 498: istate->start = NULL; 499: if (istate->start) 500: { 501: Expression *e = NULL; 502: if (ifbody) 503: e = ifbody->interpret(istate); 504: if (istate->start && elsebody) 505: e = elsebody->interpret(istate); 506: return e; 507: } 508: 509: Expression *e = condition->interpret(istate); 510: assert(e); 511: //if (e == EXP_CANT_INTERPRET) printf("cannot interpret\n"); 512: if (e != EXP_CANT_INTERPRET) 513: { 514: if (isTrueBool(e)) 515: e = ifbody ? ifbody->interpret(istate) : NULL; 516: else if (e->isBool(FALSE)) 517: e = elsebody ? elsebody->interpret(istate) : NULL; 518: else 519: { 520: e = EXP_CANT_INTERPRET; 521: } 522: } 523: return e; 524: } 525: 526: Expression *ScopeStatement::interpret(InterState *istate) 527: { 528: #if LOG 529: printf("ScopeStatement::interpret()\n"); 530: #endif 531: if (istate->start == this) 532: istate->start = NULL; 533: return statement ? statement->interpret(istate) : NULL; 534: } 535: 536: Expression *resolveSlice(Expression *e) 537: { 538: if ( ((SliceExp *)e)->e1->op == TOKnull) 539: return ((SliceExp *)e)->e1; 540: return Slice(e->type, ((SliceExp *)e)->e1, 541: ((SliceExp *)e)->lwr, ((SliceExp *)e)->upr); 542: } 543: 544: /* Determine the array length, without interpreting it. 545: * e must be an array literal, or a slice 546: * It's very wasteful to resolve the slice when we only 547: * need the length. 548: */ 549: uinteger_t resolveArrayLength(Expression *e) 550: { 551: if (e->op == TOKnull) 552: return 0; 553: if (e->op == TOKslice) 554: { uinteger_t ilo = ((SliceExp *)e)->lwr->toInteger(); 555: uinteger_t iup = ((SliceExp *)e)->upr->toInteger(); 556: return iup - ilo; 557: } 558: if (e->op == TOKstring) 559: { return ((StringExp *)e)->len; 560: } 561: if (e->op == TOKarrayliteral) 562: { ArrayLiteralExp *ale = (ArrayLiteralExp *)e; 563: return ale->elements ? ale->elements->dim : 0; 564: } 565: if (e->op == TOKassocarrayliteral) 566: { AssocArrayLiteralExp *ale = (AssocArrayLiteralExp *)e; 567: return ale->keys->dim; 568: } 569: assert(0); 570: return 0; 571: } 572: 573: // As Equal, but resolves slices before comparing 574: Expression *ctfeEqual(enum TOK op, Type *type, Expression *e1, Expression *e2) 575: { 576: if (e1->op == TOKslice) 577: e1 = resolveSlice(e1); 578: if (e2->op == TOKslice) 579: e2 = resolveSlice(e2); 580: return Equal(op, type, e1, e2); 581: } 582: 583: 584: void scrubArray(Expressions *elems); 585: 586: /* All results destined for use outside of CTFE need to have their CTFE-specific 587: * features removed. 588: * In particular, all slices must be resolved. 589: */ 590: Expression *scrubReturnValue(Expression *e) 591: { 592: if (e->op == TOKslice) 593: { 594: e = resolveSlice(e); 595: } 596: if (e->op == TOKstructliteral) 597: { 598: StructLiteralExp *se = (StructLiteralExp *)e; 599: scrubArray(se->elements); 600: } 601: if (e->op == TOKarrayliteral) 602: { 603: scrubArray(((ArrayLiteralExp *)e)->elements); 604: } 605: if (e->op == TOKassocarrayliteral) 606: { 607: AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e; 608: scrubArray(aae->keys); 609: scrubArray(aae->values); 610: } 611: return e; 612: } 613: 614: // Scrub all members of an array 615: void scrubArray(Expressions *elems) 616: { 617: for (size_t i = 0; i < elems->dim; i++) 618: { 619: Expression *m = elems->tdata()[i]; 620: if (!m) 621: continue; 622: m = scrubReturnValue(m); 623: elems->tdata()[i] = m; 624: } 625: } 626: 627: 628: Expression *ReturnStatement::interpret(InterState *istate) 629: { 630: #if LOG 631: printf("ReturnStatement::interpret(%s)\n", exp ? exp->toChars() : ""); 632: #endif 633: START() 634: if (!exp) 635: return EXP_VOID_INTERPRET; 636: assert(istate && istate->fd && istate->fd->type); 637: #if DMDV2 638: /* If the function returns a ref AND it's been called from an assignment, 639: * we need to return an lvalue. Otherwise, just do an (rvalue) interpret. 640: */ 641: if (istate->fd->type && istate->fd->type->ty==Tfunction) 642: { 643: TypeFunction *tf = (TypeFunction *)istate->fd->type; 644: if (tf->isref && istate->caller && istate->caller->awaitingLvalueReturn) 645: { // We need to return an lvalue 646: Expression *e = exp->interpret(istate, ctfeNeedLvalue); 647: if (e == EXP_CANT_INTERPRET) 648: error("ref return %s is not yet supported in CTFE", exp->toChars()); 649: return e; 650: } 651: if (tf->next && (tf->next->ty == Tdelegate) && istate->fd->closureVars.dim > 0) 652: { 653: // To support this, we need to copy all the closure vars 654: // into the delegate literal. 655: error("closures are not yet supported in CTFE"); 656: return EXP_CANT_INTERPRET; 657: } 658: } 659: #endif 660: // We need to treat pointers specially, because TOKsymoff can be used to 661: // return a value OR a pointer 662: Expression *e; 663: if ((exp->type->ty == Tpointer && exp->type->nextOf()->ty != Tfunction)) 664: e = exp->interpret(istate, ctfeNeedLvalue); 665: else 666: e = exp->interpret(istate); 667: if (e == EXP_CANT_INTERPRET) 668: return e; 669: if (!istate->caller) 670: { 671: e = scrubReturnValue(e); 672: if (e == EXP_CANT_INTERPRET) 673: return e; 674: } 675: else if (needToCopyLiteral(exp)) 676: e = copyLiteral(e); 677: #if LOGASSIGN 678: printf("RETURN %s\n", loc.toChars()); 679: showCtfeExpr(e); 680: #endif 681: return e; 682: } 683: 684: Expression *BreakStatement::interpret(InterState *istate) 685: { 686: #if LOG 687: printf("BreakStatement::interpret()\n"); 688: #endif 689: START() 690: if (ident) 691: { LabelDsymbol *label = istate->fd->searchLabel(ident); 692: assert(label && label->statement); 693: Statement *s = label->statement; 694: if (s->isLabelStatement()) 695: s = s->isLabelStatement()->statement; 696: if (s->isScopeStatement()) 697: s = s->isScopeStatement()->statement; 698: istate->gotoTarget = s; 699: return EXP_BREAK_INTERPRET; 700: } 701: else 702: { 703: istate->gotoTarget = NULL; 704: return EXP_BREAK_INTERPRET; 705: } 706: } 707: 708: Expression *ContinueStatement::interpret(InterState *istate) 709: { 710: #if LOG 711: printf("ContinueStatement::interpret()\n"); 712: #endif 713: START() 714: if (ident) 715: { LabelDsymbol *label = istate->fd->searchLabel(ident); 716: assert(label && label->statement); 717: Statement *s = label->statement; 718: if (s->isLabelStatement()) 719: s = s->isLabelStatement()->statement; 720: if (s->isScopeStatement()) 721: s = s->isScopeStatement()->statement; 722: istate->gotoTarget = s; 723: return EXP_CONTINUE_INTERPRET; 724: } 725: else 726: return EXP_CONTINUE_INTERPRET; 727: } 728: 729: Expression *WhileStatement::interpret(InterState *istate) 730: { 731: #if LOG 732: printf("WhileStatement::interpret()\n"); 733: #endif 734: assert(0); // rewritten to ForStatement 735: return NULL; 736: } 737: 738: Expression *DoStatement::interpret(InterState *istate) 739: { 740: #if LOG 741: printf("DoStatement::interpret()\n"); 742: #endif 743: if (istate->start == this) 744: istate->start = NULL; 745: Expression *e; 746: 747: if (istate->start) 748: { 749: e = body ? body->interpret(istate) : NULL; 750: if (istate->start) 751: return NULL; 752: if (e == EXP_CANT_INTERPRET) 753: return e; 754: if (e == EXP_BREAK_INTERPRET) 755: { 756: if (!istate->gotoTarget || istate->gotoTarget == this) 757: { 758: istate->gotoTarget = NULL; 759: e = NULL; 760: } // else break at a higher level 761: return e; 762: } 763: if (e == EXP_CONTINUE_INTERPRET) 764: if (!istate->gotoTarget || istate->gotoTarget == this) 765: { 766: goto Lcontinue; 767: } 768: else // else continue at a higher level 769: return e; 770: if (e) 771: return e; 772: } 773: 774: while (1) 775: { 776: e = body ? body->interpret(istate) : NULL; 777: if (e == EXP_CANT_INTERPRET) 778: break; 779: if (e == EXP_BREAK_INTERPRET) 780: { 781: if (!istate->gotoTarget || istate->gotoTarget == this) 782: { 783: istate->gotoTarget = NULL; 784: e = NULL; 785: } // else break at a higher level 786: break; 787: } 788: if (e && e != EXP_CONTINUE_INTERPRET) 789: break; 790: if (istate->gotoTarget && istate->gotoTarget != this) 791: break; // continue at a higher level 792: 793: Lcontinue: 794: istate->gotoTarget = NULL; 795: e = condition->interpret(istate); 796: if (e == EXP_CANT_INTERPRET) 797: break; 798: if (!e->isConst()) 799: { e = EXP_CANT_INTERPRET; 800: break; 801: } 802: if (isTrueBool(e)) 803: { 804: } 805: else if (e->isBool(FALSE)) 806: { e = NULL; 807: break; 808: } 809: else 810: assert(0); 811: } 812: return e; 813: } 814: 815: Expression *ForStatement::interpret(InterState *istate) 816: { 817: #if LOG 818: printf("ForStatement::interpret()\n"); 819: #endif 820: if (istate->start == this) 821: istate->start = NULL; 822: Expression *e; 823: 824: if (init) 825: { 826: e = init->interpret(istate); 827: if (e == EXP_CANT_INTERPRET) 828: return e; 829: assert(!e); 830: } 831: 832: if (istate->start) 833: { 834: e = body ? body->interpret(istate) : NULL; 835: if (istate->start) 836: return NULL; 837: if (e == EXP_CANT_INTERPRET) 838: return e; 839: if (e == EXP_BREAK_INTERPRET) 840: { 841: if (!istate->gotoTarget || istate->gotoTarget == this) 842: { 843: istate->gotoTarget = NULL; 844: return NULL; 845: } // else break at a higher level 846: } 847: if (e == EXP_CONTINUE_INTERPRET) 848: { 849: if (!istate->gotoTarget || istate->gotoTarget == this) 850: { 851: istate->gotoTarget = NULL; 852: goto Lcontinue; 853: } // else continue at a higher level 854: } 855: if (e) 856: return e; 857: } 858: 859: while (1) 860: { 861: if (!condition) 862: goto Lhead; 863: e = condition->interpret(istate); 864: if (e == EXP_CANT_INTERPRET) 865: break; 866: if (!e->isConst()) 867: { e = EXP_CANT_INTERPRET; 868: break; 869: } 870: if (isTrueBool(e)) 871: { 872: Lhead: 873: e = body ? body->interpret(istate) : NULL; 874: if (e == EXP_CANT_INTERPRET) 875: break; 876: if (e == EXP_BREAK_INTERPRET) 877: { 878: if (!istate->gotoTarget || istate->gotoTarget == this) 879: { 880: istate->gotoTarget = NULL; 881: e = NULL; 882: } // else break at a higher level 883: break; 884: } 885: if (e && e != EXP_CONTINUE_INTERPRET) 886: break; 887: if (istate->gotoTarget && istate->gotoTarget != this) 888: break; // continue at a higher level 889: Lcontinue: 890: istate->gotoTarget = NULL; 891: if (increment) 892: { 893: e = increment->interpret(istate); 894: if (e == EXP_CANT_INTERPRET) 895: break; 896: } 897: } 898: else if (e->isBool(FALSE)) 899: { e = NULL; 900: break; 901: } 902: else 903: assert(0); 904: } 905: return e; 906: } 907: 908: Expression *ForeachStatement::interpret(InterState *istate) 909: { 910: #if 1 911: assert(0); // rewritten to ForStatement 912: return NULL; 913: #else 914: #if LOG 915: printf("ForeachStatement::interpret()\n"); 916: #endif 917: if (istate->start == this) 918: istate->start = NULL; 919: if (istate->start) 920: return NULL; 921: 922: Expression *e = NULL; 923: Expression *eaggr; 924: 925: if (value->isOut() || value->isRef()) 926: return EXP_CANT_INTERPRET; 927: 928: eaggr = aggr->interpret(istate); 929: if (eaggr == EXP_CANT_INTERPRET) 930: return EXP_CANT_INTERPRET; 931: 932: Expression *dim = ArrayLength(Type::tsize_t, eaggr); 933: if (dim == EXP_CANT_INTERPRET) 934: return EXP_CANT_INTERPRET; 935: 936: Expression *keysave = key ? key->value : NULL; 937: Expression *valuesave = value->value; 938: 939: uinteger_t d = dim->toUInteger(); 940: uinteger_t index; 941: 942: if (op == TOKforeach) 943: { 944: for (index = 0; index < d; index++) 945: { 946: Expression *ekey = new IntegerExp(loc, index, Type::tsize_t); 947: if (key) 948: key->value = ekey; 949: e = Index(value->type, eaggr, ekey); 950: if (e == EXP_CANT_INTERPRET) 951: break; 952: value->value = e; 953: 954: e = body ? body->interpret(istate) : NULL; 955: if (e == EXP_CANT_INTERPRET) 956: break; 957: if (e == EXP_BREAK_INTERPRET) 958: { 959: if (!istate->gotoTarget || istate->gotoTarget == this) 960: { 961: istate->gotoTarget = NULL; 962: e = NULL; 963: } // else break at a higher level 964: break; 965: } 966: if (e == EXP_CONTINUE_INTERPRET) 967: { 968: if (istate->gotoTarget && istate->gotoTarget != this) 969: break; // continue at higher level 970: istate->gotoTarget = NULL; 971: e = NULL; 972: } 973: else if (e) 974: break; 975: } 976: } 977: else // TOKforeach_reverse 978: { 979: for (index = d; index-- != 0;) 980: { 981: Expression *ekey = new IntegerExp(loc, index, Type::tsize_t); 982: if (key) 983: key->value = ekey; 984: e = Index(value->type, eaggr, ekey); 985: if (e == EXP_CANT_INTERPRET) 986: break; 987: value->value = e; 988: 989: e = body ? body->interpret(istate) : NULL; 990: if (e == EXP_CANT_INTERPRET) 991: break; 992: if (e == EXP_BREAK_INTERPRET) 993: { 994: if (!istate->gotoTarget || istate->gotoTarget == this) 995: { 996: istate->gotoTarget = NULL; 997: e = NULL; 998: } // else break at a higher level 999: break; 1000: } 1001: if (e == EXP_CONTINUE_INTERPRET) 1002: { 1003: if (istate->gotoTarget && istate->gotoTarget != this) 1004: break; // continue at higher level 1005: istate->gotoTarget = NULL; 1006: e = NULL; 1007: } 1008: else if (e) 1009: break; 1010: } 1011: } 1012: value->value = valuesave; 1013: if (key) 1014: key->value = keysave; 1015: return e; 1016: #endif 1017: } 1018: 1019: #if DMDV2 1020: Expression *ForeachRangeStatement::interpret(InterState *istate) 1021: { 1022: #if 1 1023: assert(0); // rewritten to ForStatement 1024: return NULL; 1025: #else 1026: #if LOG 1027: printf("ForeachRangeStatement::interpret()\n"); 1028: #endif 1029: if (istate->start == this) 1030: istate->start = NULL; 1031: if (istate->start) 1032: return NULL; 1033: 1034: Expression *e = NULL; 1035: Expression *elwr = lwr->interpret(istate); 1036: if (elwr == EXP_CANT_INTERPRET) 1037: return EXP_CANT_INTERPRET; 1038: 1039: Expression *eupr = upr->interpret(istate); 1040: if (eupr == EXP_CANT_INTERPRET) 1041: return EXP_CANT_INTERPRET; 1042: 1043: Expression *keysave = key->value; 1044: 1045: if (op == TOKforeach) 1046: { 1047: key->value = elwr; 1048: 1049: while (1) 1050: { 1051: e = Cmp(TOKlt, key->value->type, key->value, eupr); 1052: if (e == EXP_CANT_INTERPRET) 1053: break; 1054: if (e->isBool(TRUE) == FALSE) 1055: { e = NULL; 1056: break; 1057: } 1058: 1059: e = body ? body->interpret(istate) : NULL; 1060: if (e == EXP_CANT_INTERPRET) 1061: break; 1062: if (e == EXP_BREAK_INTERPRET) 1063: { 1064: if (!istate->gotoTarget || istate->gotoTarget == this) 1065: { 1066: istate->gotoTarget = NULL; 1067: e = NULL; 1068: } // else break at a higher level 1069: break; 1070: } 1071: if (e == EXP_CONTINUE_INTERPRET 1072: && istate->gotoTarget && istate->gotoTarget != this) 1073: break; // continue at higher level 1074: if (e == NULL || e == EXP_CONTINUE_INTERPRET) 1075: { e = Add(key->value->type, key->value, new IntegerExp(loc, 1, key->value->type)); 1076: istate->gotoTarget = NULL; 1077: if (e == EXP_CANT_INTERPRET) 1078: break; 1079: key->value = e; 1080: } 1081: else 1082: break; 1083: } 1084: } 1085: else // TOKforeach_reverse 1086: { 1087: key->value = eupr; 1088: 1089: do 1090: { 1091: e = Cmp(TOKgt, key->value->type, key->value, elwr); 1092: if (e == EXP_CANT_INTERPRET) 1093: break; 1094: if (e->isBool(TRUE) == FALSE) 1095: { e = NULL; 1096: break; 1097: } 1098: 1099: e = Min(key->value->type, key->value, new IntegerExp(loc, 1, key->value->type)); 1100: if (e == EXP_CANT_INTERPRET) 1101: break; 1102: key->value = e; 1103: 1104: e = body ? body->interpret(istate) : NULL; 1105: if (e == EXP_CANT_INTERPRET) 1106: break; 1107: if (e == EXP_BREAK_INTERPRET) 1108: { 1109: if (!istate->gotoTarget || istate->gotoTarget == this) 1110: { 1111: istate->gotoTarget = NULL; 1112: e = NULL; 1113: } // else break at a higher level 1114: break; 1115: } 1116: if (e == EXP_CONTINUE_INTERPRET) 1117: { 1118: if (istate->gotoTarget && istate->gotoTarget != this) 1119: break; // continue at higher level 1120: istate->gotoTarget = NULL; 1121: } 1122: } while (e == NULL || e == EXP_CONTINUE_INTERPRET); 1123: } 1124: key->value = keysave; 1125: return e; 1126: #endif 1127: } 1128: #endif 1129: 1130: Expression *SwitchStatement::interpret(InterState *istate) 1131: { 1132: #if LOG 1133: printf("SwitchStatement::interpret()\n"); 1134: #endif 1135: if (istate->start == this) 1136: istate->start = NULL; 1137: Expression *e = NULL; 1138: 1139: if (istate->start) 1140: { 1141: e = body ? body->interpret(istate) : NULL; 1142: if (istate->start) 1143: return NULL; 1144: if (e == EXP_CANT_INTERPRET) 1145: return e; 1146: if (e == EXP_BREAK_INTERPRET) 1147: { 1148: if (!istate->gotoTarget || istate->gotoTarget == this) 1149: { 1150: istate->gotoTarget = NULL; 1151: return NULL; 1152: } // else break at a higher level 1153: } 1154: return e; 1155: } 1156: 1157: 1158: Expression *econdition = condition->interpret(istate); 1159: if (econdition == EXP_CANT_INTERPRET) 1160: return EXP_CANT_INTERPRET; 1161: if (econdition->op == TOKslice) 1162: econdition = resolveSlice(econdition); 1163: 1164: Statement *s = NULL; 1165: if (cases) 1166: { 1167: for (size_t i = 0; i < cases->dim; i++) 1168: { 1169: CaseStatement *cs = cases->tdata()[i]; 1170: e = ctfeEqual(TOKequal, Type::tint32, econdition, cs->exp); 1171: if (e == EXP_CANT_INTERPRET) 1172: return EXP_CANT_INTERPRET; 1173: if (e->isBool(TRUE)) 1174: { s = cs; 1175: break; 1176: } 1177: } 1178: } 1179: if (!s) 1180: { if (hasNoDefault) 1181: error("no default or case for %s in switch statement", econdition->toChars()); 1182: s = sdefault; 1183: } 1184: 1185: assert(s); 1186: istate->start = s; 1187: e = body ? body->interpret(istate) : NULL; 1188: assert(!istate->start); 1189: if (e == EXP_BREAK_INTERPRET) 1190: { 1191: if (!istate->gotoTarget || istate->gotoTarget == this) 1192: { 1193: istate->gotoTarget = NULL; 1194: e = NULL; 1195: } // else break at a higher level 1196: } 1197: return e; 1198: } 1199: 1200: Expression *CaseStatement::interpret(InterState *istate) 1201: { 1202: #if LOG 1203: printf("CaseStatement::interpret(%s) this = %p\n", exp->toChars(), this); 1204: #endif 1205: if (istate->start == this) 1206: istate->start = NULL; 1207: if (statement) 1208: return statement->interpret(istate); 1209: else 1210: return NULL; 1211: } 1212: 1213: Expression *DefaultStatement::interpret(InterState *istate) 1214: { 1215: #if LOG 1216: printf("DefaultStatement::interpret()\n"); 1217: #endif 1218: if (istate->start == this) 1219: istate->start = NULL; 1220: if (statement) 1221: return statement->interpret(istate); 1222: else 1223: return NULL; 1224: } 1225: 1226: Expression *GotoStatement::interpret(InterState *istate) 1227: { 1228: #if LOG 1229: printf("GotoStatement::interpret()\n"); 1230: #endif 1231: START() 1232: assert(label && label->statement); 1233: istate->gotoTarget = label->statement; 1234: return EXP_GOTO_INTERPRET; 1235: } 1236: 1237: Expression *GotoCaseStatement::interpret(InterState *istate) 1238: { 1239: #if LOG 1240: printf("GotoCaseStatement::interpret()\n"); 1241: #endif 1242: START() 1243: assert(cs); 1244: istate->gotoTarget = cs; 1245: return EXP_GOTO_INTERPRET; 1246: } 1247: 1248: Expression *GotoDefaultStatement::interpret(InterState *istate) 1249: { 1250: #if LOG 1251: printf("GotoDefaultStatement::interpret()\n"); 1252: #endif 1253: START() 1254: assert(sw && sw->sdefault); 1255: istate->gotoTarget = sw->sdefault; 1256: return EXP_GOTO_INTERPRET; 1257: } 1258: 1259: Expression *LabelStatement::interpret(InterState *istate) 1260: { 1261: #if LOG 1262: printf("LabelStatement::interpret()\n"); 1263: #endif 1264: if (istate->start == this) 1265: istate->start = NULL; 1266: return statement ? statement->interpret(istate) : NULL; 1267: } 1268: 1269: 1270: Expression *TryCatchStatement::interpret(InterState *istate) 1271: { 1272: #if LOG 1273: printf("TryCatchStatement::interpret()\n"); 1274: #endif 1275: START() 1276: error("try-catch statements are not yet supported in CTFE"); 1277: return EXP_CANT_INTERPRET; 1278: } 1279: 1280: 1281: Expression *TryFinallyStatement::interpret(InterState *istate) 1282: { 1283: #if LOG 1284: printf("TryFinallyStatement::interpret()\n"); 1285: #endif 1286: START() 1287: error("try-finally statements are not yet supported in CTFE"); 1288: return EXP_CANT_INTERPRET; 1289: } 1290: 1291: Expression *ThrowStatement::interpret(InterState *istate) 1292: { 1293: #if LOG 1294: printf("ThrowStatement::interpret()\n"); 1295: #endif 1296: START() 1297: error("throw statements are not yet supported in CTFE"); 1298: return EXP_CANT_INTERPRET; 1299: } 1300: 1301: Expression *OnScopeStatement::interpret(InterState *istate) 1302: { 1303: #if LOG 1304: printf("OnScopeStatement::interpret()\n"); 1305: #endif 1306: START() 1307: error("scope guard statements are not yet supported in CTFE"); 1308: return EXP_CANT_INTERPRET; 1309: } 1310: 1311: Expression *WithStatement::interpret(InterState *istate) 1312: { 1313: #if LOG 1314: printf("WithStatement::interpret()\n"); 1315: #endif 1316: START() 1317: error("with statements are not yet supported in CTFE"); 1318: return EXP_CANT_INTERPRET; 1319: } 1320: 1321: Expression *AsmStatement::interpret(InterState *istate) 1322: { 1323: #if LOG 1324: printf("AsmStatement::interpret()\n"); 1325: #endif 1326: START() 1327: error("asm statements cannot be interpreted at compile time"); 1328: return EXP_CANT_INTERPRET; 1329: } 1330: 1331: #if DMDV2 1332: Expression *ImportStatement::interpret(InterState *istate) 1333: { 1334: #if LOG 1335: printf("ImportStatement::interpret()\n"); 1336: #endif 1337: START(); 1338: return NULL; 1339: } 1340: #endif 1341: 1342: /******************************** Expression ***************************/ 1343: 1344: Expression *Expression::interpret(InterState *istate, CtfeGoal goal) 1345: { 1346: #if LOG 1347: printf("Expression::interpret() %s\n", toChars()); 1348: printf("type = %s\n", type->toChars()); 1349: dump(0); 1350: #endif 1351: error("Cannot interpret %s at compile time", toChars()); 1352: return EXP_CANT_INTERPRET; 1353: } 1354: 1355: Expression *ThisExp::interpret(InterState *istate, CtfeGoal goal) 1356: { 1357: if (istate && istate->localThis && istate->localThis->op == TOKstructliteral) 1358: return istate->localThis; 1359: if (istate && istate->localThis) 1360: return istate->localThis->interpret(istate, goal); 1361: error("value of 'this' is not known at compile time"); 1362: return EXP_CANT_INTERPRET; 1363: } 1364: 1365: Expression *NullExp::interpret(InterState *istate, CtfeGoal goal) 1366: { 1367: return this; 1368: } 1369: 1370: Expression *IntegerExp::interpret(InterState *istate, CtfeGoal goal) 1371: { 1372: #if LOG 1373: printf("IntegerExp::interpret() %s\n", toChars()); 1374: #endif 1375: return this; 1376: } 1377: 1378: Expression *RealExp::interpret(InterState *istate, CtfeGoal goal) 1379: { 1380: #if LOG 1381: printf("RealExp::interpret() %s\n", toChars()); 1382: #endif 1383: return this; 1384: } 1385: 1386: Expression *ComplexExp::interpret(InterState *istate, CtfeGoal goal) 1387: { 1388: return this; 1389: } 1390: 1391: Expression *StringExp::interpret(InterState *istate, CtfeGoal goal) 1392: { 1393: #if LOG 1394: printf("StringExp::interpret() %s\n", toChars()); 1395: #endif 1396: /* Since we are using StringExps as reference types for char[] arrays, 1397: * we need to dup them if there's any chance they'll be modified. 1398: * For efficiency, we try to only dup when necessary. 1399: */ 1400: // Fixed-length char arrays always get duped later anyway. 1401: if (type->ty == Tsarray) 1402: return this; 1403: /* String literals are normally immutable, so we don't need to dup them 1404: * In D2, we can detect attempts to write to read-only literals. 1405: * For D1, we could be pessimistic, and always dup. 1406: * But since it fails only when there has been an explicit cast, and any 1407: * such function would give different results at runtime anyway (eg, it 1408: * may crash), it hardly seems worth the massive performance hit. 1409: */ 1410: #if DMDV2 1411: if (!((TypeNext *)type)->next->mod & (MODconst | MODimmutable))
warning C4806: '&' : unsafe operation: no value of type 'bool' promoted to type 'int' can equal the given constant
warning C6290: Bitwise operation on logical result: ! has higher precedence than &. Use && or (!(x & y)) instead
1412: { // It seems this happens only when there has been an explicit cast 1413: error("cannot cast a read-only string literal to mutable in CTFE"); 1414: return EXP_CANT_INTERPRET; 1415: } 1416: #endif 1417: return this; 1418: } 1419: 1420: Expression *FuncExp::interpret(InterState *istate, CtfeGoal goal) 1421: { 1422: #if LOG 1423: printf("FuncExp::interpret() %s\n", toChars()); 1424: #endif 1425: return this; 1426: } 1427: 1428: Expression *SymOffExp::interpret(InterState *istate, CtfeGoal goal) 1429: { 1430: #if LOG 1431: printf("SymOffExp::interpret() %s\n", toChars()); 1432: #endif 1433: if (var->isFuncDeclaration() && offset == 0) 1434: { 1435: return this; 1436: } 1437: if (type->ty != Tpointer) 1438: { // Probably impossible 1439: error("Cannot interpret %s at compile time", toChars()); 1440: return EXP_CANT_INTERPRET; 1441: } 1442: Type *pointee = ((TypePointer *)type)->next; 1443: Expression *val = getVarExp(loc, istate, var, goal); 1444: if (val->type->ty == Tarray || val->type->ty == Tsarray) 1445: { 1446: TypeArray *tar = (TypeArray *)val->type; 1447: dinteger_t sz = pointee->size(); 1448: dinteger_t indx = offset/sz; 1449: assert(sz * indx == offset); 1450: Expression *aggregate = NULL; 1451: if (val->op == TOKarrayliteral || val->op == TOKstring) 1452: aggregate = val; 1453: else if (val->op == TOKslice) 1454: { 1455: aggregate = ((SliceExp *)val)->e1; 1456: Expression *lwr = ((SliceExp *)val)->lwr->interpret(istate); 1457: indx += lwr->toInteger(); 1458: } 1459: if (aggregate) 1460: { 1461: IntegerExp *ofs = new IntegerExp(loc, indx, Type::tsize_t); 1462: IndexExp *ie = new IndexExp(loc, aggregate, ofs); 1463: ie->type = type; 1464: return ie; 1465: } 1466: } 1467: else if (offset == 0 && pointee == var->type) 1468: { 1469: if (goal == ctfeNeedLvalue || goal == ctfeNeedLvalueRef) 1470: { 1471: VarExp *ve = new VarExp(loc, var); 1472: ve->type = type; 1473: return ve; 1474: } 1475: Expression *e = getVarExp(loc, istate, var, goal); 1476: e = new AddrExp(loc, e); 1477: e->type = type; 1478: return e; 1479: } 1480: 1481: error("Cannot interpret %s at compile time", toChars()); 1482: return EXP_CANT_INTERPRET; 1483: } 1484: 1485: Expression *AddrExp::interpret(InterState *istate, CtfeGoal goal) 1486: { 1487: #if LOG 1488: printf("AddrExp::interpret() %s\n", toChars()); 1489: #endif 1490: // For reference types, we need to return an lvalue ref. 1491: TY tb = e1->type->toBasetype()->ty; 1492: bool needRef = (tb == Tarray || tb == Taarray || tb == Tclass); 1493: Expression *e = e1->interpret(istate, needRef ? ctfeNeedLvalueRef : ctfeNeedLvalue); 1494: if (e == EXP_CANT_INTERPRET) 1495: return e; 1496: // Return a simplified address expression 1497: e = new AddrExp(loc, e); 1498: e->type = type; 1499: return e; 1500: } 1501: 1502: Expression *DelegateExp::interpret(InterState *istate, CtfeGoal goal) 1503: { 1504: #if LOG 1505: printf("DelegateExp::interpret() %s\n", toChars()); 1506: #endif 1507: return this; 1508: } 1509: 1510: 1511: // ------------------------------------------------------------- 1512: // Remove out, ref, and this 1513: // ------------------------------------------------------------- 1514: // The variable used in a dotvar, index, or slice expression, 1515: // after 'out', 'ref', and 'this' have been removed. 1516: // *isReference will be set to true if a reference was removed. 1517: Expression * resolveReferences(Expression *e, Expression *thisval, bool *isReference /*=NULL */) 1518: { 1519: if (isReference) 1520: *isReference = false; 1521: for(;;) 1522: { 1523: if (e->op == TOKthis) 1524: { 1525: assert(thisval); 1526: assert(e != thisval); 1527: e = thisval; 1528: continue; 1529: } 1530: if (e->op == TOKvar) { 1531: // Chase down rebinding of out and ref. 1532: VarExp *ve = (VarExp *)e; 1533: VarDeclaration *v = ve->var->isVarDeclaration(); 1534: if (v->type->ty == Tpointer) 1535: break; 1536: if (v && v->getValue() && v->getValue()->op == TOKvar) // it's probably a reference 1537: { 1538: // Make sure it's a real reference. 1539: // It's not a reference if v is a struct initialized to 1540: // 0 using an __initZ SymbolDeclaration from 1541: // TypeStruct::defaultInit() 1542: VarExp *ve2 = (VarExp *)v->getValue(); 1543: if (!ve2->var->isSymbolDeclaration()) 1544: { 1545: if (isReference) 1546: *isReference = true; 1547: e = v->getValue(); 1548: continue; 1549: } 1550: } 1551: else if (v && v->getValue() && (v->getValue()->op == TOKslice)) 1552: { 1553: SliceExp *se = (SliceExp *)v->getValue(); 1554: if (se->e1->op == TOKarrayliteral || se->e1->op == TOKassocarrayliteral || se->e1->op == TOKstring) 1555: break; 1556: e = v->getValue(); 1557: continue; 1558: } 1559: else if (v && v->getValue() && (v->getValue()->op==TOKindex || v->getValue()->op == TOKdotvar 1560: || v->getValue()->op == TOKthis )) 1561: { 1562: e = v->getValue(); 1563: continue; 1564: } 1565: } 1566: break; 1567: } 1568: return e; 1569: } 1570: 1571: Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal) 1572: { 1573: Expression *e = EXP_CANT_INTERPRET; 1574: VarDeclaration *v = d->isVarDeclaration(); 1575: SymbolDeclaration *s = d->isSymbolDeclaration(); 1576: if (v) 1577: { 1578: #if DMDV2 1579: /* Magic variable __ctfe always returns true when interpreting 1580: */ 1581: if (v->ident == Id::ctfe) 1582: return new IntegerExp(loc, 1, Type::tbool); 1583: if ((v->isConst() || v->isImmutable() || v->storage_class & STCmanifest) && v->init && !v->getValue()) 1584: #else 1585: if (v->isConst() && v->init) 1586: #endif 1587: { e = v->init->toExpression(); 1588: if (e && (e->op == TOKconstruct || e->op == TOKblit)) 1589: { AssignExp *ae = (AssignExp *)e; 1590: e = ae->e2; 1591: v->inuse++; 1592: e = e->interpret(istate, ctfeNeedAnyValue); 1593: v->inuse--; 1594: if (e == EXP_CANT_INTERPRET) 1595: return e; 1596: e->type = v->type; 1597: } 1598: else 1599: { 1600: if (e && !e->type) 1601: e->type = v->type; 1602: if (e) 1603: e = e->interpret(istate, ctfeNeedAnyValue); 1604: } 1605: if (e && e != EXP_CANT_INTERPRET) 1606: v->setValueWithoutChecking(e); 1607: } 1608: else if (v->isCTFE() && !v->getValue()) 1609: { 1610: if (v->init && v->type->size() != 0) 1611: { 1612: if (v->init->isVoidInitializer()) 1613: { 1614: error(loc, "variable %s is used before initialization", v->toChars()); 1615: return EXP_CANT_INTERPRET; 1616: } 1617: e = v->init->toExpression(); 1618: e = e->interpret(istate); 1619: } 1620: else 1621: e = v->type->defaultInitLiteral(loc); 1622: } 1623: else if (!v->isDataseg() && !v->isCTFE() && !istate) 1624: { error(loc, "variable %s cannot be read at compile time", v->toChars()); 1625: return EXP_CANT_INTERPRET; 1626: } 1627: else 1628: { e = v->getValue(); 1629: if (!e && !v->isCTFE() && v->isDataseg()) 1630: { error(loc, "static variable %s cannot be read at compile time", v->toChars()); 1631: e = EXP_CANT_INTERPRET; 1632: } 1633: else if (!e) 1634: error(loc, "variable %s is used before initialization", v->toChars()); 1635: else if (e == EXP_CANT_INTERPRET) 1636: return e; 1637: else if ((goal == ctfeNeedLvalue) 1638: || e->op == TOKstring || e->op == TOKstructliteral || e->op == TOKarrayliteral 1639: || e->op == TOKassocarrayliteral || e->op == TOKslice 1640: || e->type->toBasetype()->ty == Tpointer) 1641: return e; // it's already an Lvalue 1642: else 1643: e = e->interpret(istate, goal); 1644: } 1645: if (!e) 1646: e = EXP_CANT_INTERPRET; 1647: } 1648: else if (s) 1649: { // Struct static initializers, for example 1650: if (s->dsym->toInitializer() == s->sym) 1651: { Expressions *exps = new Expressions(); 1652: e = new StructLiteralExp(loc, s->dsym, exps); 1653: e = e->semantic(NULL); 1654: if (e->op == TOKerror) 1655: e = EXP_CANT_INTERPRET; 1656: } 1657: else 1658: error(loc, "cannot interpret symbol %s at compile time", v->toChars()); 1659: } 1660: else 1661: error(loc, "cannot interpret variable %s at compile time", v->toChars()); 1662: return e; 1663: } 1664: 1665: Expression *VarExp::interpret(InterState *istate, CtfeGoal goal) 1666: { 1667: #if LOG 1668: printf("VarExp::interpret() %s\n", toChars()); 1669: #endif 1670: if (goal == ctfeNeedLvalueRef) 1671: { 1672: // If it is a reference, return the thing it's pointing to. 1673: VarDeclaration *v = var->isVarDeclaration(); 1674: if (v && v->getValue() && (v->storage_class & (STCref | STCout))) 1675: return v->getValue(); 1676: if (v && !v->isDataseg() && !v->isCTFE() && !istate) 1677: { error("variable %s cannot be referenced at compile time", v->toChars()); 1678: return EXP_CANT_INTERPRET; 1679: } 1680: else if (v && !v->getValue() && !v->isCTFE() && v->isDataseg()) 1681: { error("static variable %s cannot be referenced at compile time", v->toChars()); 1682: return EXP_CANT_INTERPRET; 1683: } 1684: return this; 1685: } 1686: Expression *e = getVarExp(loc, istate, var, goal); 1687: // A VarExp may include an implicit cast. It must be done explicitly. 1688: if (e != EXP_CANT_INTERPRET) 1689: e = paintTypeOntoLiteral(type, e); 1690: return e; 1691: } 1692: 1693: Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal) 1694: { 1695: #if LOG 1696: printf("DeclarationExp::interpret() %s\n", toChars()); 1697: #endif 1698: Expression *e; 1699: VarDeclaration *v = declaration->isVarDeclaration(); 1700: if (v) 1701: { 1702: if (v->getValue()) 1703: { 1704: addVarToInterstate(istate, v); 1705: v->setValueNull(); 1706: } 1707: Dsymbol *s = v->toAlias(); 1708: if (s == v && !v->isStatic() && v->init) 1709: { 1710: ExpInitializer *ie = v->init->isExpInitializer(); 1711: if (ie) 1712: e = ie->exp->interpret(istate); 1713: else if (v->init->isVoidInitializer()) 1714: e = NULL; 1715: else 1716: { 1717: error("Declaration %s is not yet implemented in CTFE", toChars()); 1718: e = EXP_CANT_INTERPRET; 1719: } 1720: } 1721: else if (s == v && !v->init && v->type->size()==0) 1722: { // Zero-length arrays don't need an initializer 1723: e = v->type->defaultInitLiteral(loc); 1724: } 1725: #if DMDV2 1726: else if (s == v && (v->isConst() || v->isImmutable()) && v->init) 1727: #else 1728: else if (s == v && v->isConst() && v->init) 1729: #endif 1730: { e = v->init->toExpression(); 1731: if (!e) 1732: e = EXP_CANT_INTERPRET; 1733: else if (!e->type) 1734: e->type = v->type; 1735: } 1736: else if (s->isTupleDeclaration() && !v->init) 1737: e = NULL; 1738: else 1739: { 1740: error("Declaration %s is not yet implemented in CTFE", toChars()); 1741: e = EXP_CANT_INTERPRET; 1742: } 1743: } 1744: else if (declaration->isAttribDeclaration() || 1745: declaration->isTemplateMixin() || 1746: declaration->isTupleDeclaration()) 1747: { // These can be made to work, too lazy now 1748: error("Declaration %s is not yet implemented in CTFE", toChars()); 1749: e = EXP_CANT_INTERPRET; 1750: } 1751: else 1752: { // Others should not contain executable code, so are trivial to evaluate 1753: e = NULL; 1754: } 1755: #if LOG 1756: printf("-DeclarationExp::interpret(%s): %p\n", toChars(), e); 1757: #endif 1758: return e; 1759: } 1760: 1761: Expression *TupleExp::interpret(InterState *istate, CtfeGoal goal) 1762: { 1763: #if LOG 1764: printf("TupleExp::interpret() %s\n", toChars()); 1765: #endif 1766: Expressions *expsx = NULL; 1767: 1768: for (size_t i = 0; i < exps->dim; i++) 1769: { Expression *e = exps->tdata()[i]; 1770: Expression *ex; 1771: 1772: ex = e->interpret(istate); 1773: if (ex == EXP_CANT_INTERPRET) 1774: { delete expsx; 1775: return ex; 1776: } 1777: 1778: // A tuple of assignments can contain void (Bug 5676). 1779: if (goal == ctfeNeedNothing) 1780: continue; 1781: if (ex == EXP_VOID_INTERPRET) 1782: { 1783: error("ICE: void element %s in tuple", e->toChars()); 1784: assert(0); 1785: } 1786: 1787: /* If any changes, do Copy On Write 1788: */ 1789: if (ex != e) 1790: { 1791: if (!expsx) 1792: { expsx = new Expressions(); 1793: expsx->setDim(exps->dim); 1794: for (size_t j = 0; j < i; j++) 1795: { 1796: expsx->tdata()[j] = exps->tdata()[j]; 1797: } 1798: } 1799: expsx->tdata()[i] = ex; 1800: } 1801: } 1802: if (expsx) 1803: { TupleExp *te = new TupleExp(loc, expsx);
warning C6211: Leaking memory 'te' due to an exception. Consider using a local catch block to clean up memory: Lines: 1766, 1768, 1769, 1770, 1772, 1773, 1779, 1781, 1789, 1791, 1792, 1793, 1794, 1799, 1768, 1769, 1770, 1772, 1773, 1779, 1781, 1789, 1791, 1799, 1768, 1802, 1803, 1804, 1805
1804: expandTuples(te->exps); 1805: te->type = new TypeTuple(te->exps); 1806: return te; 1807: } 1808: return this; 1809: } 1810: 1811: Expression *ArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal) 1812: { Expressions *expsx = NULL; 1813: 1814: #if LOG 1815: printf("ArrayLiteralExp::interpret() %s\n", toChars()); 1816: #endif 1817: if (elements) 1818: { 1819: for (size_t i = 0; i < elements->dim; i++) 1820: { Expression *e = elements->tdata()[i]; 1821: Expression *ex; 1822: 1823: if (e->op == TOKindex) // segfault bug 6250 1824: assert( ((IndexExp*)e)->e1 != this); 1825: ex = e->interpret(istate); 1826: if (ex == EXP_CANT_INTERPRET) 1827: goto Lerror; 1828: 1829: /* If any changes, do Copy On Write 1830: */ 1831: if (ex != e) 1832: { 1833: if (!expsx) 1834: { expsx = new Expressions(); 1835: expsx->setDim(elements->dim); 1836: for (size_t j = 0; j < elements->dim; j++) 1837: { 1838: expsx->tdata()[j] = elements->tdata()[j]; 1839: } 1840: } 1841: expsx->tdata()[i] = ex; 1842: } 1843: } 1844: } 1845: if (elements && expsx) 1846: { 1847: expandTuples(expsx); 1848: if (expsx->dim != elements->dim) 1849: goto Lerror; 1850: ArrayLiteralExp *ae = new ArrayLiteralExp(loc, expsx); 1851: ae->type = type; 1852: return ae; 1853: } 1854: #if DMDV2 1855: if (((TypeNext *)type)->next->mod & (MODconst | MODimmutable)) 1856: { // If it's immutable, we don't need to dup it 1857: return this; 1858: } 1859: #endif 1860: return copyLiteral(this); 1861: 1862: Lerror: 1863: if (expsx) 1864: delete expsx; 1865: error("cannot interpret array literal"); 1866: return EXP_CANT_INTERPRET; 1867: } 1868: 1869: Expression *AssocArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal) 1870: { Expressions *keysx = keys; 1871: Expressions *valuesx = values; 1872: 1873: #if LOG 1874: printf("AssocArrayLiteralExp::interpret() %s\n", toChars()); 1875: #endif 1876: for (size_t i = 0; i < keys->dim; i++) 1877: { Expression *ekey = keys->tdata()[i]; 1878: Expression *evalue = values->tdata()[i]; 1879: Expression *ex; 1880: 1881: ex = ekey->interpret(istate); 1882: if (ex == EXP_CANT_INTERPRET) 1883: goto Lerr; 1884: 1885: /* If any changes, do Copy On Write 1886: */ 1887: if (ex != ekey) 1888: { 1889: if (keysx == keys) 1890: keysx = (Expressions *)keys->copy(); 1891: keysx->tdata()[i] = ex; 1892: } 1893: 1894: ex = evalue->interpret(istate); 1895: if (ex == EXP_CANT_INTERPRET) 1896: goto Lerr; 1897: 1898: /* If any changes, do Copy On Write 1899: */ 1900: if (ex != evalue) 1901: { 1902: if (valuesx == values) 1903: valuesx = (Expressions *)values->copy(); 1904: valuesx->tdata()[i] = ex; 1905: } 1906: } 1907: if (keysx != keys) 1908: expandTuples(keysx); 1909: if (valuesx != values) 1910: expandTuples(valuesx); 1911: if (keysx->dim != valuesx->dim) 1912: goto Lerr; 1913: 1914: /* Remove duplicate keys 1915: */ 1916: for (size_t i = 1; i < keysx->dim; i++) 1917: { Expression *ekey = keysx->tdata()[i - 1]; 1918: if (ekey->op == TOKslice) 1919: ekey = resolveSlice(ekey); 1920: for (size_t j = i; j < keysx->dim; j++) 1921: { Expression *ekey2 = keysx->tdata()[j]; 1922: Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, ekey2); 1923: if (ex == EXP_CANT_INTERPRET) 1924: goto Lerr; 1925: if (ex->isBool(TRUE)) // if a match 1926: { 1927: // Remove ekey 1928: if (keysx == keys) 1929: keysx = (Expressions *)keys->copy(); 1930: if (valuesx == values) 1931: valuesx = (Expressions *)values->copy(); 1932: keysx->remove(i - 1); 1933: valuesx->remove(i - 1); 1934: i -= 1; // redo the i'th iteration 1935: break; 1936: } 1937: } 1938: } 1939: 1940: if (keysx != keys || valuesx != values) 1941: { 1942: AssocArrayLiteralExp *ae; 1943: ae = new AssocArrayLiteralExp(loc, keysx, valuesx); 1944: ae->type = type; 1945: return ae; 1946: } 1947: return this; 1948: 1949: Lerr: 1950: if (keysx != keys) 1951: delete keysx; 1952: if (valuesx != values) 1953: delete values; 1954: return EXP_CANT_INTERPRET; 1955: } 1956: 1957: Expression *StructLiteralExp::interpret(InterState *istate, CtfeGoal goal) 1958: { Expressions *expsx = NULL; 1959: 1960: #if LOG 1961: printf("StructLiteralExp::interpret() %s\n", toChars()); 1962: #endif 1963: /* We don't know how to deal with overlapping fields 1964: */ 1965: if (sd->hasUnions) 1966: { error("Unions with overlapping fields are not yet supported in CTFE"); 1967: return EXP_CANT_INTERPRET; 1968: } 1969: 1970: if (elements) 1971: { 1972: for (size_t i = 0; i < elements->dim; i++) 1973: { Expression *e = elements->tdata()[i]; 1974: if (!e) 1975: continue; 1976: 1977: Expression *ex = e->interpret(istate); 1978: if (ex == EXP_CANT_INTERPRET) 1979: { delete expsx; 1980: return EXP_CANT_INTERPRET; 1981: } 1982: 1983: /* If any changes, do Copy On Write 1984: */ 1985: if (ex != e) 1986: { 1987: if (!expsx) 1988: { expsx = new Expressions(); 1989: expsx->setDim(elements->dim); 1990: for (size_t j = 0; j < elements->dim; j++) 1991: { 1992: expsx->tdata()[j] = elements->tdata()[j]; 1993: } 1994: } 1995: expsx->tdata()[i] = ex; 1996: } 1997: } 1998: } 1999: if (elements && expsx) 2000: { 2001: expandTuples(expsx); 2002: if (expsx->dim != elements->dim) 2003: { delete expsx; 2004: return EXP_CANT_INTERPRET; 2005: } 2006: StructLiteralExp *se = new StructLiteralExp(loc, sd, expsx); 2007: se->type = type; 2008: return se; 2009: } 2010: return copyLiteral(this); 2011: } 2012: 2013: /****************************** 2014: * Helper for NewExp 2015: * Create an array literal consisting of 'elem' duplicated 'dim' times. 2016: */ 2017: ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type, 2018: Expression *elem, size_t dim) 2019: { 2020: Expressions *elements = new Expressions(); 2021: elements->setDim(dim); 2022: for (size_t i = 0; i < dim; i++) 2023: elements->tdata()[i] = elem; 2024: ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements); 2025: ae->type = type; 2026: return ae; 2027: } 2028: 2029: /****************************** 2030: * Helper for NewExp 2031: * Create a string literal consisting of 'value' duplicated 'dim' times. 2032: */ 2033: StringExp *createBlockDuplicatedStringLiteral(Type *type, 2034: unsigned value, size_t dim, int sz) 2035: { 2036: unsigned char *s; 2037: s = (unsigned char *)mem.calloc(dim + 1, sz); 2038: for (int elemi=0; elemi<dim; ++elemi)
warning C4018: '<' : signed/unsigned mismatch
2039: { 2040: switch (sz) 2041: { 2042: case 1: s[elemi] = value; break; 2043: case 2: ((unsigned short *)s)[elemi] = value; break; 2044: case 4: ((unsigned *)s)[elemi] = value; break; 2045: default: assert(0); 2046: } 2047: } 2048: StringExp *se = new StringExp(0, s, dim); 2049: se->type = type; 2050: return se; 2051: } 2052: 2053: Expression *NewExp::interpret(InterState *istate, CtfeGoal goal) 2054: { 2055: #if LOG 2056: printf("NewExp::interpret() %s\n", toChars()); 2057: #endif 2058: if (newtype->ty == Tarray && arguments && arguments->dim == 1) 2059: { 2060: Expression *lenExpr = ((arguments->tdata()[0]))->interpret(istate); 2061: if (lenExpr == EXP_CANT_INTERPRET) 2062: return EXP_CANT_INTERPRET; 2063: return createBlockDuplicatedArrayLiteral(newtype, 2064: ((TypeArray *)newtype)->next->defaultInitLiteral(), 2065: lenExpr->toInteger());
warning C4244: 'argument' : conversion from 'dinteger_t' to 'size_t', possible loss of data
2066: } 2067: if (newtype->toBasetype()->ty == Tstruct) 2068: { 2069: Expression *se = newtype->defaultInitLiteral(); 2070: #if DMDV2 2071: if (member) 2072: { 2073: int olderrors = global.errors; 2074: member->interpret(istate, arguments, se); 2075: if (olderrors != global.errors) 2076: { 2077: error("cannot evaluate %s at compile time", toChars()); 2078: return EXP_CANT_INTERPRET; 2079: } 2080: } 2081: #else // The above code would fail on D1 because it doesn't use STRUCTTHISREF, 2082: // but that's OK because D1 doesn't have struct constructors anyway. 2083: assert(!member); 2084: #endif 2085: Expression *e = new AddrExp(loc, se); 2086: e->type = type; 2087: return e; 2088: } 2089: if (newtype->ty == Tclass) 2090: { 2091: error("classes are not yet supported in CTFE"); 2092: return EXP_CANT_INTERPRET; 2093: } 2094: error("Cannot interpret %s at compile time", toChars()); 2095: return EXP_CANT_INTERPRET; 2096: } 2097: 2098: Expression *UnaExp::interpretCommon(InterState *istate, CtfeGoal goal, Expression *(*fp)(Type *, Expression *)) 2099: { Expression *e; 2100: Expression *e1; 2101: 2102: #if LOG 2103: printf("UnaExp::interpretCommon() %s\n", toChars()); 2104: #endif 2105: e1 = this->e1->interpret(istate); 2106: if (e1 == EXP_CANT_INTERPRET) 2107: goto Lcant; 2108: e = (*fp)(type, e1); 2109: return e; 2110: 2111: Lcant: 2112: return EXP_CANT_INTERPRET; 2113: } 2114: 2115: #define UNA_INTERPRET(op) \ 2116: Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \ 2117: { \ 2118: return interpretCommon(istate, goal, &op); \ 2119: } 2120: 2121: UNA_INTERPRET(Neg) 2122: UNA_INTERPRET(Com) 2123: UNA_INTERPRET(Not) 2124: UNA_INTERPRET(Bool) 2125: 2126: Expression *getAggregateFromPointer(Expression *e, dinteger_t *ofs) 2127: { 2128: *ofs = 0; 2129: if (e->op == TOKaddress) 2130: e = ((AddrExp *)e)->e1; 2131: if (e->op == TOKindex) 2132: { 2133: IndexExp *ie = (IndexExp *)e; 2134: // Note that each AA element is part of its own memory block 2135: if ((ie->e1->type->ty == Tarray || ie->e1->type->ty == Tsarray 2136: || ie->e1->op == TOKstring || ie->e1->op==TOKarrayliteral) && 2137: ie->e2->op == TOKint64) 2138: { 2139: *ofs = ie->e2->toInteger(); 2140: return ie->e1; 2141: } 2142: } 2143: return e; 2144: } 2145: 2146: // return e1 - e2 as an integer, or error if not possible 2147: Expression *pointerDifference(Loc loc, Type *type, Expression *e1, Expression *e2) 2148: { 2149: dinteger_t ofs1, ofs2; 2150: Expression *agg1 = getAggregateFromPointer(e1, &ofs1); 2151: Expression *agg2 = getAggregateFromPointer(e2, &ofs2); 2152: if (agg1 == agg2) 2153: { 2154: Type *pointee = ((TypePointer *)agg1->type)->next; 2155: dinteger_t sz = pointee->size(); 2156: return new IntegerExp(loc, (ofs1-ofs2)*sz, type); 2157: } 2158: else if (agg1->op == TOKstring && agg2->op == TOKstring) 2159: { 2160: if (((StringExp *)agg1)->string == ((StringExp *)agg2)->string) 2161: { 2162: Type *pointee = ((TypePointer *)agg1->type)->next; 2163: dinteger_t sz = pointee->size(); 2164: return new IntegerExp(loc, (ofs1-ofs2)*sz, type); 2165: } 2166: } 2167: #if LOGASSIGN 2168: printf("FAILED POINTER DIFF\n"); 2169: showCtfeExpr(agg1); 2170: showCtfeExpr(agg2); 2171: #endif 2172: error(loc, "%s - %s cannot be interpreted at compile time: cannot subtract " 2173: "pointers to two different memory blocks", 2174: e1->toChars(), e2->toChars()); 2175: return EXP_CANT_INTERPRET; 2176: } 2177: 2178: // Return eptr op e2, where eptr is a pointer, e2 is an integer, 2179: // and op is TOKadd or TOKmin 2180: Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type, 2181: Expression *eptr, Expression *e2) 2182: { 2183: dinteger_t ofs1, ofs2; 2184: if (eptr->op == TOKaddress) 2185: eptr = ((AddrExp *)eptr)->e1; 2186: Expression *agg1 = getAggregateFromPointer(eptr, &ofs1); 2187: if (agg1->op != TOKstring && agg1->op != TOKarrayliteral) 2188: { 2189: error(loc, "cannot perform pointer arithmetic on non-arrays at compile time"); 2190: return EXP_CANT_INTERPRET; 2191: } 2192: ofs2 = e2->toInteger(); 2193: Type *pointee = ((TypePointer *)agg1->type)->next; 2194: dinteger_t sz = pointee->size(); 2195: Expression *dollar = ArrayLength(Type::tsize_t, agg1); 2196: assert(dollar != EXP_CANT_INTERPRET); 2197: dinteger_t len = dollar->toInteger(); 2198: 2199: Expression *val = agg1; 2200: TypeArray *tar = (TypeArray *)val->type; 2201: dinteger_t indx = ofs1; 2202: if (op == TOKadd || op == TOKaddass) 2203: indx = indx + ofs2/sz; 2204: else if (op == TOKmin || op == TOKminass) 2205: indx -= ofs2/sz; 2206: else 2207: error(loc, "CTFE Internal compiler error: bad pointer operation"); 2208: if (val->op != TOKarrayliteral && val->op != TOKstring) 2209: { 2210: error(loc, "CTFE Internal compiler error: pointer arithmetic %s", val->toChars()); 2211: return EXP_CANT_INTERPRET; 2212: } 2213: if (indx < 0 || indx > len) 2214: { 2215: error(loc, "cannot assign pointer to index %jd inside memory block [0..%jd]", indx, len); 2216: return EXP_CANT_INTERPRET; 2217: } 2218: 2219: IntegerExp *ofs = new IntegerExp(loc, indx, Type::tsize_t); 2220: IndexExp *ie = new IndexExp(loc, val, ofs); 2221: ie->type = type; 2222: return ie; 2223: } 2224: 2225: typedef Expression *(*fp_t)(Type *, Expression *, Expression *); 2226: 2227: Expression *BinExp::interpretCommon(InterState *istate, CtfeGoal goal, fp_t fp) 2228: { Expression *e; 2229: Expression *e1; 2230: Expression *e2; 2231: 2232: #if LOG 2233: printf("BinExp::interpretCommon() %s\n", toChars()); 2234: #endif 2235: if (this->e1->type->ty == Tpointer && this->e2->type->ty == Tpointer && op == TOKmin) 2236: { 2237: e1 = this->e1->interpret(istate, ctfeNeedLvalue); 2238: e2 = this->e2->interpret(istate, ctfeNeedLvalue); 2239: return pointerDifference(loc, type, e1, e2); 2240: } 2241: if (this->e1->type->ty == Tpointer && this->e2->type->isintegral()) 2242: { 2243: e1 = this->e1->interpret(istate, ctfeNeedLvalue); 2244: e2 = this->e2->interpret(istate); 2245: if (e1 == EXP_CANT_INTERPRET || e2 == EXP_CANT_INTERPRET) 2246: return EXP_CANT_INTERPRET; 2247: return pointerArithmetic(loc, op, type, e1, e2); 2248: } 2249: if (this->e2->type->ty == Tpointer && this->e1->type->ty == TOKint64 && op==TOKadd) 2250: { 2251: e2 = this->e2->interpret(istate, ctfeNeedLvalue); 2252: e1 = this->e1->interpret(istate); 2253: return pointerArithmetic(loc, op, type, e2, e1); 2254: } 2255: if (this->e1->type->ty == Tpointer || this->e2->type->ty == Tpointer) 2256: { 2257: error("pointer expression %s cannot be interpreted at compile time", toChars()); 2258: return EXP_CANT_INTERPRET; 2259: } 2260: e1 = this->e1->interpret(istate); 2261: if (e1 == EXP_CANT_INTERPRET) 2262: goto Lcant; 2263: if (e1->isConst() != 1) 2264: goto Lcant; 2265: 2266: e2 = this->e2->interpret(istate); 2267: if (e2 == EXP_CANT_INTERPRET) 2268: goto Lcant; 2269: if (e2->isConst() != 1) 2270: goto Lcant; 2271: 2272: e = (*fp)(type, e1, e2); 2273: if (e == EXP_CANT_INTERPRET) 2274: error("%s cannot be interpreted at compile time", toChars()); 2275: return e; 2276: 2277: Lcant: 2278: return EXP_CANT_INTERPRET; 2279: } 2280: 2281: #define BIN_INTERPRET(op) \ 2282: Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \ 2283: { \ 2284: return interpretCommon(istate, goal, &op); \ 2285: } 2286: 2287: BIN_INTERPRET(Add) 2288: BIN_INTERPRET(Min) 2289: BIN_INTERPRET(Mul) 2290: BIN_INTERPRET(Div) 2291: BIN_INTERPRET(Mod) 2292: BIN_INTERPRET(Shl) 2293: BIN_INTERPRET(Shr) 2294: BIN_INTERPRET(Ushr) 2295: BIN_INTERPRET(And) 2296: BIN_INTERPRET(Or) 2297: BIN_INTERPRET(Xor) 2298: 2299: 2300: typedef Expression *(*fp2_t)(enum TOK, Type *, Expression *, Expression *); 2301: 2302: // Return EXP_CANT_INTERPRET if they point to independent memory blocks 2303: Expression *comparePointers(Loc loc, enum TOK op, Type *type, Expression *e1, Expression *e2) 2304: { 2305: dinteger_t ofs1, ofs2; 2306: Expression *agg1 = getAggregateFromPointer(e1, &ofs1); 2307: Expression *agg2 = getAggregateFromPointer(e2, &ofs2); 2308: if (agg1 == agg2 || 2309: (agg1->op == TOKstring && agg2->op == TOKstring && 2310: ((StringExp *)agg1)->string == ((StringExp *)agg2)->string)) 2311: 2312: { 2313: dinteger_t cm = ofs1 - ofs2; 2314: dinteger_t n; 2315: dinteger_t zero = 0; 2316: switch(op) 2317: { 2318: case TOKlt: n = (ofs1 < ofs2); break; 2319: case TOKle: n = (ofs1 <= ofs2); break; 2320: case TOKgt: n = (ofs1 > ofs2); break; 2321: case TOKge: n = (ofs1 >= ofs2); break; 2322: case TOKidentity: 2323: case TOKequal: n = (ofs1 == ofs2); break; 2324: case TOKnotidentity: 2325: case TOKnotequal: n = (ofs1 != ofs2); break; 2326: default: 2327: assert(0); 2328: } 2329: return new IntegerExp(loc, n, type); 2330: } 2331: int cmp; 2332: if (e1->op == TOKnull) 2333: { 2334: cmp = (e2->op == TOKnull); 2335: } 2336: else if (e2->op == TOKnull) 2337: { 2338: cmp = 0; 2339: } 2340: else 2341: { 2342: switch(op) 2343: { 2344: case TOKidentity: 2345: case TOKequal: 2346: case TOKnotidentity: // 'cmp' gets inverted below 2347: case TOKnotequal: 2348: cmp = 0; 2349: break; 2350: default: 2351: return EXP_CANT_INTERPRET; 2352: } 2353: } 2354: if (op == TOKnotidentity || op == TOKnotequal) 2355: cmp ^= 1; 2356: return new IntegerExp(loc, cmp, type); 2357: } 2358: 2359: Expression *BinExp::interpretCommon2(InterState *istate, CtfeGoal goal, fp2_t fp) 2360: { Expression *e; 2361: Expression *e1; 2362: Expression *e2; 2363: 2364: #if LOG 2365: printf("BinExp::interpretCommon2() %s\n", toChars()); 2366: #endif 2367: if (this->e1->type->ty == Tpointer && this->e2->type->ty == Tpointer) 2368: { 2369: e1 = this->e1->interpret(istate, ctfeNeedLvalue); 2370: e2 = this->e2->interpret(istate, ctfeNeedLvalue); 2371: e = comparePointers(loc, op, type, e1, e2); 2372: if (e == EXP_CANT_INTERPRET) 2373: { 2374: error("%s and %s point to independent memory blocks and " 2375: "cannot be compared at compile time", this->e1->toChars(), 2376: this->e2->toChars()); 2377: } 2378: return e; 2379: } 2380: e1 = this->e1->interpret(istate); 2381: if (e1 == EXP_CANT_INTERPRET) 2382: goto Lcant; 2383: if (e1->op == TOKslice) 2384: e1 = resolveSlice(e1); 2385: 2386: if (e1->isConst() != 1 && 2387: e1->op != TOKnull && 2388: e1->op != TOKstring && 2389: e1->op != TOKarrayliteral && 2390: e1->op != TOKstructliteral) 2391: { 2392: error("cannot compare %s at compile time", e1->toChars()); 2393: goto Lcant; 2394: } 2395: 2396: e2 = this->e2->interpret(istate); 2397: if (e2 == EXP_CANT_INTERPRET) 2398: goto Lcant; 2399: if (e2->op == TOKslice) 2400: e2 = resolveSlice(e2); 2401: if (e2->isConst() != 1 && 2402: e2->op != TOKnull && 2403: e2->op != TOKstring && 2404: e2->op != TOKarrayliteral && 2405: e2->op != TOKstructliteral) 2406: { 2407: error("cannot compare %s at compile time", e2->toChars()); 2408: goto Lcant; 2409: } 2410: e = (*fp)(op, type, e1, e2); 2411: if (e == EXP_CANT_INTERPRET) 2412: error("%s cannot be interpreted at compile time", toChars()); 2413: return e; 2414: 2415: Lcant: 2416: return EXP_CANT_INTERPRET; 2417: } 2418: 2419: #define BIN_INTERPRET2(op) \ 2420: Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \ 2421: { \ 2422: return interpretCommon2(istate, goal, &op); \ 2423: } 2424: 2425: BIN_INTERPRET2(Equal) 2426: BIN_INTERPRET2(Identity) 2427: BIN_INTERPRET2(Cmp) 2428: 2429: /* Helper functions for BinExp::interpretAssignCommon 2430: */ 2431: 2432: /*************************************** 2433: * Duplicate the elements array, then set field 'indexToChange' = newelem. 2434: */ 2435: Expressions *changeOneElement(Expressions *oldelems, size_t indexToChange, Expression *newelem) 2436: { 2437: Expressions *expsx = new Expressions(); 2438: expsx->setDim(oldelems->dim); 2439: for (size_t j = 0; j < expsx->dim; j++) 2440: { 2441: if (j == indexToChange) 2442: expsx->tdata()[j] = newelem; 2443: else 2444: expsx->tdata()[j] = oldelems->tdata()[j]; 2445: } 2446: return expsx; 2447: } 2448: 2449: /******************************** 2450: * Add v to the istate list, unless it already exists there. 2451: */ 2452: void addVarToInterstate(InterState *istate, VarDeclaration *v) 2453: { 2454: if (!v->isParameter()) 2455: { 2456: for (size_t i = 0; 1; i++) 2457: { 2458: if (i == istate->vars.dim) 2459: { istate->vars.push(v); 2460: //printf("\tadding %s to istate\n", v->toChars()); 2461: break; 2462: } 2463: if (v == istate->vars.tdata()[i]) 2464: break; 2465: } 2466: } 2467: } 2468: 2469: // Create a new struct literal, which is the same as se except that se.field[offset] = elem 2470: Expression * modifyStructField(Type *type, StructLiteralExp *se, size_t offset, Expression *newval) 2471: { 2472: int fieldi = se->getFieldIndex(newval->type, offset); 2473: if (fieldi == -1) 2474: return EXP_CANT_INTERPRET; 2475: /* Create new struct literal reflecting updated fieldi 2476: */ 2477: Expressions *expsx = changeOneElement(se->elements, fieldi, newval); 2478: Expression * ee = new StructLiteralExp(se->loc, se->sd, expsx); 2479: ee->type = se->type; 2480: return ee; 2481: } 2482: 2483: /******************************** 2484: * Given an array literal arr (either arrayliteral, stringliteral, or assocArrayLiteral), 2485: * set arr[index] = newval and return the new array. 2486: * 2487: */ 2488: Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae, Expression *index, Expression *newval) 2489: { 2490: /* Create new associative array literal reflecting updated key/value 2491: */ 2492: Expressions *keysx = aae->keys; 2493: Expressions *valuesx = aae->values; 2494: int updated = 0; 2495: for (size_t j = valuesx->dim; j; ) 2496: { j--; 2497: Expression *ekey = aae->keys->tdata()[j]; 2498: Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index); 2499: if (ex == EXP_CANT_INTERPRET) 2500: return EXP_CANT_INTERPRET; 2501: if (ex->isBool(TRUE)) 2502: { valuesx->tdata()[j] = newval; 2503: updated = 1; 2504: } 2505: } 2506: if (!updated) 2507: { // Append index/newval to keysx[]/valuesx[] 2508: valuesx->push(newval); 2509: keysx->push(index); 2510: } 2511: return newval; 2512: } 2513: 2514: // Return true if e is derived from UnaryExp. 2515: // Consider moving this function into Expression. 2516: UnaExp *isUnaExp(Expression *e) 2517: { 2518: switch (e->op) 2519: { 2520: case TOKdotvar: 2521: case TOKindex: 2522: case TOKslice: 2523: case TOKcall: 2524: case TOKdot: 2525: case TOKdotti: 2526: case TOKdottype: 2527: case TOKcast: 2528: return (UnaExp *)e; 2529: default: 2530: break; 2531: } 2532: return NULL; 2533: } 2534: 2535: // Returns the variable which is eventually modified, or NULL if an rvalue. 2536: // thisval is the current value of 'this'. 2537: VarDeclaration * findParentVar(Expression *e, Expression *thisval) 2538: { 2539: for (;;) 2540: { 2541: e = resolveReferences(e, thisval); 2542: if (e->op == TOKvar) 2543: break; 2544: if (e->op == TOKindex) 2545: e = ((IndexExp*)e)->e1; 2546: else if (e->op == TOKdotvar) 2547: e = ((DotVarExp *)e)->e1; 2548: else if (e->op == TOKdotti) 2549: e = ((DotTemplateInstanceExp *)e)->e1; 2550: else if (e->op == TOKslice) 2551: e = ((SliceExp*)e)->e1; 2552: else 2553: return NULL; 2554: } 2555: VarDeclaration *v = ((VarExp *)e)->var->isVarDeclaration(); 2556: assert(v); 2557: return v; 2558: } 2559: 2560: // Given expr, which evaluates to an array/AA/string literal, 2561: // return true if it needs to be copied 2562: bool needToCopyLiteral(Expression *expr) 2563: { 2564: for (;;) 2565: { 2566: switch (expr->op) 2567: { 2568: case TOKarrayliteral: 2569: case TOKassocarrayliteral: 2570: case TOKstructliteral: 2571: return true; 2572: case TOKstring: 2573: case TOKthis: 2574: case TOKvar: 2575: return false; 2576: case TOKassign: 2577: return false; 2578: case TOKindex: 2579: case TOKdotvar: 2580: case TOKslice: 2581: case TOKcast: 2582: expr = ((UnaExp *)expr)->e1; 2583: continue; 2584: case TOKcat: 2585: return needToCopyLiteral(((BinExp *)expr)->e1) || 2586: needToCopyLiteral(((BinExp *)expr)->e2); 2587: case TOKcatass: 2588: expr = ((BinExp *)expr)->e2; 2589: continue; 2590: default: 2591: return false; 2592: } 2593: } 2594: } 2595: 2596: Expressions *copyLiteralArray(Expressions *oldelems) 2597: { 2598: if (!oldelems) 2599: return oldelems; 2600: Expressions *newelems = new Expressions(); 2601: newelems->setDim(oldelems->dim); 2602: for (size_t i = 0; i < oldelems->dim; i++) 2603: newelems->tdata()[i] = copyLiteral(oldelems->tdata()[i]); 2604: return newelems; 2605: } 2606: 2607: 2608: 2609: // Make a copy of the ArrayLiteral, AALiteral, String, or StructLiteral. 2610: // This value will be used for in-place modification. 2611: Expression *copyLiteral(Expression *e) 2612: { 2613: if (e->op == TOKstring) // syntaxCopy doesn't make a copy for StringExp! 2614: { 2615: StringExp *se = (StringExp *)e; 2616: unsigned char *s; 2617: s = (unsigned char *)mem.calloc(se->len + 1, se->sz); 2618: memcpy(s, se->string, se->len * se->sz); 2619: StringExp *se2 = new StringExp(se->loc, s, se->len); 2620: se2->committed = se->committed; 2621: se2->postfix = se->postfix; 2622: se2->type = se->type; 2623: se2->sz = se->sz; 2624: return se2; 2625: } 2626: else if (e->op == TOKarrayliteral) 2627: { 2628: ArrayLiteralExp *ae = (ArrayLiteralExp *)e; 2629: ArrayLiteralExp *r = new ArrayLiteralExp(e->loc, 2630: copyLiteralArray(ae->elements)); 2631: r->type = e->type; 2632: return r; 2633: } 2634: else if (e->op == TOKassocarrayliteral) 2635: { 2636: AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e; 2637: AssocArrayLiteralExp *r = new AssocArrayLiteralExp(e->loc, 2638: copyLiteralArray(aae->keys), copyLiteralArray(aae->values)); 2639: r->type = e->type; 2640: return r; 2641: } 2642: /* syntaxCopy doesn't work for struct literals, because of a nasty special 2643: * case: block assignment is permitted inside struct literals, eg, 2644: * an int[4] array can be initialized with a single int. 2645: */ 2646: else if (e->op == TOKstructliteral) 2647: { 2648: StructLiteralExp *se = (StructLiteralExp *)e; 2649: Expressions *oldelems = se->elements; 2650: Expressions * newelems = new Expressions(); 2651: newelems->setDim(oldelems->dim); 2652: for (size_t i = 0; i < newelems->dim; i++) 2653: { 2654: Expression *m = oldelems->tdata()[i]; 2655: // We need the struct definition to detect block assignment 2656: StructDeclaration *sd = se->sd; 2657: Dsymbol *s = sd->fields.tdata()[i]; 2658: VarDeclaration *v = s->isVarDeclaration(); 2659: assert(v); 2660: // If it is a void assignment, use the default initializer 2661: if (!m) 2662: m = v->type->defaultInitLiteral(e->loc); 2663: if (m->op == TOKslice) 2664: m = resolveSlice(m); 2665: if ((v->type->ty != m->type->ty) && v->type->ty == Tsarray) 2666: { 2667: // Block assignment from inside struct literals 2668: TypeSArray *tsa = (TypeSArray *)v->type; 2669: uinteger_t length = tsa->dim->toInteger(); 2670: m = createBlockDuplicatedArrayLiteral(v->type, m, length);
warning C4244: 'argument' : conversion from 'uinteger_t' to 'size_t', possible loss of data
2671: } 2672: else if (v->type->ty != Tarray) // NOTE: do not copy array references 2673: m = copyLiteral(m); 2674: newelems->tdata()[i] = m; 2675: } 2676: #if DMDV2 2677: StructLiteralExp *r = new StructLiteralExp(e->loc, se->sd, newelems, se->stype); 2678: #else 2679: StructLiteralExp *r = new StructLiteralExp(e->loc, se->sd, newelems); 2680: #endif 2681: r->type = e->type; 2682: return r; 2683: } 2684: else if (e->op == TOKfunction || e->op == TOKdelegate 2685: || e->op == TOKsymoff || e->op == TOKnull 2686: || e->op == TOKvar 2687: || e->op == TOKint64 || e->op == TOKfloat64 2688: || e->op == TOKchar || e->op == TOKcomplex80) 2689: { // Simple value types 2690: Expression *r = e->syntaxCopy(); 2691: r->type = e->type; 2692: return r; 2693: } 2694: else if (e->type->ty == Tpointer && e->type->nextOf()->ty != Tfunction) 2695: { // For pointers, we only do a shallow copy. 2696: Expression *r; 2697: if (e->op == TOKaddress) 2698: r = new AddrExp(e->loc, ((AddrExp *)e)->e1); 2699: else if (e->op == TOKindex) 2700: r = new IndexExp(e->loc, ((IndexExp *)e)->e1, ((IndexExp *)e)->e2); 2701: else if (e->op == TOKdotvar) 2702: r = new DotVarExp(e->loc, ((DotVarExp *)e)->e1, 2703: ((DotVarExp *)e)->var 2704: #if DMDV2 2705: , ((DotVarExp *)e)->hasOverloads 2706: #endif 2707: ); 2708: else 2709: assert(0); 2710: r->type = e->type; 2711: return r; 2712: } 2713: else if (e->op == TOKslice) 2714: { // Array slices only do a shallow copy 2715: Expression *r = new SliceExp(e->loc, ((SliceExp *)e)->e1, 2716: ((SliceExp *)e)->lwr, ((SliceExp *)e)->upr); 2717: r->type = e->type; 2718: return r; 2719: } 2720: else 2721: { 2722: e->error("Internal Compiler Error: CTFE literal %s", e->toChars()); 2723: assert(0); 2724: return e; 2725: } 2726: } 2727: 2728: /* Deal with type painting. 2729: * Type painting is a major nuisance: we can't just set 2730: * e->type = type, because that would change the original literal. 2731: * But, we can't simply copy the literal either, because that would change 2732: * the values of any pointers. 2733: */ 2734: Expression *paintTypeOntoLiteral(Type *type, Expression *lit) 2735: { 2736: if (lit->type == type) 2737: return lit; 2738: Expression *e; 2739: if (lit->op == TOKslice) 2740: { 2741: SliceExp *se = (SliceExp *)lit; 2742: e = new SliceExp(lit->loc, se->e1, se->lwr, se->upr); 2743: } 2744: else if (lit->op == TOKindex) 2745: { 2746: IndexExp *ie = (IndexExp *)lit; 2747: e = new IndexExp(lit->loc, ie->e1, ie->e2); 2748: } 2749: else if (lit->op == TOKarrayliteral) 2750: { 2751: ArrayLiteralExp *ae = (ArrayLiteralExp *)lit; 2752: e = new ArrayLiteralExp(lit->loc, ae->elements); 2753: } 2754: else if (lit->op == TOKstring) 2755: { 2756: // For strings, we need to introduce another level of indirection 2757: e = new SliceExp(lit->loc, lit, 2758: new IntegerExp(0, 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit)); 2759: } 2760: else if (lit->op == TOKassocarrayliteral) 2761: { 2762: AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)lit; 2763: e = new AssocArrayLiteralExp(lit->loc, aae->keys, aae->values); 2764: } 2765: else 2766: e = copyLiteral(lit); 2767: e->type = type; 2768: return e; 2769: } 2770: 2771: /* Set a slice of char array literal 'existingAE' from a string 'newval'. 2772: * existingAE[firstIndex..firstIndex+newval.length] = newval. 2773: */ 2774: void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *newval, int firstIndex) 2775: { 2776: size_t newlen = newval->len; 2777: size_t sz = newval->sz; 2778: unsigned char *s = (unsigned char *)newval->string; 2779: Type *elemType = existingAE->type->nextOf(); 2780: for (size_t j = 0; j < newlen; j++) 2781: { 2782: dinteger_t val; 2783: switch (sz) 2784: { 2785: case 1: val = s[j]; break; 2786: case 2: val = ((unsigned short *)s)[j]; break; 2787: case 4: val = ((unsigned *)s)[j]; break; 2788: default: 2789: assert(0); 2790: break; 2791: } 2792: existingAE->elements->tdata()[j+firstIndex] 2793: = new IntegerExp(newval->loc, val, elemType); 2794: } 2795: } 2796: 2797: /* Set a slice of string 'existingSE' from a char array literal 'newae'. 2798: * existingSE[firstIndex..firstIndex+newae.length] = newae. 2799: */ 2800: void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, int firstIndex) 2801: { 2802: unsigned char *s = (unsigned char *)existingSE->string; 2803: for (size_t j = 0; j < newae->elements->dim; j++) 2804: { 2805: unsigned value = newae->elements->tdata()[j]->toInteger();
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'unsigned int', possible loss of data
2806: switch (existingSE->sz) 2807: { 2808: case 1: s[j+firstIndex] = value; break; 2809: case 2: ((unsigned short *)s)[j+firstIndex] = value; break; 2810: case 4: ((unsigned *)s)[j+firstIndex] = value; break; 2811: default: 2812: assert(0); 2813: break; 2814: } 2815: } 2816: } 2817: 2818: /* Set a slice of string 'existingSE' from a string 'newstr'. 2819: * existingSE[firstIndex..firstIndex+newstr.length] = newstr. 2820: */ 2821: void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, int firstIndex) 2822: { 2823: unsigned char *s = (unsigned char *)existingSE->string; 2824: size_t sz = existingSE->sz; 2825: assert(sz == newstr->sz); 2826: memcpy(s + firstIndex * sz, newstr->string, sz * newstr->len); 2827: } 2828: 2829: 2830: /* Set dest = src, where both dest and src are container value literals 2831: * (ie, struct literals, or static arrays (can be an array literal or a string) 2832: * Assignment is recursively in-place. 2833: * Purpose: any reference to a member of 'dest' will remain valid after the 2834: * assignment. 2835: */ 2836: void assignInPlace(Expression *dest, Expression *src) 2837: { 2838: assert(dest->op == TOKstructliteral || dest->op == TOKarrayliteral || 2839: dest->op == TOKstring); 2840: Expressions *oldelems; 2841: Expressions *newelems; 2842: if (dest->op == TOKstructliteral) 2843: { 2844: assert(dest->op == src->op); 2845: oldelems = ((StructLiteralExp *)dest)->elements; 2846: newelems = ((StructLiteralExp *)src)->elements; 2847: } 2848: else if (dest->op == TOKarrayliteral && src->op==TOKarrayliteral) 2849: { 2850: oldelems = ((ArrayLiteralExp *)dest)->elements; 2851: newelems = ((ArrayLiteralExp *)src)->elements; 2852: } 2853: else if (dest->op == TOKstring && src->op == TOKstring) 2854: { 2855: sliceAssignStringFromString((StringExp *)dest, (StringExp *)src, 0); 2856: return; 2857: } 2858: else if (dest->op == TOKarrayliteral && src->op == TOKstring) 2859: { 2860: sliceAssignArrayLiteralFromString((ArrayLiteralExp *)dest, (StringExp *)src, 0); 2861: return; 2862: } 2863: else if (src->op == TOKarrayliteral && dest->op == TOKstring) 2864: { 2865: sliceAssignStringFromArrayLiteral((StringExp *)dest, (ArrayLiteralExp *)src, 0); 2866: return; 2867: } 2868: else assert(0); 2869: 2870: assert(oldelems->dim == newelems->dim); 2871: 2872: for (size_t i= 0; i < oldelems->dim; ++i) 2873: { 2874: Expression *e = newelems->tdata()[i]; 2875: Expression *o = oldelems->tdata()[i]; 2876: if (e->op == TOKstructliteral) 2877: { 2878: assert(o->op == e->op); 2879: assignInPlace(o, e); 2880: } 2881: else if (e->type->ty == Tsarray && o->type->ty == Tsarray) 2882: { 2883: assignInPlace(o, e); 2884: } 2885: else 2886: { 2887: oldelems->tdata()[i] = newelems->tdata()[i]; 2888: } 2889: } 2890: } 2891: 2892: void recursiveBlockAssign(ArrayLiteralExp *ae, Expression *val, bool wantRef) 2893: { 2894: assert( ae->type->ty == Tsarray || ae->type->ty == Tarray); 2895: #if DMDV2 2896: Type *desttype = ((TypeArray *)ae->type)->next->castMod(0); 2897: bool directblk = (val->type->toBasetype()->castMod(0)) == desttype; 2898: #else 2899: Type *desttype = ((TypeArray *)ae->type)->next; 2900: bool directblk = (val->type->toBasetype()) == desttype; 2901: #endif 2902: 2903: bool cow = !(val->op == TOKstructliteral || val->op == TOKarrayliteral 2904: || val->op == TOKstring); 2905: 2906: for (size_t k = 0; k < ae->elements->dim; k++) 2907: { 2908: if (!directblk && ae->elements->tdata()[k]->op == TOKarrayliteral) 2909: { 2910: recursiveBlockAssign((ArrayLiteralExp *)ae->elements->tdata()[k], val, wantRef); 2911: } 2912: else 2913: { 2914: if (wantRef || cow) 2915: ae->elements->tdata()[k] = val; 2916: else 2917: assignInPlace(ae->elements->tdata()[k], val); 2918: } 2919: } 2920: } 2921: 2922: 2923: Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_t fp, int post) 2924: { 2925: #if LOG 2926: printf("BinExp::interpretAssignCommon() %s\n", toChars()); 2927: #endif 2928: Expression *returnValue = EXP_CANT_INTERPRET; 2929: Expression *e1 = this->e1; 2930: if (!istate) 2931: { 2932: error("value of %s is not known at compile time", e1->toChars()); 2933: return returnValue; 2934: } 2935: /* Before we begin, we need to know if this is a reference assignment 2936: * (dynamic array, AA, or class) or a value assignment. 2937: * Determining this for slice assignments are tricky: we need to know 2938: * if it is a block assignment (a[] = e) rather than a direct slice 2939: * assignment (a[] = b[]). Note that initializers of multi-dimensional 2940: * static arrays can have 2D block assignments (eg, int[7][7] x = 6;). 2941: * So we need to recurse to determine if it is a block assignment. 2942: */ 2943: bool isBlockAssignment = false; 2944: if (e1->op == TOKslice) 2945: { 2946: // a[] = e can have const e. So we compare the naked types. 2947: Type *desttype = e1->type->toBasetype(); 2948: #if DMDV2 2949: Type *srctype = e2->type->toBasetype()->castMod(0); 2950: #else 2951: Type *srctype = e2->type->toBasetype(); 2952: #endif 2953: while ( desttype->ty == Tsarray || desttype->ty == Tarray) 2954: { 2955: desttype = ((TypeArray *)desttype)->next; 2956: #if DMDV2 2957: if (srctype == desttype->castMod(0)) 2958: #else 2959: if (srctype == desttype) 2960: #endif 2961: { 2962: isBlockAssignment = true; 2963: break; 2964: } 2965: } 2966: } 2967: bool wantRef = false; 2968: if (!fp && this->e1->type->toBasetype() == this->e2->type->toBasetype() && 2969: (e1->type->toBasetype()->ty == Tarray || e1->type->toBasetype()->ty == Taarray || 2970: e1->type->toBasetype()->ty == Tclass) 2971: // e = *x is never a reference, because *x is always a value 2972: && this->e2->op != TOKstar 2973: ) 2974: { 2975: #if DMDV2 2976: wantRef = true; 2977: #else 2978: /* D1 doesn't have const in the type system. But there is still a 2979: * vestigal const in the form of static const variables. 2980: * Problematic code like: 2981: * const int [] x = [1,2,3]; 2982: * int [] y = x; 2983: * can be dealt with by making this a non-ref assign (y = x.dup). 2984: * Otherwise it's a big mess. 2985: */ 2986: VarDeclaration * targetVar = findParentVar(e2, istate->localThis); 2987: if (!(targetVar && targetVar->isConst())) 2988: wantRef = true; 2989: // slice assignment of static arrays is not reference assignment 2990: if ((e1->op==TOKslice) && ((SliceExp *)e1)->e1->type->ty == Tsarray) 2991: wantRef = false; 2992: #endif 2993: } 2994: if (isBlockAssignment && (e2->type->toBasetype()->ty == Tarray || e2->type->toBasetype()->ty == Tsarray)) 2995: { 2996: wantRef = true; 2997: } 2998: /* This happens inside compiler-generated foreach statements. 2999: * It's another case where we need a reference 3000: * Note that a similar case, where e2 = 'this', occurs in 3001: * construction of a struct with an invariant(). 3002: */ 3003: if (op==TOKconstruct && this->e1->op==TOKvar && this->e2->op != TOKthis 3004: && this->e2->op != TOKcomma 3005: && ((VarExp*)this->e1)->var->storage_class & STCref) 3006: wantRef = true; 3007: 3008: if (fp) 3009: { 3010: if (e1->op == TOKcast) 3011: { CastExp *ce = (CastExp *)e1; 3012: e1 = ce->e1; 3013: } 3014: } 3015: if (e1 == EXP_CANT_INTERPRET) 3016: return e1; 3017: 3018: // First, deal with this = e; and call() = e; 3019: if (e1->op == TOKthis) 3020: { 3021: e1 = istate->localThis; 3022: } 3023: if (e1->op == TOKcall) 3024: { 3025: bool oldWaiting = istate->awaitingLvalueReturn; 3026: istate->awaitingLvalueReturn = true; 3027: e1 = e1->interpret(istate); 3028: istate->awaitingLvalueReturn = oldWaiting; 3029: if (e1 == EXP_CANT_INTERPRET) 3030: return e1; 3031: if (e1->op == TOKarrayliteral || e1->op == TOKstring) 3032: { 3033: // f() = e2, when f returns an array, is always a slice assignment. 3034: // Convert into arr[0..arr.length] = e2 3035: e1 = new SliceExp(loc, e1, 3036: new IntegerExp(0, 0, Type::tsize_t), 3037: ArrayLength(Type::tsize_t, e1)); 3038: e1->type = type; 3039: } 3040: } 3041: if (e1->op == TOKstar) 3042: { 3043: e1 = e1->interpret(istate, ctfeNeedLvalue); 3044: if (e1 == EXP_CANT_INTERPRET) 3045: return EXP_CANT_INTERPRET; 3046: } 3047: 3048: if (!(e1->op == TOKarraylength || e1->op == TOKvar || e1->op == TOKdotvar 3049: || e1->op == TOKindex || e1->op == TOKslice)) 3050: printf("CTFE internal error: unsupported assignment %s\n", toChars()); 3051: assert(e1->op == TOKarraylength || e1->op == TOKvar || e1->op == TOKdotvar 3052: || e1->op == TOKindex || e1->op == TOKslice); 3053: 3054: Expression * newval = NULL; 3055: 3056: if (!wantRef) 3057: { // We need to treat pointers specially, because TOKsymoff can be used to 3058: // return a value OR a pointer 3059: assert(e1); 3060: assert(e1->type); 3061: if ((e1->type->ty == Tpointer && e1->type->nextOf()->ty != Tfunction) && (e2->op == TOKsymoff || e2->op==TOKaddress || e2->op==TOKvar)) // && (e1->op==TOKaddress)) //TOKsymoff || e1->op==TOKdotvar)) 3062: newval = this->e2->interpret(istate, ctfeNeedLvalue); 3063: else 3064: newval = this->e2->interpret(istate); 3065: } 3066: if (newval == EXP_CANT_INTERPRET) 3067: return newval; 3068: // ---------------------------------------------------- 3069: // Deal with read-modify-write assignments. 3070: // Set 'newval' to the final assignment value 3071: // Also determine the return value (except for slice 3072: // assignments, which are more complicated) 3073: // ---------------------------------------------------- 3074: 3075: if (fp || e1->op == TOKarraylength) 3076: { 3077: // If it isn't a simple assignment, we need the existing value 3078: Expression * oldval = e1->interpret(istate); 3079: if (oldval == EXP_CANT_INTERPRET) 3080: return EXP_CANT_INTERPRET; 3081: while (oldval->op == TOKvar) 3082: { 3083: oldval = resolveReferences(oldval, istate->localThis); 3084: oldval = oldval->interpret(istate); 3085: if (oldval == EXP_CANT_INTERPRET) 3086: return oldval; 3087: } 3088: 3089: if (fp) 3090: { 3091: // ~= can create new values (see bug 6052) 3092: if (op == TOKcatass) 3093: { 3094: if (needToCopyLiteral(this->e2)) 3095: newval = copyLiteral(newval); 3096: if (newval->op == TOKslice) 3097: newval = resolveSlice(newval); 3098: // It becomes a reference assignment 3099: wantRef = true; 3100: } 3101: if (oldval->op == TOKslice) 3102: oldval = resolveSlice(oldval); 3103: if (this->e1->type->ty == Tpointer && this->e2->type->isintegral() 3104: && (op==TOKaddass || op == TOKminass)) 3105: { 3106: oldval = this->e1->interpret(istate, ctfeNeedLvalue); 3107: newval = this->e2->interpret(istate); 3108: if (oldval == EXP_CANT_INTERPRET || newval == EXP_CANT_INTERPRET) 3109: return EXP_CANT_INTERPRET; 3110: newval = pointerArithmetic(loc, op, type, oldval, newval); 3111: } 3112: else if (this->e1->type->ty == Tpointer) 3113: { 3114: error("pointer expression %s cannot be interpreted at compile time", toChars()); 3115: return EXP_CANT_INTERPRET; 3116: } 3117: else 3118: { 3119: newval = (*fp)(type, oldval, newval); 3120: } 3121: if (newval == EXP_CANT_INTERPRET) 3122: { 3123: error("Cannot interpret %s at compile time", toChars()); 3124: return EXP_CANT_INTERPRET; 3125: } 3126: // Determine the return value 3127: returnValue = Cast(type, type, post ? oldval : newval); 3128: if (returnValue == EXP_CANT_INTERPRET) 3129: return returnValue; 3130: } 3131: else 3132: returnValue = newval; 3133: if (e1->op == TOKarraylength) 3134: { 3135: size_t oldlen = oldval->toInteger();
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'size_t', possible loss of data
3136: size_t newlen = newval->toInteger();
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'size_t', possible loss of data
3137: if (oldlen == newlen) // no change required -- we're done! 3138: return returnValue; 3139: // Now change the assignment from arr.length = n into arr = newval 3140: e1 = ((ArrayLengthExp *)e1)->e1; 3141: if (oldlen != 0) 3142: { // Get the old array literal. 3143: oldval = e1->interpret(istate); 3144: while (oldval->op == TOKvar) 3145: { oldval = resolveReferences(oldval, istate->localThis); 3146: oldval = oldval->interpret(istate); 3147: } 3148: } 3149: if (oldval->op == TOKslice) 3150: oldval = resolveSlice(oldval); 3151: Type *t = e1->type->toBasetype(); 3152: if (t->ty == Tarray) 3153: { 3154: Type *elemType= NULL; 3155: elemType = ((TypeArray *)t)->next; 3156: assert(elemType); 3157: Expression *defaultElem = elemType->defaultInitLiteral(); 3158: 3159: Expressions *elements = new Expressions(); 3160: elements->setDim(newlen); 3161: size_t copylen = oldlen < newlen ? oldlen : newlen; 3162: if (oldlen !=0) 3163: assert(oldval->op == TOKarrayliteral); 3164: ArrayLiteralExp *ae = (ArrayLiteralExp *)oldval; 3165: for (size_t i = 0; i < copylen; i++) 3166: elements->tdata()[i] = ae->elements->tdata()[i]; 3167: if (elemType->ty == Tstruct || elemType->ty == Tsarray) 3168: { /* If it is an aggregate literal representing a value type, 3169: * we need to create a unique copy for each element 3170: */ 3171: for (size_t i = copylen; i < newlen; i++) 3172: elements->tdata()[i] = copyLiteral(defaultElem); 3173: } 3174: else 3175: { 3176: for (size_t i = copylen; i < newlen; i++) 3177: elements->tdata()[i] = defaultElem; 3178: } 3179: ArrayLiteralExp *aae = new ArrayLiteralExp(0, elements); 3180: aae->type = t; 3181: newval = aae; 3182: // We have changed it into a reference assignment 3183: // Note that returnValue is still the new length. 3184: wantRef = true; 3185: if (e1->op == TOKstar) 3186: { // arr.length+=n becomes (t=&arr, *(t).length=*(t).length+n); 3187: e1 = e1->interpret(istate, ctfeNeedLvalue); 3188: if (e1 == EXP_CANT_INTERPRET) 3189: return EXP_CANT_INTERPRET; 3190: } 3191: } 3192: else 3193: { 3194: error("%s is not yet supported at compile time", toChars()); 3195: return EXP_CANT_INTERPRET; 3196: } 3197: 3198: } 3199: } 3200: else if (!wantRef && e1->op != TOKslice) 3201: { /* Look for special case of struct being initialized with 0. 3202: */ 3203: if (type->toBasetype()->ty == Tstruct && newval->op == TOKint64) 3204: { 3205: newval = type->defaultInitLiteral(loc); 3206: } 3207: newval = Cast(type, type, newval); 3208: if (newval == EXP_CANT_INTERPRET) 3209: { 3210: error("CTFE error: cannot cast %s to type %s", this->e2->toChars(), type->toChars()); 3211: return EXP_CANT_INTERPRET; 3212: } 3213: returnValue = newval; 3214: } 3215: if (newval == EXP_CANT_INTERPRET) 3216: return newval; 3217: 3218: // ------------------------------------------------- 3219: // Make sure destination can be modified 3220: // ------------------------------------------------- 3221: // Make sure we're not trying to modify a global or static variable 3222: // We do this by locating the ultimate parent variable which gets modified. 3223: VarDeclaration * ultimateVar = findParentVar(e1, istate->localThis); 3224: if (ultimateVar && ultimateVar->isDataseg() && !ultimateVar->isCTFE()) 3225: { // Can't modify global or static data 3226: error("%s cannot be modified at compile time", ultimateVar->toChars()); 3227: return EXP_CANT_INTERPRET; 3228: } 3229: 3230: // This happens inside compiler-generated foreach statements. 3231: if (op==TOKconstruct && this->e1->op==TOKvar && this->e2->op != TOKthis 3232: && this->e2->op != TOKcomma 3233: && ((VarExp*)this->e1)->var->storage_class & STCref) 3234: { 3235: VarDeclaration *v = ((VarExp *)e1)->var->isVarDeclaration(); 3236: v->setValueNull(); 3237: v->createStackValue(e2); 3238: #if (LOGASSIGN) 3239: printf("FOREACH ASSIGN %s=%s\n", v->toChars(), e2->toChars()); 3240: #endif 3241: return e2; 3242: } 3243: 3244: bool destinationIsReference = false; 3245: e1 = resolveReferences(e1, istate->localThis, &destinationIsReference); 3246: 3247: // Unless we have a simple var assignment, we're 3248: // only modifying part of the variable. So we need to make sure 3249: // that the parent variable exists. 3250: if (e1->op != TOKvar && ultimateVar && !ultimateVar->getValue()) 3251: ultimateVar->createRefValue(copyLiteral(ultimateVar->type->defaultInitLiteral())); 3252: 3253: // --------------------------------------- 3254: // Deal with reference assignment 3255: // (We already have 'newval' for arraylength operations) 3256: // --------------------------------------- 3257: if (wantRef && !fp && this->e1->op != TOKarraylength) 3258: { 3259: newval = this->e2->interpret(istate, ctfeNeedLvalue); 3260: if (newval == EXP_CANT_INTERPRET) 3261: return newval; 3262: // If it is an assignment from a array function parameter passed by 3263: // reference, resolve the reference. (This should NOT happen for 3264: // non-reference types). 3265: if (newval->op == TOKvar && (newval->type->ty == Tarray || 3266: newval->type->ty == Tclass)) 3267: { 3268: newval = newval->interpret(istate); 3269: } 3270: 3271: if (newval->op == TOKassocarrayliteral || newval->op == TOKstring || 3272: newval->op==TOKarrayliteral) 3273: { 3274: if (needToCopyLiteral(this->e2)) 3275: newval = copyLiteral(newval); 3276: } 3277: returnValue = newval; 3278: } 3279: 3280: // --------------------------------------- 3281: // Deal with dotvar expressions 3282: // --------------------------------------- 3283: // Because structs are not reference types, dotvar expressions can be 3284: // collapsed into a single assignment. 3285: if (!wantRef && e1->op == TOKdotvar) 3286: { 3287: // Strip of all of the leading dotvars, unless we started with a call 3288: // (in which case, we already have the lvalue). 3289: if (this->e1->op != TOKcall) 3290: e1 = e1->interpret(istate, ctfeNeedLvalue); 3291: if (e1 == EXP_CANT_INTERPRET) 3292: return e1; 3293: if (e1->op == TOKstructliteral && newval->op == TOKstructliteral) 3294: { 3295: assignInPlace(e1, newval); 3296: return returnValue; 3297: } 3298: } 3299: #if LOGASSIGN 3300: if (wantRef) 3301: printf("REF ASSIGN: %s=%s\n", e1->toChars(), newval->toChars()); 3302: else 3303: printf("ASSIGN: %s=%s\n", e1->toChars(), newval->toChars()); 3304: showCtfeExpr(newval); 3305: #endif 3306: 3307: /* Assignment to variable of the form: 3308: * v = newval 3309: */ 3310: if (e1->op == TOKvar) 3311: { 3312: VarExp *ve = (VarExp *)e1; 3313: VarDeclaration *v = ve->var->isVarDeclaration(); 3314: if (!destinationIsReference) 3315: addVarToInterstate(istate, v); 3316: if (wantRef) 3317: { 3318: v->setValueNull(); 3319: v->createRefValue(newval); 3320: } 3321: else if (e1->type->toBasetype()->ty == Tstruct) 3322: { 3323: // In-place modification 3324: if (newval->op != TOKstructliteral) 3325: { 3326: error("CTFE internal error assigning struct"); 3327: return EXP_CANT_INTERPRET; 3328: } 3329: newval = copyLiteral(newval); 3330: if (v->getValue()) 3331: assignInPlace(v->getValue(), newval); 3332: else 3333: v->createRefValue(newval); 3334: } 3335: else 3336: { 3337: if (e1->type->toBasetype()->ty == Tarray || e1->type->toBasetype()->ty == Taarray) 3338: { // arr op= arr 3339: if (!v->getValue()) 3340: v->createRefValue(newval); 3341: else v->setRefValue(newval); 3342: } 3343: else 3344: { 3345: if (!v->getValue()) // creating a new value 3346: v->createStackValue(newval); 3347: else 3348: v->setStackValue(newval); 3349: } 3350: } 3351: } 3352: else if (e1->op == TOKdotvar) 3353: { 3354: /* Assignment to member variable of the form: 3355: * e.v = newval 3356: */ 3357: Expression *exx = ((DotVarExp *)e1)->e1; 3358: if (wantRef && exx->op != TOKstructliteral) 3359: { 3360: exx = exx->interpret(istate); 3361: if (exx == EXP_CANT_INTERPRET) 3362: return exx; 3363: } 3364: if (exx->op != TOKstructliteral) 3365: { 3366: error("CTFE internal error: Dotvar assignment"); 3367: return EXP_CANT_INTERPRET; 3368: } 3369: StructLiteralExp *se = (StructLiteralExp *)exx; 3370: VarDeclaration *member = ((DotVarExp *)e1)->var->isVarDeclaration(); 3371: if (!member) 3372: { 3373: error("CTFE internal error: Dotvar assignment"); 3374: return EXP_CANT_INTERPRET; 3375: } 3376: int fieldi = se->getFieldIndex(member->type, member->offset); 3377: if (fieldi == -1) 3378: return EXP_CANT_INTERPRET; 3379: assert(fieldi>=0 && fieldi < se->elements->dim);
warning C4018: '<' : signed/unsigned mismatch
3380: if (newval->op == TOKstructliteral) 3381: assignInPlace(se->elements->tdata()[fieldi], newval); 3382: else 3383: se->elements->tdata()[fieldi] = newval; 3384: if (ultimateVar && !destinationIsReference) 3385: addVarToInterstate(istate, ultimateVar); 3386: return returnValue; 3387: } 3388: else if (e1->op == TOKindex) 3389: { 3390: /* Assignment to array element of the form: 3391: * aggregate[i] = newval 3392: */ 3393: IndexExp *ie = (IndexExp *)e1; 3394: uinteger_t destarraylen = 0; // not for AAs 3395: 3396: // Set the $ variable, and find the array literal to modify 3397: if (ie->e1->type->toBasetype()->ty != Taarray && ie->e1->type->toBasetype()->ty != Tpointer) 3398: { 3399: Expression *oldval = ie->e1->interpret(istate); 3400: if (oldval->op == TOKnull) 3401: { 3402: error("cannot index null array %s", ie->e1->toChars()); 3403: return EXP_CANT_INTERPRET; 3404: } 3405: if (oldval->op != TOKarrayliteral && oldval->op != TOKstring 3406: && oldval->op != TOKslice) 3407: { 3408: error("cannot determine length of %s at compile time", 3409: ie->e1->toChars()); 3410: return EXP_CANT_INTERPRET; 3411: } 3412: destarraylen = resolveArrayLength(oldval); 3413: if (ie->lengthVar) 3414: { 3415: IntegerExp *dollarExp = new IntegerExp(loc, destarraylen, Type::tsize_t); 3416: ie->lengthVar->createStackValue(dollarExp); 3417: } 3418: } 3419: Expression *index = ie->e2->interpret(istate); 3420: if (ie->lengthVar) 3421: ie->lengthVar->setValueNull(); // $ is defined only inside [] 3422: if (index == EXP_CANT_INTERPRET) 3423: return EXP_CANT_INTERPRET; 3424: 3425: if (index->op == TOKslice) // only happens with AA assignment 3426: index = resolveSlice(index); 3427: 3428: ArrayLiteralExp *existingAE = NULL; 3429: StringExp *existingSE = NULL; 3430: AssocArrayLiteralExp *existingAA = NULL; 3431: 3432: Expression *aggregate = resolveReferences(ie->e1, istate->localThis); 3433: 3434: // Set the index to modify (for non-AAs), and check that it is in range 3435: int indexToModify = 0; 3436: if (ie->e1->type->toBasetype()->ty != Taarray) 3437: { 3438: indexToModify = index->toInteger();
warning C4244: '=' : conversion from 'dinteger_t' to 'int', possible loss of data
3439: if (ie->e1->type->toBasetype()->ty == Tpointer) 3440: { 3441: dinteger_t ofs; 3442: aggregate = aggregate->interpret(istate, ctfeNeedLvalue); 3443: if (aggregate == EXP_CANT_INTERPRET) 3444: return EXP_CANT_INTERPRET; 3445: if (aggregate->op == TOKnull) 3446: { 3447: error("cannot index through null pointer %s", ie->e1->toChars()); 3448: return EXP_CANT_INTERPRET; 3449: } 3450: aggregate = getAggregateFromPointer(aggregate, &ofs); 3451: indexToModify += ofs;
warning C4244: '+=' : conversion from 'dinteger_t' to 'int', possible loss of data
3452: destarraylen = resolveArrayLength(aggregate); 3453: } 3454: if (indexToModify >= destarraylen) 3455: { 3456: error("array index %d is out of bounds [0..%d]", indexToModify, 3457: destarraylen); 3458: return EXP_CANT_INTERPRET; 3459: } 3460: } 3461: 3462: /* The only possible indexable LValue aggregates are array literals, 3463: * slices of array literals, and AA literals. 3464: */ 3465: if (aggregate->op == TOKindex || aggregate->op == TOKdotvar || 3466: aggregate->op == TOKslice || aggregate->op == TOKcall || 3467: aggregate->op == TOKstar) 3468: { 3469: aggregate = aggregate->interpret(istate, ctfeNeedLvalue); 3470: if (aggregate == EXP_CANT_INTERPRET) 3471: return EXP_CANT_INTERPRET; 3472: // The array could be an index of an AA. Resolve it if so. 3473: if (aggregate->op == TOKindex) 3474: { 3475: IndexExp *ie = (IndexExp *)aggregate;
warning C6246: Local declaration of 'ie' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3393' of 'c:\projects\extern\d\dmd\src\interpret.c': Lines: 3393
3476: aggregate = Index(ie->type, ie->e1, ie->e2); 3477: } 3478: } 3479: if (aggregate->op == TOKvar) 3480: { 3481: VarExp *ve = (VarExp *)aggregate; 3482: VarDeclaration *v = ve->var->isVarDeclaration(); 3483: aggregate = v->getValue(); 3484: if (aggregate->op == TOKnull) 3485: { 3486: if (v->type->ty == Taarray) 3487: { // Assign to empty associative array 3488: Expressions *valuesx = new Expressions(); 3489: Expressions *keysx = new Expressions(); 3490: Expression *index = ie->e2->interpret(istate);
warning C6246: Local declaration of 'index' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3419' of 'c:\projects\extern\d\dmd\src\interpret.c': Lines: 3419
3491: if (index == EXP_CANT_INTERPRET) 3492: return EXP_CANT_INTERPRET; 3493: valuesx->push(newval); 3494: keysx->push(index); 3495: Expression *aae2 = new AssocArrayLiteralExp(loc, keysx, valuesx); 3496: aae2->type = v->type; 3497: newval = aae2; 3498: v->setRefValue(newval); 3499: return returnValue; 3500: } 3501: // This would be a runtime segfault 3502: error("cannot index null array %s", v->toChars()); 3503: return EXP_CANT_INTERPRET; 3504: } 3505: } 3506: if (aggregate->op == TOKslice) 3507: { 3508: SliceExp *sexp = (SliceExp *)aggregate; 3509: aggregate = sexp->e1; 3510: Expression *lwr = sexp->lwr->interpret(istate); 3511: indexToModify += lwr->toInteger();
warning C4244: '+=' : conversion from 'dinteger_t' to 'int', possible loss of data
3512: } 3513: if (aggregate->op == TOKarrayliteral) 3514: existingAE = (ArrayLiteralExp *)aggregate; 3515: else if (aggregate->op == TOKstring) 3516: existingSE = (StringExp *)aggregate; 3517: else if (aggregate->op == TOKassocarrayliteral) 3518: existingAA = (AssocArrayLiteralExp *)aggregate; 3519: else 3520: { 3521: error("CTFE internal compiler error %s", aggregate->toChars()); 3522: return EXP_CANT_INTERPRET; 3523: } 3524: if (!wantRef && newval->op == TOKslice) 3525: { 3526: newval = resolveSlice(newval); 3527: if (newval == EXP_CANT_INTERPRET) 3528: { 3529: error("Compiler error: CTFE index assign %s", toChars()); 3530: assert(0); 3531: } 3532: } 3533: 3534: if (existingAE) 3535: { 3536: if (newval->op == TOKstructliteral) 3537: assignInPlace((Expression *)(existingAE->elements->tdata()[indexToModify]), newval); 3538: else 3539: existingAE->elements->tdata()[indexToModify] = newval; 3540: return returnValue; 3541: } 3542: if (existingSE) 3543: { 3544: unsigned char *s = (unsigned char *)existingSE->string; 3545: unsigned value = newval->toInteger();
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'unsigned int', possible loss of data
3546: switch (existingSE->sz) 3547: { 3548: case 1: s[indexToModify] = value; break; 3549: case 2: ((unsigned short *)s)[indexToModify] = value; break; 3550: case 4: ((unsigned *)s)[indexToModify] = value; break; 3551: default: 3552: assert(0); 3553: break; 3554: } 3555: return returnValue; 3556: } 3557: else if (existingAA) 3558: { 3559: if (assignAssocArrayElement(loc, existingAA, index, newval) == EXP_CANT_INTERPRET) 3560: return EXP_CANT_INTERPRET; 3561: return returnValue; 3562: } 3563: else 3564: { 3565: error("Index assignment %s is not yet supported in CTFE ", toChars()); 3566: return EXP_CANT_INTERPRET; 3567: } 3568: return returnValue; 3569: } 3570: else if (e1->op == TOKslice) 3571: { 3572: // ------------------------------ 3573: // aggregate[] = newval 3574: // aggregate[low..upp] = newval 3575: // ------------------------------ 3576: SliceExp * sexp = (SliceExp *)e1; 3577: // Set the $ variable 3578: Expression *oldval = sexp->e1; 3579: bool assignmentToSlicedPointer = false; 3580: if (oldval->type->toBasetype()->ty == Tpointer && oldval->type->toBasetype()->nextOf()->ty != Tfunction) 3581: { // Slicing a pointer 3582: oldval = oldval->interpret(istate, ctfeNeedLvalue); 3583: dinteger_t ofs; 3584: oldval = getAggregateFromPointer(oldval, &ofs); 3585: assignmentToSlicedPointer = true; 3586: } else 3587: oldval = oldval->interpret(istate); 3588: 3589: if (oldval->op != TOKarrayliteral && oldval->op != TOKstring 3590: && oldval->op != TOKslice && oldval->op != TOKnull) 3591: { 3592: error("CTFE ICE: cannot resolve array length"); 3593: return EXP_CANT_INTERPRET; 3594: } 3595: uinteger_t dollar = resolveArrayLength(oldval); 3596: if (sexp->lengthVar) 3597: { 3598: Expression *arraylen = new IntegerExp(loc, dollar, Type::tsize_t); 3599: sexp->lengthVar->createStackValue(arraylen); 3600: } 3601: 3602: Expression *upper = NULL; 3603: Expression *lower = NULL; 3604: if (sexp->upr) 3605: upper = sexp->upr->interpret(istate); 3606: if (sexp->lwr) 3607: lower = sexp->lwr->interpret(istate); 3608: if (sexp->lengthVar) 3609: sexp->lengthVar->setValueNull(); // $ is defined only in [L..U] 3610: if (upper == EXP_CANT_INTERPRET || lower == EXP_CANT_INTERPRET) 3611: return EXP_CANT_INTERPRET; 3612: 3613: int dim = dollar;
warning C4244: 'initializing' : conversion from 'uinteger_t' to 'int', possible loss of data
3614: int upperbound = upper ? upper->toInteger() : dim;
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'int', possible loss of data
3615: int lowerbound = lower ? lower->toInteger() : 0;
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'int', possible loss of data
3616: 3617: if (!assignmentToSlicedPointer && (((int)lowerbound < 0) || (upperbound > dim))) 3618: { 3619: error("Array bounds [0..%d] exceeded in slice [%d..%d]", 3620: dim, lowerbound, upperbound); 3621: return EXP_CANT_INTERPRET; 3622: } 3623: if (upperbound == lowerbound) 3624: return newval; 3625: 3626: Expression *aggregate = resolveReferences(((SliceExp *)e1)->e1, istate->localThis); 3627: int firstIndex = lowerbound; 3628: 3629: ArrayLiteralExp *existingAE = NULL; 3630: StringExp *existingSE = NULL; 3631: 3632: /* The only possible slicable LValue aggregates are array literals, 3633: * and slices of array literals. 3634: */ 3635: 3636: if (aggregate->op == TOKindex || aggregate->op == TOKdotvar || 3637: aggregate->op == TOKslice || 3638: aggregate->op == TOKstar || aggregate->op == TOKcall) 3639: { 3640: aggregate = aggregate->interpret(istate, ctfeNeedLvalue); 3641: if (aggregate == EXP_CANT_INTERPRET) 3642: return EXP_CANT_INTERPRET; 3643: // The array could be an index of an AA. Resolve it if so. 3644: if (aggregate->op == TOKindex) 3645: { 3646: IndexExp *ie = (IndexExp *)aggregate; 3647: aggregate = Index(ie->type, ie->e1, ie->e2); 3648: } 3649: } 3650: if (aggregate->op == TOKvar) 3651: { 3652: VarExp *ve = (VarExp *)(aggregate); 3653: VarDeclaration *v = ve->var->isVarDeclaration(); 3654: aggregate = v->getValue(); 3655: } 3656: if (aggregate->op == TOKslice) 3657: { // Slice of a slice --> change the bounds 3658: SliceExp *sexpold = (SliceExp *)aggregate; 3659: dinteger_t hi = upperbound + sexpold->lwr->toInteger(); 3660: firstIndex = lowerbound + sexpold->lwr->toInteger();
warning C4244: '=' : conversion from 'dinteger_t' to 'int', possible loss of data
3661: if (hi > sexpold->upr->toInteger()) 3662: { 3663: error("slice [%d..%d] exceeds array bounds [0..%jd]", 3664: lowerbound, upperbound, 3665: sexpold->upr->toInteger() - sexpold->lwr->toInteger()); 3666: return EXP_CANT_INTERPRET; 3667: } 3668: aggregate = sexpold->e1; 3669: } 3670: if (aggregate->type->toBasetype()->ty == Tpointer && aggregate->type->toBasetype()->nextOf()->ty != Tfunction) 3671: { // Slicing a pointer --> change the bounds 3672: aggregate = sexp->e1->interpret(istate, ctfeNeedLvalue); 3673: dinteger_t ofs; 3674: aggregate = getAggregateFromPointer(aggregate, &ofs); 3675: dinteger_t hi = upperbound + ofs; 3676: firstIndex = lowerbound + ofs;
warning C4244: '=' : conversion from 'dinteger_t' to 'int', possible loss of data
3677: if (firstIndex < 0 || hi > dim) 3678: { 3679: error("slice [%d..%jd] exceeds memory block bounds [0..%jd]", 3680: firstIndex, hi, dim); 3681: return EXP_CANT_INTERPRET; 3682: } 3683: } 3684: if (aggregate->op==TOKarrayliteral) 3685: existingAE = (ArrayLiteralExp *)aggregate; 3686: else if (aggregate->op==TOKstring) 3687: existingSE = (StringExp *)aggregate; 3688: 3689: if (!wantRef && newval->op == TOKslice) 3690: { 3691: newval = resolveSlice(newval); 3692: if (newval == EXP_CANT_INTERPRET) 3693: { 3694: error("Compiler error: CTFE slice %s", toChars()); 3695: assert(0); 3696: } 3697: } 3698: 3699: // For slice assignment, we check that the lengths match. 3700: size_t srclen = 0; 3701: if (newval->op == TOKarrayliteral) 3702: srclen = ((ArrayLiteralExp *)newval)->elements->dim; 3703: else if (newval->op == TOKstring) 3704: srclen = ((StringExp *)newval)->len; 3705: if (!isBlockAssignment && srclen != (upperbound - lowerbound)) 3706: { 3707: error("Array length mismatch assigning [0..%d] to [%d..%d]", srclen, lowerbound, upperbound); 3708: return EXP_CANT_INTERPRET; 3709: } 3710: 3711: if (!isBlockAssignment && newval->op == TOKarrayliteral && existingAE) 3712: { 3713: Expressions *oldelems = existingAE->elements; 3714: Expressions *newelems = ((ArrayLiteralExp *)newval)->elements; 3715: for (size_t j = 0; j < newelems->dim; j++) 3716: { 3717: oldelems->tdata()[j + firstIndex] = newelems->tdata()[j]; 3718: } 3719: return newval; 3720: } 3721: else if (newval->op == TOKstring && existingSE) 3722: { 3723: sliceAssignStringFromString((StringExp *)existingSE, (StringExp *)newval, firstIndex); 3724: return newval; 3725: } 3726: else if (newval->op == TOKstring && existingAE) 3727: { /* Mixed slice: it was initialized as an array literal of chars. 3728: * Now a slice of it is being set with a string. 3729: */ 3730: sliceAssignArrayLiteralFromString(existingAE, (StringExp *)newval, firstIndex); 3731: return newval; 3732: } 3733: else if (newval->op == TOKarrayliteral && existingSE) 3734: { /* Mixed slice: it was initialized as a string literal. 3735: * Now a slice of it is being set with an array literal. 3736: */ 3737: sliceAssignStringFromArrayLiteral(existingSE, (ArrayLiteralExp *)newval, firstIndex); 3738: return newval; 3739: } 3740: else if (existingSE) 3741: { // String literal block slice assign 3742: unsigned value = newval->toInteger();
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'unsigned int', possible loss of data
3743: unsigned char *s = (unsigned char *)existingSE->string; 3744: for (size_t j = 0; j < upperbound-lowerbound; j++)
warning C4018: '<' : signed/unsigned mismatch
3745: { 3746: switch (existingSE->sz) 3747: { 3748: case 1: s[j+firstIndex] = value; break; 3749: case 2: ((unsigned short *)s)[j+firstIndex] = value; break; 3750: case 4: ((unsigned *)s)[j+firstIndex] = value; break; 3751: default: 3752: assert(0); 3753: break; 3754: } 3755: } 3756: if (goal == ctfeNeedNothing) 3757: return NULL; // avoid creating an unused literal 3758: SliceExp *retslice = new SliceExp(loc, existingSE, 3759: new IntegerExp(loc, firstIndex, Type::tsize_t), 3760: new IntegerExp(loc, firstIndex + upperbound-lowerbound, Type::tsize_t)); 3761: retslice->type = this->type; 3762: return retslice->interpret(istate); 3763: } 3764: else if (existingAE) 3765: { 3766: /* Block assignment, initialization of static arrays 3767: * x[] = e 3768: * x may be a multidimensional static array. (Note that this 3769: * only happens with array literals, never with strings). 3770: */ 3771: Expressions * w = existingAE->elements; 3772: assert( existingAE->type->ty == Tsarray || 3773: existingAE->type->ty == Tarray); 3774: #if DMDV2 3775: Type *desttype = ((TypeArray *)existingAE->type)->next->castMod(0); 3776: bool directblk = (e2->type->toBasetype()->castMod(0)) == desttype; 3777: #else 3778: Type *desttype = ((TypeArray *)existingAE->type)->next; 3779: bool directblk = (e2->type->toBasetype()) == desttype; 3780: #endif 3781: bool cow = !(newval->op == TOKstructliteral || newval->op == TOKarrayliteral 3782: || newval->op == TOKstring); 3783: for (size_t j = 0; j < upperbound-lowerbound; j++)
warning C4018: '<' : signed/unsigned mismatch
3784: { 3785: if (!directblk) 3786: // Multidimensional array block assign 3787: recursiveBlockAssign((ArrayLiteralExp *)w->tdata()[j+firstIndex], newval, wantRef); 3788: else 3789: { 3790: if (wantRef || cow) 3791: existingAE->elements->tdata()[j+firstIndex] = newval; 3792: else 3793: assignInPlace(existingAE->elements->tdata()[j+firstIndex], newval); 3794: } 3795: } 3796: if (goal == ctfeNeedNothing) 3797: return NULL; // avoid creating an unused literal 3798: SliceExp *retslice = new SliceExp(loc, existingAE, 3799: new IntegerExp(loc, firstIndex, Type::tsize_t), 3800: new IntegerExp(loc, firstIndex + upperbound-lowerbound, Type::tsize_t)); 3801: retslice->type = this->type; 3802: return retslice->interpret(istate); 3803: } 3804: else 3805: error("Slice operation %s cannot be evaluated at compile time", toChars()); 3806: } 3807: else 3808: { 3809: error("%s cannot be evaluated at compile time", toChars()); 3810: #ifdef DEBUG 3811: dump(0); 3812: #endif 3813: } 3814: return returnValue; 3815: } 3816: 3817: Expression *AssignExp::interpret(InterState *istate, CtfeGoal goal) 3818: { 3819: return interpretAssignCommon(istate, goal, NULL); 3820: } 3821: 3822: #define BIN_ASSIGN_INTERPRET(op) \ 3823: Expression *op##AssignExp::interpret(InterState *istate, CtfeGoal goal) \ 3824: { \ 3825: return interpretAssignCommon(istate, goal, &op); \ 3826: } 3827: 3828: BIN_ASSIGN_INTERPRET(Add) 3829: BIN_ASSIGN_INTERPRET(Min) 3830: BIN_ASSIGN_INTERPRET(Cat) 3831: BIN_ASSIGN_INTERPRET(Mul) 3832: BIN_ASSIGN_INTERPRET(Div) 3833: BIN_ASSIGN_INTERPRET(Mod) 3834: BIN_ASSIGN_INTERPRET(Shl) 3835: BIN_ASSIGN_INTERPRET(Shr) 3836: BIN_ASSIGN_INTERPRET(Ushr) 3837: BIN_ASSIGN_INTERPRET(And) 3838: BIN_ASSIGN_INTERPRET(Or) 3839: BIN_ASSIGN_INTERPRET(Xor) 3840: 3841: Expression *PostExp::interpret(InterState *istate, CtfeGoal goal) 3842: { 3843: #if LOG 3844: printf("PostExp::interpret() %s\n", toChars()); 3845: #endif 3846: Expression *e; 3847: if (op == TOKplusplus) 3848: e = interpretAssignCommon(istate, goal, &Add, 1); 3849: else 3850: e = interpretAssignCommon(istate, goal, &Min, 1); 3851: #if LOG 3852: if (e == EXP_CANT_INTERPRET) 3853: printf("PostExp::interpret() CANT\n"); 3854: #endif 3855: return e; 3856: } 3857: 3858: Expression *AndAndExp::interpret(InterState *istate, CtfeGoal goal) 3859: { 3860: #if LOG 3861: printf("AndAndExp::interpret() %s\n", toChars()); 3862: #endif 3863: Expression *e = e1->interpret(istate); 3864: if (e != EXP_CANT_INTERPRET) 3865: { 3866: if (e->isBool(FALSE)) 3867: e = new IntegerExp(e1->loc, 0, type); 3868: else if (isTrueBool(e)) 3869: { 3870: e = e2->interpret(istate); 3871: if (e != EXP_CANT_INTERPRET) 3872: { 3873: if (e->isBool(FALSE)) 3874: e = new IntegerExp(e1->loc, 0, type); 3875: else if (isTrueBool(e)) 3876: e = new IntegerExp(e1->loc, 1, type); 3877: else 3878: e = EXP_CANT_INTERPRET; 3879: } 3880: } 3881: else 3882: e = EXP_CANT_INTERPRET; 3883: } 3884: return e; 3885: } 3886: 3887: Expression *OrOrExp::interpret(InterState *istate, CtfeGoal goal) 3888: { 3889: #if LOG 3890: printf("OrOrExp::interpret() %s\n", toChars()); 3891: #endif 3892: Expression *e = e1->interpret(istate); 3893: if (e != EXP_CANT_INTERPRET) 3894: { 3895: if (isTrueBool(e)) 3896: e = new IntegerExp(e1->loc, 1, type); 3897: else if (e->isBool(FALSE)) 3898: { 3899: e = e2->interpret(istate); 3900: if (e != EXP_CANT_INTERPRET) 3901: { 3902: if (e->isBool(FALSE)) 3903: e = new IntegerExp(e1->loc, 0, type); 3904: else if (isTrueBool(e)) 3905: e = new IntegerExp(e1->loc, 1, type); 3906: else 3907: e = EXP_CANT_INTERPRET; 3908: } 3909: } 3910: else 3911: e = EXP_CANT_INTERPRET; 3912: } 3913: return e; 3914: } 3915: 3916: Expression *CallExp::interpret(InterState *istate, CtfeGoal goal) 3917: { Expression *e = EXP_CANT_INTERPRET; 3918: 3919: #if LOG 3920: printf("CallExp::interpret() %s\n", toChars()); 3921: #endif 3922: 3923: Expression * pthis = NULL; 3924: FuncDeclaration *fd = NULL; 3925: Expression *ecall = e1; 3926: if (ecall->op == TOKcall) 3927: { 3928: ecall = e1->interpret(istate); 3929: if (ecall == EXP_CANT_INTERPRET) 3930: return ecall; 3931: } 3932: if (ecall->op == TOKstar) 3933: { // Calling a function pointer 3934: Expression * pe = ((PtrExp*)ecall)->e1; 3935: if (pe->op == TOKvar) { 3936: VarDeclaration *vd = ((VarExp *)((PtrExp*)ecall)->e1)->var->isVarDeclaration(); 3937: if (vd && vd->getValue() && vd->getValue()->op == TOKsymoff) 3938: fd = ((SymOffExp *)vd->getValue())->var->isFuncDeclaration(); 3939: else 3940: { 3941: ecall = getVarExp(loc, istate, vd, goal); 3942: if (ecall == EXP_CANT_INTERPRET) 3943: return ecall; 3944: 3945: if (ecall->op == TOKsymoff) 3946: fd = ((SymOffExp *)ecall)->var->isFuncDeclaration(); 3947: } 3948: } 3949: else 3950: ecall = ((PtrExp*)ecall)->e1->interpret(istate); 3951: 3952: } 3953: if (ecall == EXP_CANT_INTERPRET) 3954: return ecall; 3955: 3956: if (ecall->op == TOKindex) 3957: { ecall = e1->interpret(istate); 3958: if (ecall == EXP_CANT_INTERPRET) 3959: return ecall; 3960: } 3961: 3962: if (ecall->op == TOKdotvar && !((DotVarExp*)ecall)->var->isFuncDeclaration()) 3963: { ecall = e1->interpret(istate); 3964: if (ecall == EXP_CANT_INTERPRET) 3965: return ecall; 3966: } 3967: 3968: if (ecall->op == TOKdotvar) 3969: { // Calling a member function 3970: pthis = ((DotVarExp*)e1)->e1; 3971: fd = ((DotVarExp*)e1)->var->isFuncDeclaration(); 3972: } 3973: else if (ecall->op == TOKvar) 3974: { 3975: VarDeclaration *vd = ((VarExp *)ecall)->var->isVarDeclaration(); 3976: if (vd && vd->getValue()) 3977: ecall = vd->getValue(); 3978: else // Calling a function 3979: fd = ((VarExp *)e1)->var->isFuncDeclaration(); 3980: } 3981: if (ecall->op == TOKdelegate) 3982: { // Calling a delegate 3983: fd = ((DelegateExp *)ecall)->func; 3984: pthis = ((DelegateExp *)ecall)->e1; 3985: } 3986: else if (ecall->op == TOKfunction) 3987: { // Calling a delegate literal 3988: fd = ((FuncExp*)ecall)->fd; 3989: } 3990: else if (ecall->op == TOKstar && ((PtrExp*)ecall)->e1->op==TOKfunction) 3991: { // Calling a function literal 3992: fd = ((FuncExp*)((PtrExp*)ecall)->e1)->fd; 3993: } 3994: 3995: TypeFunction *tf = fd ? (TypeFunction *)(fd->type) : NULL; 3996: if (!tf) 3997: { // DAC: I'm not sure if this ever happens 3998: //printf("ecall=%s %d %d\n", ecall->toChars(), ecall->op, TOKcall); 3999: error("cannot evaluate %s at compile time", toChars()); 4000: return EXP_CANT_INTERPRET; 4001: } 4002: if (!fd) 4003: { 4004: error("cannot evaluate %s at compile time", toChars()); 4005: return EXP_CANT_INTERPRET; 4006: } 4007: if (pthis) 4008: { // Member function call 4009: if (pthis->op == TOKthis) 4010: pthis = istate ? istate->localThis : NULL; 4011: else 4012: { 4013: if (pthis->op == TOKcomma) 4014: pthis = pthis->interpret(istate); 4015: if (pthis == EXP_CANT_INTERPRET) 4016: return EXP_CANT_INTERPRET; 4017: // Evaluate 'this' 4018: if (pthis->op != TOKvar) 4019: pthis = pthis->interpret(istate, ctfeNeedLvalue); 4020: if (pthis == EXP_CANT_INTERPRET) 4021: return EXP_CANT_INTERPRET; 4022: } 4023: } 4024: // Check for built-in functions 4025: Expression *eresult; 4026: if (evaluateIfBuiltin(&eresult, istate, fd, arguments, pthis)) 4027: return eresult; 4028: 4029: // Inline .dup. Special case because it needs the return type. 4030: if (!pthis && fd->ident == Id::adDup && arguments && arguments->dim == 2) 4031: { 4032: e = arguments->tdata()[1]; 4033: e = e->interpret(istate); 4034: if (e != EXP_CANT_INTERPRET) 4035: { 4036: if (e->op == TOKslice) 4037: e= resolveSlice(e); 4038: e = expType(type, e); 4039: e = copyLiteral(e); 4040: } 4041: return e; 4042: } 4043: if (!fd->fbody) 4044: { 4045: error("%s cannot be interpreted at compile time," 4046: " because it has no available source code", fd->toChars()); 4047: return EXP_CANT_INTERPRET; 4048: } 4049: eresult = fd->interpret(istate, arguments, pthis); 4050: if (eresult) 4051: e = eresult; 4052: else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors) 4053: e = EXP_VOID_INTERPRET; 4054: else 4055: error("cannot evaluate %s at compile time", toChars()); 4056: return e; 4057: } 4058: 4059: Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal) 4060: { 4061: #if LOG 4062: printf("CommaExp::interpret() %s\n", toChars()); 4063: #endif 4064: 4065: CommaExp * firstComma = this; 4066: while (firstComma->e1->op == TOKcomma) 4067: firstComma = (CommaExp *)firstComma->e1; 4068: 4069: // If it creates a variable, and there's no context for 4070: // the variable to be created in, we need to create one now. 4071: InterState istateComma; 4072: if (!istate && firstComma->e1->op == TOKdeclaration) 4073: istate = &istateComma; 4074: 4075: // If the comma returns a temporary variable, it needs to be an lvalue 4076: // (this is particularly important for struct constructors) 4077: if (e1->op == TOKdeclaration && e2->op == TOKvar 4078: && ((DeclarationExp *)e1)->declaration == ((VarExp*)e2)->var 4079: && ((VarExp*)e2)->var->storage_class & STCctfe) // same as Expression::isTemp 4080: { 4081: VarExp* ve = (VarExp *)e2; 4082: VarDeclaration *v = ve->var->isVarDeclaration(); 4083: if (!v->init && !v->getValue()) 4084: { 4085: v->createRefValue(copyLiteral(v->type->defaultInitLiteral())); 4086: } 4087: if (!v->getValue()) { 4088: Expression *newval = v->init->toExpression(); 4089: // v->setRefValue(v->init->toExpression()); 4090: // Bug 4027. Copy constructors are a weird case where the 4091: // initializer is a void function (the variable is modified 4092: // through a reference parameter instead). 4093: newval = newval->interpret(istate); 4094: if (newval == EXP_CANT_INTERPRET) 4095: return EXP_CANT_INTERPRET; 4096: if (newval != EXP_VOID_INTERPRET) 4097: { 4098: // v isn't necessarily null. 4099: v->setValueWithoutChecking(copyLiteral(newval)); 4100: } 4101: } 4102: if (goal == ctfeNeedLvalue || goal == ctfeNeedLvalueRef) 4103: return e2; 4104: return e2->interpret(istate, goal); 4105: } 4106: Expression *e = e1->interpret(istate, ctfeNeedNothing); 4107: if (e != EXP_CANT_INTERPRET) 4108: e = e2->interpret(istate, goal); 4109: return e; 4110: } 4111: 4112: Expression *CondExp::interpret(InterState *istate, CtfeGoal goal) 4113: { 4114: #if LOG 4115: printf("CondExp::interpret() %s\n", toChars()); 4116: #endif 4117: Expression *e; 4118: if (econd->type->ty == Tpointer && econd->type->nextOf()->ty != Tfunction) 4119: { 4120: e = econd->interpret(istate, ctfeNeedLvalue); 4121: if (e == EXP_CANT_INTERPRET) 4122: return e; 4123: if (e->op != TOKnull) 4124: e = new IntegerExp(loc, 1, Type::tbool); 4125: } 4126: else 4127: e = econd->interpret(istate); 4128: if (e != EXP_CANT_INTERPRET) 4129: { 4130: if (isTrueBool(e)) 4131: e = e1->interpret(istate, goal); 4132: else if (e->isBool(FALSE)) 4133: e = e2->interpret(istate, goal); 4134: else 4135: { 4136: error("%s does not evaluate to boolean result at compile time", 4137: econd->toChars()); 4138: e = EXP_CANT_INTERPRET; 4139: } 4140: } 4141: return e; 4142: } 4143: 4144: Expression *ArrayLengthExp::interpret(InterState *istate, CtfeGoal goal) 4145: { Expression *e; 4146: Expression *e1; 4147: 4148: #if LOG 4149: printf("ArrayLengthExp::interpret() %s\n", toChars()); 4150: #endif 4151: e1 = this->e1->interpret(istate); 4152: assert(e1); 4153: if (e1 == EXP_CANT_INTERPRET) 4154: return EXP_CANT_INTERPRET; 4155: if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKslice 4156: || e1->op == TOKassocarrayliteral || e1->op == TOKnull) 4157: { 4158: e = new IntegerExp(loc, resolveArrayLength(e1), type); 4159: } 4160: else 4161: { 4162: error("%s cannot be evaluated at compile time", toChars()); 4163: return EXP_CANT_INTERPRET; 4164: } 4165: return e; 4166: } 4167: 4168: /* Given an AA literal 'ae', and a key 'e2': 4169: * Return ae[e2] if present, or NULL if not found. 4170: * Return EXP_CANT_INTERPRET on error. 4171: */ 4172: Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2) 4173: { 4174: /* Search the keys backwards, in case there are duplicate keys 4175: */ 4176: for (size_t i = ae->keys->dim; i;) 4177: { 4178: i--; 4179: Expression *ekey = ae->keys->tdata()[i]; 4180: Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, e2); 4181: if (ex == EXP_CANT_INTERPRET) 4182: { 4183: error("cannot evaluate %s==%s at compile time", 4184: ekey->toChars(), e2->toChars()); 4185: return ex; 4186: } 4187: if (ex->isBool(TRUE)) 4188: { 4189: return ae->values->tdata()[i]; 4190: } 4191: } 4192: return NULL; 4193: } 4194: 4195: Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal) 4196: { 4197: Expression *e1 = NULL; 4198: Expression *e2; 4199: 4200: #if LOG 4201: printf("IndexExp::interpret() %s\n", toChars()); 4202: #endif 4203: if (this->e1->type->toBasetype()->ty == Tpointer) 4204: { 4205: // Indexing a pointer. Note that there is no $ in this case. 4206: e1 = this->e1->interpret(istate); 4207: if (e1 == EXP_CANT_INTERPRET) 4208: return EXP_CANT_INTERPRET; 4209: 4210: e2 = this->e2->interpret(istate); 4211: if (e2 == EXP_CANT_INTERPRET) 4212: return EXP_CANT_INTERPRET; 4213: dinteger_t indx = e2->toInteger(); 4214: Expression *e;
warning C4101: 'e' : unreferenced local variable
4215: dinteger_t ofs; 4216: Expression *agg = getAggregateFromPointer(e1, &ofs); 4217: if (agg->op == TOKnull) 4218: { 4219: error("cannot index null pointer %s", this->e1->toChars()); 4220: return EXP_CANT_INTERPRET; 4221: } 4222: assert(agg->op == TOKarrayliteral || agg->op == TOKstring); 4223: dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger(); 4224: Type *pointee = ((TypePointer *)agg->type)->next; 4225: if ((indx + ofs) < 0 || (indx+ofs) > len) 4226: { 4227: error("pointer index [%jd] exceeds allocated memory block [0..%jd]", 4228: indx+ofs, len); 4229: return EXP_CANT_INTERPRET; 4230: } 4231: return Index(type, agg, new IntegerExp(loc, indx+ofs, Type::tsize_t)); 4232: } 4233: e1 = this->e1->interpret(istate); 4234: if (e1 == EXP_CANT_INTERPRET) 4235: return EXP_CANT_INTERPRET; 4236: 4237: if (e1->op == TOKnull) 4238: { 4239: error("cannot index null array %s", this->e1->toChars()); 4240: return EXP_CANT_INTERPRET; 4241: } 4242: /* Set the $ variable. 4243: * Note that foreach uses indexing but doesn't need $ 4244: */ 4245: if (lengthVar && (e1->op == TOKstring || e1->op == TOKarrayliteral 4246: || e1->op == TOKslice)) 4247: { 4248: uinteger_t dollar = resolveArrayLength(e1); 4249: Expression *dollarExp = new IntegerExp(loc, dollar, Type::tsize_t); 4250: lengthVar->createStackValue(dollarExp); 4251: } 4252: 4253: e2 = this->e2->interpret(istate); 4254: if (lengthVar) 4255: lengthVar->setValueNull(); // $ is defined only inside [] 4256: if (e2 == EXP_CANT_INTERPRET) 4257: return EXP_CANT_INTERPRET; 4258: if (e1->op == TOKslice && e2->op == TOKint64) 4259: { 4260: // Simplify index of slice: agg[lwr..upr][indx] --> agg[indx'] 4261: uinteger_t indx = e2->toInteger(); 4262: uinteger_t ilo = ((SliceExp *)e1)->lwr->toInteger(); 4263: uinteger_t iup = ((SliceExp *)e1)->upr->toInteger(); 4264: 4265: if (indx > iup - ilo) 4266: { 4267: error("index %ju exceeds array length %ju", indx, iup - ilo); 4268: return EXP_CANT_INTERPRET; 4269: } 4270: indx += ilo; 4271: e1 = ((SliceExp *)e1)->e1; 4272: e2 = new IntegerExp(e2->loc, indx, e2->type); 4273: } 4274: Expression *e = NULL; 4275: if ((goal == ctfeNeedLvalue && type->ty != Taarray && type->ty != Tarray 4276: && type->ty != Tsarray && type->ty != Tstruct && type->ty != Tclass) 4277: || (goal == ctfeNeedLvalueRef && type->ty != Tsarray && type->ty != Tstruct) 4278: ) 4279: { // Pointer or reference of a scalar type 4280: e = new IndexExp(loc, e1, e2); 4281: e->type = type; 4282: return e; 4283: } 4284: if (e1->op == TOKassocarrayliteral) 4285: { 4286: if (e2->op == TOKslice) 4287: e2 = resolveSlice(e2); 4288: e = findKeyInAA((AssocArrayLiteralExp *)e1, e2); 4289: if (!e) 4290: { 4291: error("key %s not found in associative array %s", 4292: e2->toChars(), this->e1->toChars()); 4293: return EXP_CANT_INTERPRET; 4294: } 4295: if (e == EXP_CANT_INTERPRET) 4296: return e; 4297: assert(!e->checkSideEffect(2)); 4298: e = paintTypeOntoLiteral(type, e); 4299: } 4300: else 4301: { 4302: e = Index(type, e1, e2); 4303: } 4304: if (e == EXP_CANT_INTERPRET) 4305: { 4306: error("%s cannot be interpreted at compile time", toChars()); 4307: return e; 4308: } 4309: if (goal == ctfeNeedRvalue && (e->op == TOKslice || e->op == TOKdotvar)) 4310: e = e->interpret(istate); 4311: return e; 4312: } 4313: 4314: 4315: Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal) 4316: { 4317: Expression *e1; 4318: Expression *lwr; 4319: Expression *upr; 4320: 4321: #if LOG 4322: printf("SliceExp::interpret() %s\n", toChars()); 4323: #endif 4324: 4325: if (this->e1->type->toBasetype()->ty == Tpointer) 4326: { 4327: // Slicing a pointer. Note that there is no $ in this case. 4328: e1 = this->e1->interpret(istate); 4329: if (e1 == EXP_CANT_INTERPRET) 4330: return EXP_CANT_INTERPRET; 4331: 4332: /* Evaluate lower and upper bounds of slice 4333: */ 4334: lwr = this->lwr->interpret(istate); 4335: if (lwr == EXP_CANT_INTERPRET) 4336: return EXP_CANT_INTERPRET; 4337: upr = this->upr->interpret(istate); 4338: if (upr == EXP_CANT_INTERPRET) 4339: return EXP_CANT_INTERPRET; 4340: uinteger_t ilwr; 4341: uinteger_t iupr; 4342: ilwr = lwr->toInteger(); 4343: iupr = upr->toInteger(); 4344: Expression *e; 4345: dinteger_t ofs; 4346: Expression *agg = getAggregateFromPointer(e1, &ofs); 4347: if (agg->op == TOKnull) 4348: { 4349: if (iupr == ilwr) 4350: { 4351: e = new NullExp(loc); 4352: e->type = type; 4353: return e; 4354: } 4355: error("cannot slice null pointer %s", this->e1->toChars()); 4356: return EXP_CANT_INTERPRET; 4357: } 4358: assert(agg->op == TOKarrayliteral || agg->op == TOKstring); 4359: dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger(); 4360: Type *pointee = ((TypePointer *)agg->type)->next; 4361: if ((ilwr + ofs) < 0 || (iupr+ofs) > (len + 1) || iupr < ilwr) 4362: { 4363: error("pointer slice [%jd..%jd] exceeds allocated memory block [0..%jd]", 4364: ilwr+ofs, iupr+ofs, len); 4365: return EXP_CANT_INTERPRET; 4366: } 4367: e = new SliceExp(loc, agg, lwr, upr); 4368: e->type = type; 4369: return e; 4370: } 4371: if (goal == ctfeNeedRvalue && this->e1->op == TOKstring) 4372: e1 = this->e1; // Will get duplicated anyway 4373: else 4374: e1 = this->e1->interpret(istate, goal); 4375: if (e1 == EXP_CANT_INTERPRET) 4376: return EXP_CANT_INTERPRET; 4377: if (e1->op == TOKvar) 4378: e1 = e1->interpret(istate); 4379: 4380: if (!this->lwr) 4381: { 4382: if (goal == ctfeNeedLvalue || goal == ctfeNeedLvalueRef) 4383: return e1; 4384: Expression *e = e1->castTo(NULL, type); 4385: return e->interpret(istate); 4386: } 4387: 4388: /* Set the $ variable 4389: */ 4390: if (e1->op != TOKarrayliteral && e1->op != TOKstring && 4391: e1->op != TOKnull && e1->op != TOKslice) 4392: { 4393: error("Cannot determine length of %s at compile time\n", e1->toChars()); 4394: return EXP_CANT_INTERPRET; 4395: } 4396: uinteger_t dollar = resolveArrayLength(e1); 4397: if (lengthVar) 4398: { 4399: IntegerExp *dollarExp = new IntegerExp(loc, dollar, Type::tsize_t); 4400: lengthVar->createStackValue(dollarExp); 4401: } 4402: 4403: /* Evaluate lower and upper bounds of slice 4404: */ 4405: lwr = this->lwr->interpret(istate); 4406: if (lwr != EXP_CANT_INTERPRET) 4407: upr = this->upr->interpret(istate); 4408: if (lengthVar) 4409: lengthVar->setValueNull(); // $ is defined only inside [L..U] 4410: if (lwr == EXP_CANT_INTERPRET || upr == EXP_CANT_INTERPRET) 4411: { 4412: return EXP_CANT_INTERPRET; 4413: } 4414: 4415: Expression *e; 4416: uinteger_t ilwr; 4417: uinteger_t iupr; 4418: ilwr = lwr->toInteger(); 4419: iupr = upr->toInteger(); 4420: if (e1->op == TOKnull) 4421: { 4422: if (ilwr== 0 && iupr == 0) 4423: return e1; 4424: e1->error("slice [%ju..%ju] is out of bounds", ilwr, iupr); 4425: return EXP_CANT_INTERPRET; 4426: } 4427: if (e1->op == TOKslice) 4428: { 4429: SliceExp *se = (SliceExp *)e1; 4430: // Simplify slice of slice: 4431: // aggregate[lo1..up1][lwr..upr] ---> aggregate[lwr'..upr'] 4432: uinteger_t lo1 = se->lwr->toInteger(); 4433: uinteger_t up1 = se->upr->toInteger(); 4434: if (ilwr > iupr || iupr > up1 - lo1) 4435: { 4436: error("slice[%ju..%ju] exceeds array bounds[%ju..%ju]", 4437: ilwr, iupr, lo1, up1); 4438: return EXP_CANT_INTERPRET; 4439: } 4440: ilwr += lo1; 4441: iupr += lo1; 4442: e = new SliceExp(loc, se->e1, 4443: new IntegerExp(loc, ilwr, lwr->type), 4444: new IntegerExp(loc, iupr, upr->type)); 4445: e->type = type; 4446: return e; 4447: } 4448: if (e1->op == TOKarrayliteral 4449: || e1->op == TOKstring) 4450: { 4451: if (iupr < ilwr || ilwr < 0 || iupr > dollar) 4452: { 4453: error("slice [%jd..%jd] exceeds array bounds [0..%jd]", 4454: ilwr, iupr, dollar); 4455: return EXP_CANT_INTERPRET; 4456: } 4457: } 4458: e = new SliceExp(loc, e1, lwr, upr); 4459: e->type = type; 4460: return e; 4461: } 4462: 4463: Expression *InExp::interpret(InterState *istate, CtfeGoal goal) 4464: { Expression *e = EXP_CANT_INTERPRET; 4465: 4466: #if LOG 4467: printf("InExp::interpret() %s\n", toChars()); 4468: #endif 4469: Expression *e1 = this->e1->interpret(istate); 4470: if (e1 == EXP_CANT_INTERPRET) 4471: return e1; 4472: Expression *e2 = this->e2->interpret(istate); 4473: if (e2 == EXP_CANT_INTERPRET) 4474: return e2; 4475: if (e2->op == TOKnull) 4476: return new NullExp(loc, type); 4477: if (e2->op != TOKassocarrayliteral) 4478: { 4479: error(" %s cannot be interpreted at compile time", toChars()); 4480: return EXP_CANT_INTERPRET; 4481: } 4482: if (e1->op == TOKslice) 4483: e1 = resolveSlice(e1); 4484: e = findKeyInAA((AssocArrayLiteralExp *)e2, e1); 4485: if (e == EXP_CANT_INTERPRET) 4486: return e; 4487: if (!e) 4488: return new NullExp(loc, type); 4489: e = new IndexExp(loc, e2, e1); 4490: e->type = type; 4491: return e; 4492: } 4493: 4494: Expression *CatExp::interpret(InterState *istate, CtfeGoal goal) 4495: { Expression *e; 4496: Expression *e1; 4497: Expression *e2; 4498: 4499: #if LOG 4500: printf("CatExp::interpret() %s\n", toChars()); 4501: #endif 4502: e1 = this->e1->interpret(istate); 4503: if (e1 == EXP_CANT_INTERPRET) 4504: { 4505: goto Lcant; 4506: } 4507: if (e1->op == TOKslice) 4508: { 4509: e1 = resolveSlice(e1); 4510: } 4511: e2 = this->e2->interpret(istate); 4512: if (e2 == EXP_CANT_INTERPRET) 4513: goto Lcant; 4514: if (e2->op == TOKslice) 4515: e2 = resolveSlice(e2); 4516: e = Cat(type, e1, e2); 4517: if (e == EXP_CANT_INTERPRET) 4518: error("%s cannot be interpreted at compile time", toChars()); 4519: return e; 4520: 4521: Lcant: 4522: #if LOG 4523: printf("CatExp::interpret() %s CANT\n", toChars()); 4524: #endif 4525: return EXP_CANT_INTERPRET; 4526: } 4527: 4528: 4529: Expression *CastExp::interpret(InterState *istate, CtfeGoal goal) 4530: { Expression *e; 4531: Expression *e1; 4532: 4533: #if LOG 4534: printf("CastExp::interpret() %s\n", toChars()); 4535: #endif 4536: e1 = this->e1->interpret(istate, goal); 4537: if (e1 == EXP_CANT_INTERPRET) 4538: goto Lcant; 4539: if (to->ty == Tpointer && e1->op != TOKnull) 4540: { // Deal with casts from char[] to char * 4541: if (e1->op == TOKslice) 4542: { 4543: if ( ((SliceExp *)e1)->e1->op == TOKnull) 4544: { 4545: return paintTypeOntoLiteral(type, ((SliceExp *)e1)->e1); 4546: } 4547: e = new IndexExp(loc, ((SliceExp *)e1)->e1, ((SliceExp *)e1)->lwr); 4548: e->type = type; 4549: return e; 4550: } 4551: if (e1->op == TOKarrayliteral) 4552: { 4553: e = new IndexExp(loc, e1, new IntegerExp(loc, 0, Type::tsize_t)); 4554: e->type = type; 4555: return e; 4556: } 4557: if (e1->op == TOKstring) 4558: { 4559: return e1; 4560: } 4561: if (e1->op == TOKindex && ((IndexExp *)e1)->e1->type != e1->type) 4562: { // type painting operation 4563: IndexExp *ie = (IndexExp *)e1; 4564: e = new IndexExp(e1->loc, ie->e1, ie->e2); 4565: e->type = type; 4566: return e; 4567: } 4568: error("pointer cast from %s to %s is not supported at compile time", 4569: e1->type->toChars(), to->toChars()); 4570: return EXP_CANT_INTERPRET; 4571: } 4572: if (to->ty == Tarray && e1->op == TOKslice) 4573: { 4574: e1 = new SliceExp(e1->loc, ((SliceExp *)e1)->e1, ((SliceExp *)e1)->lwr, 4575: ((SliceExp *)e1)->upr); 4576: e1->type = to; 4577: return e1; 4578: } 4579: // Disallow array type painting, except for conversions between built-in 4580: // types of identical size. 4581: if ((to->ty == Tsarray || to->ty == Tarray) && 4582: (e1->type->ty == Tsarray || e1->type->ty == Tarray) && 4583: #if DMDV2 4584: e1->type->nextOf()->castMod(0) != to->nextOf()->castMod(0) 4585: #else 4586: e1->type->nextOf() != to->nextOf() 4587: #endif 4588: && !(to->nextOf()->isTypeBasic() && e1->type->nextOf()->isTypeBasic() 4589: && to->nextOf()->size() == e1->type->nextOf()->size()) ) 4590: { 4591: error("array cast from %s to %s is not supported at compile time", e1->type->toChars(), to->toChars()); 4592: return EXP_CANT_INTERPRET; 4593: } 4594: if (to->ty == Tsarray && e1->op == TOKslice) 4595: e1 = resolveSlice(e1); 4596: if (to->toBasetype()->ty == Tbool && e1->type->ty==Tpointer) 4597: { 4598: return new IntegerExp(loc, e1->op != TOKnull, to); 4599: } 4600: if (e1->op == TOKnull) 4601: return paintTypeOntoLiteral(to, e1); 4602: 4603: e = Cast(type, to, e1); 4604: if (e == EXP_CANT_INTERPRET) 4605: error("%s cannot be interpreted at compile time", toChars()); 4606: return e; 4607: 4608: Lcant: 4609: #if LOG 4610: printf("CastExp::interpret() %s CANT\n", toChars()); 4611: #endif 4612: return EXP_CANT_INTERPRET; 4613: } 4614: 4615: 4616: Expression *AssertExp::interpret(InterState *istate, CtfeGoal goal) 4617: { Expression *e; 4618: Expression *e1; 4619: 4620: #if LOG 4621: printf("AssertExp::interpret() %s\n", toChars()); 4622: #endif 4623: if (this->e1->op == TOKthis) 4624: { 4625: if (istate->localThis) 4626: { 4627: if (istate->localThis->op == TOKdotvar 4628: && ((DotVarExp *)(istate->localThis))->e1->op == TOKthis) 4629: return getVarExp(loc, istate, ((DotVarExp*)(istate->localThis))->var, ctfeNeedRvalue); 4630: else 4631: return istate->localThis->interpret(istate); 4632: } 4633: } 4634: // Deal with pointers (including compiler-inserted assert(&this, "null this")) 4635: if (this->e1->type->ty == Tpointer && this->e1->type->nextOf()->ty != Tfunction) 4636: { 4637: e1 = this->e1->interpret(istate, ctfeNeedLvalue); 4638: if (e1 == EXP_CANT_INTERPRET) 4639: goto Lcant; 4640: if (e1->op != TOKnull) 4641: return new IntegerExp(loc, 1, Type::tbool); 4642: } 4643: else 4644: e1 = this->e1->interpret(istate); 4645: if (e1 == EXP_CANT_INTERPRET) 4646: goto Lcant; 4647: if (isTrueBool(e1)) 4648: { 4649: } 4650: else if (e1->isBool(FALSE)) 4651: { 4652: if (msg) 4653: { 4654: e = msg->interpret(istate); 4655: if (e == EXP_CANT_INTERPRET) 4656: goto Lcant; 4657: error("%s", e->toChars()); 4658: } 4659: else 4660: error("%s failed", toChars()); 4661: goto Lcant; 4662: } 4663: else 4664: { 4665: error("%s is not a compile-time boolean expression", e1->toChars()); 4666: goto Lcant; 4667: } 4668: return e1; 4669: 4670: Lcant: 4671: return EXP_CANT_INTERPRET; 4672: } 4673: 4674: Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal) 4675: { Expression *e = EXP_CANT_INTERPRET; 4676: 4677: #if LOG 4678: printf("PtrExp::interpret() %s\n", toChars()); 4679: #endif 4680: // Constant fold *(&structliteral + offset) 4681: if (e1->op == TOKadd) 4682: { AddExp *ae = (AddExp *)e1; 4683: if (ae->e1->op == TOKaddress && ae->e2->op == TOKint64) 4684: { AddrExp *ade = (AddrExp *)ae->e1; 4685: Expression *ex = ade->e1; 4686: ex = ex->interpret(istate); 4687: if (ex != EXP_CANT_INTERPRET) 4688: { 4689: if (ex->op == TOKstructliteral) 4690: { StructLiteralExp *se = (StructLiteralExp *)ex; 4691: unsigned offset = ae->e2->toInteger();
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'unsigned int', possible loss of data
4692: e = se->getField(type, offset); 4693: if (!e) 4694: e = EXP_CANT_INTERPRET; 4695: return e; 4696: } 4697: } 4698: } 4699: e = Ptr(type, e1); 4700: } 4701: #if DMDV2 4702: #else // this is required for D1, where structs return *this instead of 'this'. 4703: else if (e1->op == TOKthis) 4704: { 4705: if(istate->localThis) 4706: return istate->localThis->interpret(istate); 4707: } 4708: #endif 4709: else 4710: { // It's possible we have an array bounds error. We need to make sure it 4711: // errors with this line number, not the one where the pointer was set. 4712: e = e1->interpret(istate, ctfeNeedLvalue); 4713: if (e == EXP_CANT_INTERPRET) 4714: return e; 4715: if (goal != ctfeNeedLvalue) 4716: { 4717: if (e->op == TOKindex && e->type->ty == Tpointer) 4718: { 4719: IndexExp *ie = (IndexExp *)e; 4720: if ((ie->e1->op == TOKarrayliteral || ie->e1->op == TOKstring) 4721: && ie->e2->op == TOKint64) 4722: { 4723: Expression *dollar = ArrayLength(Type::tsize_t, ie->e1); 4724: dinteger_t len = dollar->toInteger(); 4725: dinteger_t indx = ie->e2->toInteger(); 4726: assert(indx >=0 && indx <= len); // invalid pointer 4727: if (indx == len) 4728: { 4729: error("dereference of pointer %s one past end of memory block limits [0..%jd]", 4730: toChars(), len); 4731: return EXP_CANT_INTERPRET; 4732: } 4733: return Index(type, ie->e1, ie->e2); 4734: } 4735: if (ie->e1->op == TOKassocarrayliteral) 4736: return Index(type, ie->e1, ie->e2); 4737: } 4738: if (e->op == TOKstructliteral) 4739: return e; 4740: e = e1->interpret(istate, goal); 4741: if (e->op == TOKaddress) 4742: { 4743: e = ((AddrExp*)e)->e1; 4744: if (e->op == TOKdotvar || e->op == TOKindex) 4745: e = e->interpret(istate, goal); 4746: } 4747: if (e == EXP_CANT_INTERPRET) 4748: return e; 4749: } 4750: else if (e->op == TOKaddress) 4751: e = ((AddrExp*)e)->e1; // *(&x) ==> x 4752: if (e->op == TOKnull) 4753: { 4754: error("dereference of null pointer '%s'", e1->toChars()); 4755: return EXP_CANT_INTERPRET; 4756: } 4757: e->type = type; 4758: } 4759: 4760: #if LOG 4761: if (e == EXP_CANT_INTERPRET) 4762: printf("PtrExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars()); 4763: #endif 4764: return e; 4765: } 4766: 4767: Expression *DotVarExp::interpret(InterState *istate, CtfeGoal goal) 4768: { Expression *e = EXP_CANT_INTERPRET; 4769: 4770: #if LOG 4771: printf("DotVarExp::interpret() %s\n", toChars()); 4772: #endif 4773: 4774: Expression *ex = e1->interpret(istate); 4775: if (ex != EXP_CANT_INTERPRET) 4776: { 4777: if (ex->op == TOKaddress) 4778: ex = ((AddrExp *)ex)->e1; 4779: if (ex->op == TOKstructliteral) 4780: { StructLiteralExp *se = (StructLiteralExp *)ex; 4781: VarDeclaration *v = var->isVarDeclaration(); 4782: if (v) 4783: { 4784: if (goal == ctfeNeedLvalue || goal == ctfeNeedLvalueRef) 4785: { 4786: // We can't use getField, because it makes a copy 4787: int i = se->getFieldIndex(type, v->offset); 4788: if (i == -1) 4789: { 4790: error("couldn't find field %s in %s", v->toChars(), type->toChars()); 4791: return EXP_CANT_INTERPRET; 4792: } 4793: e = se->elements->tdata()[i]; 4794: // If it is an lvalue literal, return it... 4795: if (e->op == TOKstructliteral) 4796: return e; 4797: if ((type->ty == Tsarray || goal == ctfeNeedLvalue) && ( 4798: e->op == TOKarrayliteral || 4799: e->op == TOKassocarrayliteral || e->op == TOKstring || 4800: e->op == TOKslice)) 4801: return e; 4802: /* Element is an allocated pointer, which was created in 4803: * CastExp. 4804: */ 4805: if (goal == ctfeNeedLvalue && e->op == TOKindex && 4806: e->type == type && 4807: (type->ty == Tpointer && type->nextOf()->ty != Tfunction)) 4808: return e; 4809: // ...Otherwise, just return the (simplified) dotvar expression 4810: e = new DotVarExp(loc, ex, v); 4811: e->type = type; 4812: return e; 4813: } 4814: e = se->getField(type, v->offset); 4815: if (!e) 4816: { 4817: error("couldn't find field %s in %s", v->toChars(), type->toChars()); 4818: e = EXP_CANT_INTERPRET; 4819: } 4820: // If it is an rvalue literal, return it... 4821: if (e->op == TOKstructliteral || e->op == TOKarrayliteral || 4822: e->op == TOKassocarrayliteral || e->op == TOKstring) 4823: return e; 4824: if (type->ty == Tpointer && type->nextOf()->ty != Tfunction) 4825: { 4826: assert(e->type == type); 4827: return e; 4828: } 4829: return e->interpret(istate, goal); 4830: } 4831: } 4832: else 4833: error("%s.%s is not yet implemented at compile time", e1->toChars(), var->toChars()); 4834: } 4835: 4836: #if LOG 4837: if (e == EXP_CANT_INTERPRET) 4838: printf("DotVarExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars()); 4839: #endif 4840: return e; 4841: } 4842: 4843: /******************************* Special Functions ***************************/ 4844: 4845: #if DMDV1 4846: 4847: Expression *interpret_aaLen(InterState *istate, Expressions *arguments) 4848: { 4849: if (!arguments || arguments->dim != 1) 4850: return NULL; 4851: Expression *earg = arguments->tdata()[0]; 4852: earg = earg->interpret(istate); 4853: if (earg == EXP_CANT_INTERPRET) 4854: return NULL; 4855: if (earg->op != TOKassocarrayliteral) 4856: return NULL; 4857: AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; 4858: Expression *e = new IntegerExp(aae->loc, aae->keys->dim, Type::tsize_t); 4859: return e; 4860: } 4861: 4862: Expression *interpret_aaKeys(InterState *istate, Expressions *arguments) 4863: { 4864: #if LOG 4865: printf("interpret_aaKeys()\n"); 4866: #endif 4867: if (!arguments || arguments->dim != 2) 4868: return NULL; 4869: Expression *earg = arguments->tdata()[0]; 4870: earg = earg->interpret(istate); 4871: if (earg == EXP_CANT_INTERPRET) 4872: return NULL; 4873: if (earg->op == TOKnull) 4874: return new NullExp(earg->loc); 4875: if (earg->op != TOKassocarrayliteral && earg->type->toBasetype()->ty != Taarray) 4876: return NULL; 4877: AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; 4878: Expression *e = new ArrayLiteralExp(aae->loc, aae->keys); 4879: Type *elemType = ((TypeAArray *)aae->type)->index; 4880: e->type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments->dim : 0)); 4881: return copyLiteral(e); 4882: } 4883: 4884: Expression *interpret_aaValues(InterState *istate, Expressions *arguments) 4885: { 4886: #if LOG 4887: printf("interpret_aaValues()\n"); 4888: #endif 4889: if (!arguments || arguments->dim != 3) 4890: return NULL; 4891: Expression *earg = arguments->tdata()[0]; 4892: earg = earg->interpret(istate); 4893: if (earg == EXP_CANT_INTERPRET) 4894: return NULL; 4895: if (earg->op == TOKnull) 4896: return new NullExp(earg->loc); 4897: if (earg->op != TOKassocarrayliteral && earg->type->toBasetype()->ty != Taarray) 4898: return NULL; 4899: AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; 4900: Expression *e = new ArrayLiteralExp(aae->loc, aae->values); 4901: Type *elemType = ((TypeAArray *)aae->type)->next; 4902: e->type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments->dim : 0)); 4903: //printf("result is %s\n", e->toChars()); 4904: return copyLiteral(e); 4905: } 4906: 4907: #endif 4908: 4909: #if DMDV2 4910: 4911: Expression *interpret_length(InterState *istate, Expression *earg) 4912: { 4913: //printf("interpret_length()\n"); 4914: earg = earg->interpret(istate); 4915: if (earg == EXP_CANT_INTERPRET) 4916: return NULL; 4917: if (earg->op != TOKassocarrayliteral) 4918: return NULL; 4919: AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; 4920: Expression *e = new IntegerExp(aae->loc, aae->keys->dim, Type::tsize_t); 4921: return e; 4922: } 4923: 4924: Expression *interpret_keys(InterState *istate, Expression *earg, FuncDeclaration *fd) 4925: { 4926: #if LOG 4927: printf("interpret_keys()\n"); 4928: #endif 4929: earg = earg->interpret(istate); 4930: if (earg == EXP_CANT_INTERPRET) 4931: return NULL; 4932: if (earg->op == TOKnull) 4933: return new NullExp(earg->loc); 4934: if (earg->op != TOKassocarrayliteral && earg->type->toBasetype()->ty != Taarray) 4935: return NULL; 4936: assert(earg->op == TOKassocarrayliteral); 4937: AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; 4938: Expression *e = new ArrayLiteralExp(aae->loc, aae->keys); 4939: assert(fd->type->ty == Tfunction); 4940: assert(fd->type->nextOf()->ty == Tarray); 4941: Type *elemType = ((TypeFunction *)fd->type)->nextOf()->nextOf(); 4942: e->type = new TypeSArray(elemType, new IntegerExp(aae->keys->dim)); 4943: return copyLiteral(e); 4944: } 4945: 4946: Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclaration *fd) 4947: { 4948: #if LOG 4949: printf("interpret_values()\n"); 4950: #endif 4951: earg = earg->interpret(istate); 4952: if (earg == EXP_CANT_INTERPRET) 4953: return NULL; 4954: if (earg->op == TOKnull) 4955: return new NullExp(earg->loc); 4956: if (earg->op != TOKassocarrayliteral && earg->type->toBasetype()->ty != Taarray) 4957: return NULL; 4958: assert(earg->op == TOKassocarrayliteral); 4959: AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; 4960: Expression *e = new ArrayLiteralExp(aae->loc, aae->values); 4961: assert(fd->type->ty == Tfunction); 4962: assert(fd->type->nextOf()->ty == Tarray); 4963: Type *elemType = ((TypeFunction *)fd->type)->nextOf()->nextOf(); 4964: e->type = new TypeSArray(elemType, new IntegerExp(aae->values->dim)); 4965: //printf("result is %s\n", e->toChars()); 4966: return copyLiteral(e); 4967: } 4968: 4969: #endif 4970: 4971: #if DMDV2 4972: // Return true if t is an AA, or AssociativeArray!(key, value) 4973: bool isAssocArray(Type *t) 4974: { 4975: t = t->toBasetype(); 4976: if (t->ty == Taarray) 4977: return true; 4978: if (t->ty != Tstruct) 4979: return false; 4980: StructDeclaration *sym = ((TypeStruct *)t)->sym; 4981: if (sym->ident == Id::AssociativeArray) 4982: return true; 4983: return false; 4984: } 4985: #endif 4986: 4987: /* Decoding UTF strings for foreach loops. Duplicates the functionality of 4988: * the twelve _aApplyXXn functions in aApply.d in the runtime. 4989: */ 4990: Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *deleg, bool rvs) 4991: { 4992: #if LOG 4993: printf("foreachApplyUtf(%s, %s)\n", str->toChars(), deleg->toChars()); 4994: #endif 4995: FuncDeclaration *fd; 4996: Expression *pthis = NULL; 4997: if (deleg->op == TOKdelegate) 4998: { 4999: fd = ((DelegateExp *)deleg)->func; 5000: pthis = ((DelegateExp *)deleg)->e1; 5001: } 5002: else if (deleg->op == TOKfunction) 5003: fd = ((FuncExp*)deleg)->fd; 5004: 5005: assert(fd && fd->fbody);
warning C6001: Using uninitialized memory 'fd': Lines: 4995, 4996, 4997, 5002, 5005
5006: assert(fd->parameters); 5007: int numParams = fd->parameters->dim; 5008: assert(numParams == 1 || numParams==2); 5009: Type *charType = fd->parameters->tdata()[numParams-1]->type; 5010: Type *indexType = numParams == 2 ? fd->parameters->tdata()[0]->type 5011: : Type::tsize_t; 5012: uinteger_t len = resolveArrayLength(str); 5013: if (len == 0) 5014: return new IntegerExp(deleg->loc, 0, indexType); 5015: 5016: if (str->op == TOKslice) 5017: str = resolveSlice(str); 5018: 5019: StringExp *se = NULL; 5020: ArrayLiteralExp *ale = NULL; 5021: if (str->op == TOKstring) 5022: se = (StringExp *) str; 5023: else if (str->op == TOKarrayliteral) 5024: ale = (ArrayLiteralExp *)str; 5025: else 5026: { error("CTFE internal error: cannot foreach %s", str->toChars()); 5027: return EXP_CANT_INTERPRET; 5028: } 5029: Expressions args; 5030: args.setDim(numParams); 5031: 5032: Expression *eresult; 5033: 5034: // Buffers for encoding; also used for decoding array literals 5035: unsigned char utf8buf[4]; 5036: unsigned short utf16buf[2]; 5037: 5038: size_t start = rvs ? len : 0;
warning C4244: 'initializing' : conversion from 'uinteger_t' to 'size_t', possible loss of data
5039: size_t end = rvs ? 0: len;
warning C4244: 'initializing' : conversion from 'uinteger_t' to 'size_t', possible loss of data
5040: for (size_t indx = start; indx != end;) 5041: { 5042: // Step 1: Decode the next dchar from the string. 5043: 5044: const char *errmsg = NULL; // Used for reporting decoding errors 5045: dchar_t rawvalue; // Holds the decoded dchar 5046: 5047: if (ale) 5048: { // If it is an array literal, copy the code points into the buffer 5049: int buflen = 1; // #code points in the buffer 5050: size_t n = 1; // #code points in this char 5051: int sz = ale->type->nextOf()->size();
warning C4244: 'initializing' : conversion from 'd_uns64' to 'int', possible loss of data
5052: 5053: switch(sz) 5054: { 5055: case 1: 5056: if (rvs) 5057: { // find the start of the string 5058: --indx; 5059: buflen = 1; 5060: while (indx > 0 && buflen < 4) 5061: { Expression * r = ale->elements->tdata()[indx]; 5062: assert(r->op == TOKint64); 5063: unsigned char x = ((IntegerExp *)r)->value;
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'unsigned char', possible loss of data
5064: if ( (x & 0xC0) != 0x80) 5065: break; 5066: ++buflen; 5067: } 5068: } 5069: else 5070: buflen = (indx + 4 > len) ? len - indx : 4;
warning C4244: '=' : conversion from 'uinteger_t' to 'int', possible loss of data
5071: for (int i=0; i < buflen; ++i) 5072: { 5073: Expression * r = ale->elements->tdata()[indx + i]; 5074: assert(r->op == TOKint64); 5075: utf8buf[i] = ((IntegerExp *)r)->value;
warning C4244: '=' : conversion from 'dinteger_t' to 'unsigned char', possible loss of data
5076: } 5077: n = 0; 5078: errmsg = utf_decodeChar(&utf8buf[0], buflen, &n, &rawvalue); 5079: break; 5080: case 2: 5081: if (rvs) 5082: { // find the start of the string 5083: --indx; 5084: buflen = 1; 5085: Expression * r = ale->elements->tdata()[indx]; 5086: assert(r->op == TOKint64); 5087: unsigned short x = ((IntegerExp *)r)->value;
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'unsigned short', possible loss of data
5088: if (indx > 0 && x >= 0xDC00 && x <= 0xDFFF) 5089: { 5090: --indx; 5091: ++buflen; 5092: } 5093: } 5094: else 5095: buflen = (indx + 2 > len) ? len - indx : 2;
warning C4244: '=' : conversion from 'uinteger_t' to 'int', possible loss of data
5096: for (int i=0; i < buflen; ++i) 5097: { 5098: Expression * r = ale->elements->tdata()[indx + i]; 5099: assert(r->op == TOKint64); 5100: utf16buf[i] = ((IntegerExp *)r)->value;
warning C4244: '=' : conversion from 'dinteger_t' to 'unsigned short', possible loss of data
5101: } 5102: n = 0; 5103: errmsg = utf_decodeWchar(&utf16buf[0], buflen, &n, &rawvalue); 5104: break; 5105: case 4: 5106: { 5107: if (rvs) 5108: --indx; 5109: 5110: Expression * r = ale->elements->tdata()[indx]; 5111: assert(r->op == TOKint64); 5112: rawvalue = ((IntegerExp *)r)->value;
warning C4244: '=' : conversion from 'dinteger_t' to 'dchar_t', possible loss of data
5113: n = 1; 5114: } 5115: break; 5116: default: 5117: assert(0); 5118: } 5119: if (!rvs) 5120: indx += n; 5121: } 5122: else 5123: { // String literals 5124: size_t saveindx; // used for reverse iteration 5125: 5126: switch (se->sz) 5127: { 5128: case 1: 5129: if (rvs) 5130: { // find the start of the string 5131: unsigned char *s = (unsigned char *)se->string; 5132: --indx; 5133: while (indx > 0 && ((s[indx]&0xC0)==0x80)) 5134: --indx; 5135: saveindx = indx; 5136: } 5137: errmsg = utf_decodeChar((unsigned char *)se->string, se->len, &indx, &rawvalue); 5138: if (rvs) 5139: indx = saveindx; 5140: break; 5141: case 2: 5142: if (rvs) 5143: { // find the start 5144: unsigned short *s = (unsigned short *)se->string; 5145: --indx; 5146: if (s[indx] >= 0xDC00 && s[indx]<= 0xDFFF) 5147: --indx; 5148: saveindx = indx; 5149: } 5150: errmsg = utf_decodeWchar((unsigned short *)se->string, se->len, &indx, &rawvalue); 5151: if (rvs) 5152: indx = saveindx; 5153: break; 5154: case 4: 5155: if (rvs) 5156: --indx; 5157: rawvalue = ((unsigned *)(se->string))[indx]; 5158: if (!rvs) 5159: ++indx; 5160: break; 5161: default: 5162: assert(0); 5163: } 5164: } 5165: if (errmsg) 5166: { deleg->error("%s", errmsg); 5167: return EXP_CANT_INTERPRET; 5168: } 5169: 5170: // Step 2: encode the dchar in the target encoding 5171: 5172: int charlen = 1; // How many codepoints are involved? 5173: switch(charType->size()) 5174: { 5175: case 1: 5176: charlen = utf_codeLengthChar(rawvalue); 5177: utf_encodeChar(&utf8buf[0], rawvalue); 5178: break; 5179: case 2: 5180: charlen = utf_codeLengthWchar(rawvalue); 5181: utf_encodeWchar(&utf16buf[0], rawvalue); 5182: break; 5183: case 4: 5184: break; 5185: default: 5186: assert(0); 5187: } 5188: 5189: 5190: // Step 3: call the delegate once for each code point 5191: 5192: // The index only needs to be set once 5193: if (numParams == 2) 5194: args.tdata()[0] = new IntegerExp(deleg->loc, indx, indexType); 5195: 5196: Expression *val = NULL; 5197: 5198: for (int k= 0; k < charlen; ++k) 5199: { 5200: dchar_t codepoint; 5201: switch(charType->size()) 5202: { 5203: case 1: 5204: codepoint = utf8buf[k]; 5205: break; 5206: case 2: 5207: codepoint = utf16buf[k]; 5208: break; 5209: case 4: 5210: codepoint = rawvalue; 5211: break; 5212: default: 5213: assert(0); 5214: } 5215: val = new IntegerExp(str->loc, codepoint, charType); 5216: 5217: args.tdata()[numParams - 1] = val; 5218: 5219: eresult = fd->interpret(istate, &args, pthis); 5220: if (eresult == EXP_CANT_INTERPRET) 5221: return EXP_CANT_INTERPRET; 5222: 5223: assert(eresult->op == TOKint64); 5224: if (((IntegerExp *)eresult)->value != 0) 5225: return eresult; 5226: } 5227: } 5228: return eresult; 5229: } 5230: 5231: /* If this is a built-in function, set 'result' to the interpreted result, 5232: * and return true. 5233: * Otherwise, return false 5234: */ 5235: bool evaluateIfBuiltin(Expression **result, InterState *istate, 5236: FuncDeclaration *fd, Expressions *arguments, Expression *pthis) 5237: { 5238: Expression *e = NULL; 5239: int nargs = arguments ? arguments->dim : 0; 5240: #if DMDV2 5241: if (pthis && isAssocArray(pthis->type) && nargs==0) 5242: { 5243: if (fd->ident == Id::length) 5244: e = interpret_length(istate, pthis); 5245: else if (fd->ident == Id::keys) 5246: e = interpret_keys(istate, pthis, fd); 5247: else if (fd->ident == Id::values) 5248: e = interpret_values(istate, pthis, fd); 5249: else if (fd->ident == Id::rehash) 5250: e = pthis; // rehash is a no-op 5251: } 5252: if (!pthis) 5253: { 5254: enum BUILTIN b = fd->isBuiltin(); 5255: if (b) 5256: { Expressions args; 5257: args.setDim(arguments->dim);
warning C6011: Dereferencing NULL pointer 'arguments': Lines: 5238, 5239, 5241, 5252, 5254, 5255, 5256, 5257
5258: for (size_t i = 0; i < args.dim; i++) 5259: { 5260: Expression *earg = arguments->tdata()[i]; 5261: earg = earg->interpret(istate); 5262: if (earg == EXP_CANT_INTERPRET) 5263: return earg;
warning C4800: 'Expression *' : forcing value to bool 'true' or 'false' (performance warning)
5264: args.tdata()[i] = earg; 5265: } 5266: e = eval_builtin(b, &args); 5267: if (!e) 5268: e = EXP_CANT_INTERPRET; 5269: } 5270: } 5271: #endif 5272: #if DMDV1 5273: if (!pthis) 5274: { 5275: if (fd->ident == Id::aaLen) 5276: e = interpret_aaLen(istate, arguments); 5277: else if (fd->ident == Id::aaKeys) 5278: e = interpret_aaKeys(istate, arguments); 5279: else if (fd->ident == Id::aaValues) 5280: e = interpret_aaValues(istate, arguments); 5281: else if (fd->ident == Id::aaRehash && nargs == 2) 5282: { // rehash is a no-op 5283: Expression *earg = (Expression *)(arguments->data[0]); 5284: return earg->interpret(istate, ctfeNeedLvalue); 5285: } 5286: } 5287: #endif 5288: if (!pthis) 5289: { 5290: size_t idlen = strlen(fd->ident->string); 5291: if (nargs == 2 && (idlen == 10 || idlen == 11) 5292: && !strncmp(fd->ident->string, "_aApply", 7)) 5293: { // Functions from aApply.d and aApplyR.d in the runtime 5294: bool rvs = (idlen == 11); // true if foreach_reverse 5295: char c = fd->ident->string[idlen-3]; // char width: 'c', 'w', or 'd' 5296: char s = fd->ident->string[idlen-2]; // string width: 'c', 'w', or 'd' 5297: char n = fd->ident->string[idlen-1]; // numParams: 1 or 2. 5298: // There are 12 combinations 5299: if ( (n == '1' || n == '2') && 5300: (c == 'c' || c == 'w' || c == 'd') && 5301: (s == 'c' || s == 'w' || s == 'd') && c != s) 5302: { Expression *str = arguments->tdata()[0]; 5303: str = str->interpret(istate); 5304: if (str == EXP_CANT_INTERPRET) 5305: { 5306: *result = EXP_CANT_INTERPRET; 5307: return true; 5308: } 5309: *result = foreachApplyUtf(istate, str, arguments->tdata()[1], rvs); 5310: return true; 5311: } 5312: } 5313: } 5314: if (!e) 5315: return false; 5316: *result = e; 5317: return true; 5318: } 5319: 5320: /*************************** CTFE Sanity Checks ***************************/ 5321: 5322: /* Setter functions for CTFE variable values. 5323: * These functions exist to check for compiler CTFE bugs. 5324: */ 5325: 5326: bool isStackValueValid(Expression *newval) 5327: { 5328: if (newval->type->ty == Tpointer && newval->type->nextOf()->ty != Tfunction) 5329: { 5330: if (newval->op == TOKaddress || newval->op == TOKnull || 5331: newval->op == TOKstring) 5332: return true; 5333: if (newval->op == TOKindex) 5334: { 5335: Expression *g = ((IndexExp *)newval)->e1; 5336: if (g->op == TOKarrayliteral || g->op == TOKstring || 5337: g->op == TOKassocarrayliteral) 5338: return true; 5339: } 5340: if (newval->op == TOKvar) 5341: return true; 5342: if (newval->type->nextOf()->ty == Tarray && newval->op == TOKslice) 5343: return true; 5344: newval->error("CTFE internal error: illegal pointer value %s\n", newval->toChars()); 5345: return false; 5346: } 5347: if ((newval->op ==TOKarrayliteral) || ( newval->op==TOKstructliteral) || 5348: (newval->op==TOKstring) || (newval->op == TOKassocarrayliteral) || 5349: (newval->op == TOKnull) || (newval->op == TOKslice)) 5350: { return false; 5351: } 5352: if (newval->op == TOKvar) 5353: { 5354: VarExp *ve = (VarExp *)newval; 5355: VarDeclaration *vv = ve->var->isVarDeclaration(); 5356: // Must not be a reference to a reference 5357: if (!(vv && vv->getValue() && vv->getValue()->op == TOKvar)) 5358: return true; 5359: } 5360: if (newval->op == TOKdotvar) 5361: { 5362: if (((DotVarExp *)newval)->e1->op == TOKstructliteral) 5363: return true; 5364: } 5365: if (newval->op == TOKindex) 5366: { 5367: IndexExp *ie = (IndexExp *)newval; 5368: if (ie->e2->op == TOKint64) 5369: { 5370: if (ie->e1->op == TOKarrayliteral || ie->e1->op == TOKstring) 5371: return true; 5372: } 5373: if (ie->e1->op == TOKassocarrayliteral) 5374: return true; 5375: // BUG: Happens ONLY in ref foreach. Should tighten this. 5376: if (ie->e2->op == TOKvar) 5377: return true; 5378: } 5379: if (newval->op == TOKfunction) return true; // function/delegate literal 5380: if (newval->op == TOKdelegate) return true; 5381: if (newval->op == TOKsymoff) // function pointer 5382: { 5383: if (((SymOffExp *)newval)->var->isFuncDeclaration()) 5384: return true; 5385: } 5386: if (newval->op == TOKint64 || newval->op == TOKfloat64 || 5387: newval->op == TOKchar || newval->op == TOKcomplex80) 5388: return true; 5389: newval->error("CTFE internal error: illegal stack value %s\n", newval->toChars()); 5390: return false; 5391: } 5392: 5393: bool isRefValueValid(Expression *newval) 5394: { 5395: assert(newval); 5396: if ((newval->op ==TOKarrayliteral) || ( newval->op==TOKstructliteral) || 5397: (newval->op==TOKstring) || (newval->op == TOKassocarrayliteral) || 5398: (newval->op == TOKnull)) 5399: { return true; 5400: } 5401: // Dynamic arrays passed by ref may be null. When this happens 5402: // they may originate from an index or dotvar expression. 5403: if (newval->type->ty == Tarray || newval->type->ty == Taarray 5404: || newval->type->ty == Tclass) 5405: if (newval->op == TOKdotvar || newval->op == TOKindex) 5406: return isStackValueValid(newval); // actually must be null 5407: if (newval->op == TOKslice) 5408: { 5409: SliceExp *se = (SliceExp *)newval; 5410: assert(se->lwr && se->lwr != EXP_CANT_INTERPRET && se->lwr->op == TOKint64); 5411: assert(se->upr && se->upr != EXP_CANT_INTERPRET && se->upr->op == TOKint64); 5412: assert(se->e1->op == TOKarrayliteral || se->e1->op == TOKstring); 5413: return true; 5414: } 5415: newval->error("CTFE internal error: illegal reference value %s\n", newval->toChars()); 5416: return false; 5417: } 5418: 5419: void VarDeclaration::setValueNull() 5420: { 5421: literalvalue = NULL; 5422: } 5423: 5424: // Don't check for validity 5425: void VarDeclaration::setValueWithoutChecking(Expression *newval) 5426: { 5427: assert(!newval || isStackValueValid(newval) || isRefValueValid(newval)); 5428: literalvalue = newval; 5429: } 5430: void VarDeclaration::createRefValue(Expression *newval) 5431: { 5432: assert(!literalvalue); 5433: assert(isRefValueValid(newval)); 5434: literalvalue = newval; 5435: } 5436: 5437: void VarDeclaration::setRefValue(Expression *newval) 5438: { 5439: assert(literalvalue); 5440: assert(isRefValueValid(newval)); 5441: literalvalue = newval; 5442: } 5443: 5444: void VarDeclaration::setStackValue(Expression *newval) 5445: { 5446: assert(literalvalue); 5447: assert(isStackValueValid(newval)); 5448: literalvalue = newval; 5449: } 5450: void VarDeclaration::createStackValue(Expression *newval) 5451: { 5452: assert(!literalvalue); 5453: assert(isStackValueValid(newval)); 5454: literalvalue = newval; 5455: } 5456: