Changeset 314
- Timestamp:
- 12/29/09 00:15:03 (15 years ago)
- Files:
-
- branches/dmd-1.x/src/constfold.c (modified) (2 diffs)
- branches/dmd-1.x/src/declaration.c (modified) (3 diffs)
- branches/dmd-1.x/src/declaration.h (modified) (2 diffs)
- branches/dmd-1.x/src/expression.c (modified) (1 diff)
- branches/dmd-1.x/src/interpret.c (modified) (9 diffs)
- trunk/src/constfold.c (modified) (1 diff)
- trunk/src/declaration.c (modified) (1 diff)
- trunk/src/declaration.h (modified) (2 diffs)
- trunk/src/expression.c (modified) (1 diff)
- trunk/src/interpret.c (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/dmd-1.x/src/constfold.c
r199 r314 838 838 } 839 839 #endif 840 840 } 841 841 else if (e1->type->iscomplex()) 842 842 { 843 843 cmp = e1->toComplex() == e2->toComplex(); 844 844 } 845 845 else if (e1->type->isintegral() || e1->type->toBasetype()->ty == Tpointer) 846 846 { 847 847 cmp = (e1->toInteger() == e2->toInteger()); 848 848 } 849 849 else 850 850 return EXP_CANT_INTERPRET; 851 851 if (op == TOKnotequal) 852 852 cmp ^= 1; 853 853 e = new IntegerExp(loc, cmp, type); 854 854 return e; 855 855 } 856 856 857 857 Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2) 858 { Expression *e;858 { 859 859 Loc loc = e1->loc; 860 860 int cmp; 861 861 862 862 if (e1->op == TOKnull) 863 863 { 864 864 cmp = (e2->op == TOKnull); 865 865 } 866 866 else if (e2->op == TOKnull) 867 867 { 868 868 cmp = 0; 869 869 } 870 870 else if (e1->op == TOKsymoff && e2->op == TOKsymoff) 871 871 { 872 872 SymOffExp *es1 = (SymOffExp *)e1; 873 873 SymOffExp *es2 = (SymOffExp *)e2; 874 874 875 875 cmp = (es1->var == es2->var && es1->offset == es2->offset); 876 876 } 877 877 else if (e1->isConst() == 1 && e2->isConst() == 1) 878 878 return Equal((op == TOKidentity) ? TOKequal : TOKnotequal, … … 1042 1042 Loc loc = e1->loc; 1043 1043 1044 1044 //printf("Cast(type = %s, to = %s, e1 = %s)\n", type->toChars(), to->toChars(), e1->toChars()); 1045 1045 //printf("e1->type = %s\n", e1->type->toChars()); 1046 1046 if (type->equals(e1->type) && to->equals(type)) 1047 1047 return e1; 1048 1048 1049 1049 Type *tb = to->toBasetype(); 1050 1050 1051 1051 /* Allow casting from one string type to another 1052 1052 */ 1053 1053 if (e1->op == TOKstring) 1054 1054 { 1055 1055 Type *typeb = type->toBasetype(); 1056 1056 if (tb->ty == Tarray && typeb->ty == Tarray && 1057 1057 tb->nextOf()->size() == typeb->nextOf()->size()) 1058 1058 { 1059 1059 return expType(to, e1); 1060 1060 } 1061 1061 } 1062 1063 if (e1->op == TOKarrayliteral && e1->type->toBasetype() == tb) 1064 return e1; 1062 1065 1063 1066 if (e1->isConst() != 1) 1064 1067 return EXP_CANT_INTERPRET; 1065 1068 1066 1069 if (tb->ty == Tbool) 1067 1070 e = new IntegerExp(loc, e1->toInteger() != 0, type); 1068 1071 else if (type->isintegral()) 1069 1072 { 1070 1073 if (e1->type->isfloating()) 1071 1074 { dinteger_t result; 1072 1075 real_t r = e1->toReal(); 1073 1076 1074 1077 switch (type->toBasetype()->ty) 1075 1078 { 1076 1079 case Tint8: result = (d_int8)r; break; 1077 1080 case Tchar: 1078 1081 case Tuns8: result = (d_uns8)r; break; 1079 1082 case Tint16: result = (d_int16)r; break; 1080 1083 case Twchar: 1081 1084 case Tuns16: result = (d_uns16)r; break; branches/dmd-1.x/src/declaration.c
r304 r314 290 290 st->htype = htype->syntaxCopy(); 291 291 if (!hbasetype) 292 292 { if (basetype) 293 293 { hbasetype = basetype->syntaxCopy(); 294 294 st->hbasetype = basetype->syntaxCopy(); 295 295 } 296 296 } 297 297 else 298 298 st->hbasetype = hbasetype->syntaxCopy(); 299 299 #endif 300 300 return st; 301 301 } 302 302 303 303 void TypedefDeclaration::semantic(Scope *sc) 304 304 { 305 305 //printf("TypedefDeclaration::semantic(%s) sem = %d\n", toChars(), sem); 306 306 if (sem == 0) 307 307 { sem = 1; 308 308 basetype = basetype->semantic(loc, sc); 309 309 sem = 2; 310 #if DMDV2 311 type = type->addStorageClass(storage_class); 312 #endif 310 313 type = type->semantic(loc, sc); 311 314 if (sc->parent->isFuncDeclaration() && init) 312 315 semantic2(sc); 313 316 storage_class |= sc->stc & STCdeprecated; 314 317 } 315 318 else if (sem == 1) 316 319 { 317 320 error("circular definition"); 318 321 } 319 322 } 320 323 321 324 void TypedefDeclaration::semantic2(Scope *sc) 322 325 { 323 326 //printf("TypedefDeclaration::semantic2(%s) sem = %d\n", toChars(), sem); 324 327 if (sem == 2) 325 328 { sem = 3; 326 329 if (init) 327 330 { 328 331 init = init->semantic(sc, basetype); 329 332 … … 421 424 sa->haliassym = aliassym->syntaxCopy(s); 422 425 } 423 426 } 424 427 else 425 428 sa->haliassym = haliassym->syntaxCopy(s); 426 429 #endif 427 430 return sa; 428 431 } 429 432 430 433 void AliasDeclaration::semantic(Scope *sc) 431 434 { 432 435 //printf("AliasDeclaration::semantic() %s\n", toChars()); 433 436 if (aliassym) 434 437 { 435 438 if (aliassym->isTemplateInstance()) 436 439 aliassym->semantic(sc); 437 440 return; 438 441 } 439 442 this->inSemantic = 1; 440 443 444 #if DMDV1 // don't really know why this is here 441 445 if (storage_class & STCconst) 442 446 error("cannot be const"); 447 #endif 443 448 444 449 storage_class |= sc->stc & STCdeprecated; 445 450 446 451 // Given: 447 452 // alias foo.bar.abc def; 448 453 // it is not knowable from the syntax whether this is an alias 449 454 // for a type or an alias for a symbol. It is up to the semantic() 450 455 // pass to distinguish. 451 456 // If it is a type, then type is set and getType() will return that 452 457 // type. If it is a symbol, then aliassym is set and type is NULL - 453 458 // toAlias() will return aliasssym. 454 459 455 460 Dsymbol *s; 456 461 Type *t; 457 462 Expression *e; 458 463 459 464 /* This section is needed because resolve() will: 460 465 * const x = 3; 461 466 * alias x y; 462 467 * try to alias y to 3. 463 468 */ 464 469 s = type->toDsymbol(sc); 465 470 if (s 466 471 #if DMDV2 467 472 ` && ((s->getType() && type->equals(s->getType())) || s->isEnumMember()) 468 473 #endif 469 474 ) 470 475 goto L2; // it's a symbolic alias 471 476 472 477 #if DMDV2 478 type = type->addStorageClass(storage_class); 473 479 if (storage_class & (STCref | STCnothrow | STCpure)) 474 480 { // For 'ref' to be attached to function types, and picked 475 481 // up by Type::resolve(), it has to go into sc. 476 482 sc = sc->push(); 477 sc->stc |= storage_class & (STCref | STCnothrow | STCpure );483 sc->stc |= storage_class & (STCref | STCnothrow | STCpure | STCshared); 478 484 type->resolve(loc, sc, &e, &t, &s); 479 485 sc = sc->pop(); 480 486 } 481 487 else 482 488 #endif 483 489 type->resolve(loc, sc, &e, &t, &s); 484 490 if (s) 485 491 { 486 492 goto L2; 487 493 } 488 494 else if (e) 489 495 { 490 496 // Try to convert Expression to Dsymbol 491 497 if (e->op == TOKvar) 492 498 { s = ((VarExp *)e)->var; 493 499 goto L2; 494 500 } 495 501 else if (e->op == TOKfunction) 496 502 { s = ((FuncExp *)e)->fd; 497 503 goto L2; … … 1311 1317 Dsymbol *parent = this->toParent(); 1312 1318 if (!parent && !(storage_class & (STCstatic | STCconst))) 1313 1319 { error("forward referenced"); 1314 1320 type = Type::terror; 1315 1321 return 0; 1316 1322 } 1317 1323 return (storage_class & (STCstatic | STCconst) || 1318 1324 parent->isModule() || 1319 1325 parent->isTemplateInstance()); 1320 1326 } 1321 1327 1322 1328 /************************************ 1323 1329 * Does symbol go into thread local storage? 1324 1330 */ 1325 1331 1326 1332 int VarDeclaration::isThreadlocal() 1327 1333 { 1328 1334 return 0; 1329 1335 } 1330 1336 1337 /******************************************** 1338 * Can variable be read and written by CTFE? 1339 */ 1340 1341 int VarDeclaration::isCTFE() 1342 { 1343 return (storage_class & STCctfe) || !isDataseg(); 1344 } 1345 1331 1346 int VarDeclaration::hasPointers() 1332 1347 { 1333 1348 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type->ty); 1334 1349 return (!isDataseg() && type->hasPointers()); 1335 1350 } 1336 1351 1337 1352 /****************************************** 1338 1353 * If a variable has an auto destructor call, return call for it. 1339 1354 * Otherwise, return NULL. 1340 1355 */ 1341 1356 1342 1357 Expression *VarDeclaration::callAutoDtor(Scope *sc) 1343 1358 { Expression *e = NULL; 1344 1359 1345 1360 //printf("VarDeclaration::callAutoDtor() %s\n", toChars()); 1346 1361 if (storage_class & (STCauto | STCscope) && !noauto) 1347 1362 { 1348 1363 for (ClassDeclaration *cd = type->isClassHandle(); 1349 1364 cd; 1350 1365 cd = cd->baseClass) branches/dmd-1.x/src/declaration.h
r304 r314 56 56 STCout = 0x1000, // out parameter 57 57 STClazy = 0x2000, // lazy parameter 58 58 STCforeach = 0x4000, // variable for foreach loop 59 59 STCcomdat = 0x8000, // should go into COMDAT record 60 60 STCvariadic = 0x10000, // variadic function argument 61 61 STCctorinit = 0x20000, // can only be set inside constructor 62 62 STCtemplateparameter = 0x40000, // template parameter 63 63 STCscope = 0x80000, // template parameter 64 64 STCimmutable = 0x100000, 65 65 STCref = 0x200000, 66 66 STCinit = 0x400000, // has explicit initializer 67 67 STCmanifest = 0x800000, // manifest constant 68 68 STCnodtor = 0x1000000, // don't run destructor 69 69 STCnothrow = 0x2000000, // never throws exceptions 70 70 STCpure = 0x4000000, // pure function 71 71 STCtls = 0x8000000, // thread local 72 72 STCalias = 0x10000000, // alias parameter 73 73 STCshared = 0x20000000, // accessible from multiple threads 74 74 STCgshared = 0x40000000, // accessible from multiple threads 75 75 // but not typed as "shared" 76 STC_TYPECTOR = (STCconst | STCimmutable | STCshared), 77 }; 76 STCwild = 0x80000000, // for "wild" type constructor 77 STC_TYPECTOR = (STCconst | STCimmutable | STCshared | STCwild), 78 }; 79 80 #define STCproperty 0x100000000LL 81 #define STCsafe 0x200000000LL 82 #define STCtrusted 0x400000000LL 83 #define STCsystem 0x800000000LL 84 #define STCctfe 0x1000000000LL // can be used in CTFE, even if it is static 78 85 79 86 struct Match 80 87 { 81 88 int count; // number of matches found 82 89 MATCH last; // match level of lastf 83 90 FuncDeclaration *lastf; // last matching function we found 84 91 FuncDeclaration *nextf; // current matching function 85 92 FuncDeclaration *anyf; // pick a func, any func, to use for error recovery 86 93 }; 87 94 88 95 void overloadResolveX(Match *m, FuncDeclaration *f, 89 96 Expression *ethis, Expressions *arguments); 90 97 int overloadApply(FuncDeclaration *fstart, 91 98 int (*fp)(void *, FuncDeclaration *), 92 99 void *param); 93 100 94 101 /**************************************************************/ 95 102 96 103 struct Declaration : Dsymbol 97 104 { … … 245 252 #if DMDV2 246 253 VarDeclaration *rundtor; // if !NULL, rundtor is tested at runtime to see 247 254 // if the destructor should be run. Used to prevent 248 255 // dtor calls on postblitted vars 249 256 #endif 250 257 251 258 VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init); 252 259 Dsymbol *syntaxCopy(Dsymbol *); 253 260 void semantic(Scope *sc); 254 261 void semantic2(Scope *sc); 255 262 const char *kind(); 256 263 void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 257 264 #ifdef _DH 258 265 Type *htype; 259 266 Initializer *hinit; 260 267 #endif 261 268 int needThis(); 262 269 int isImportedSymbol(); 263 270 int isDataseg(); 264 271 int isThreadlocal(); 272 int isCTFE(); 265 273 int hasPointers(); 266 274 #if DMDV2 267 275 int canTakeAddressOf(); 268 276 int needsAutoDtor(); 269 277 #endif 270 278 Expression *callAutoDtor(Scope *sc); 271 279 ExpInitializer *getExpInitializer(); 272 280 Expression *getConstInitializer(); 273 281 void checkCtorConstInit(); 274 282 void checkNestedReference(Scope *sc, Loc loc); 275 283 Dsymbol *toAlias(); 276 284 277 285 Symbol *toSymbol(); 278 286 void toObjFile(int multiobj); // compile to .obj file 279 287 int cvMember(unsigned char *p); 280 288 281 289 // Eliminate need for dynamic_cast 282 290 VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; } 283 291 }; 284 292 branches/dmd-1.x/src/expression.c
r304 r314 680 680 Type *tret = p->isLazyArray(); 681 681 switch (tb->ty) 682 682 { 683 683 case Tsarray: 684 684 case Tarray: 685 685 { // Create a static array variable v of type arg->type 686 686 #ifdef IN_GCC 687 687 /* GCC 4.0 does not like zero length arrays used like 688 688 this; pass a null array value instead. Could also 689 689 just make a one-element array. */ 690 690 if (nargs - i == 0) 691 691 { 692 692 arg = new NullExp(loc); 693 693 break; 694 694 } 695 695 #endif 696 696 Identifier *id = Lexer::uniqueId("__arrayArg"); 697 697 Type *t = new TypeSArray(((TypeArray *)tb)->next, new IntegerExp(nargs - i)); 698 698 t = t->semantic(loc, sc); 699 699 VarDeclaration *v = new VarDeclaration(loc, t, id, new VoidInitializer(loc)); 700 v->storage_class |= STCctfe; 700 701 v->semantic(sc); 701 702 v->parent = sc->parent; 702 703 //sc->insert(v); 703 704 704 705 Expression *c = new DeclarationExp(0, v); 705 706 c->type = v->type; 706 707 707 708 for (size_t u = i; u < nargs; u++) 708 709 { Expression *a = (Expression *)arguments->data[u]; 709 710 if (tret && !((TypeArray *)tb)->next->equals(a->type)) 710 711 a = a->toDelegate(sc, tret); 711 712 712 713 Expression *e = new VarExp(loc, v); 713 714 e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams)); 714 715 AssignExp *ae = new AssignExp(loc, e, a); 715 716 #if DMDV2 716 717 ae->op = TOKconstruct; 717 718 #endif 718 719 if (c) 719 720 c = new CommaExp(loc, c, ae); branches/dmd-1.x/src/interpret.c
r310 r314 31 31 { 32 32 InterState *caller; // calling function's InterState 33 33 FuncDeclaration *fd; // function being interpreted 34 34 Dsymbols vars; // variables used in this function 35 35 Statement *start; // if !=NULL, start execution at this statement 36 36 Statement *gotoTarget; // target of EXP_GOTO_INTERPRET result 37 37 Expression *localThis; // value of 'this', or NULL if none 38 38 39 39 InterState(); 40 40 }; 41 41 42 42 InterState::InterState() 43 43 { 44 44 memset(this, 0, sizeof(InterState)); 45 45 } 46 46 47 47 Expression *interpret_aaLen(InterState *istate, Expressions *arguments); 48 48 Expression *interpret_aaKeys(InterState *istate, Expressions *arguments); 49 49 Expression *interpret_aaValues(InterState *istate, Expressions *arguments); 50 50 51 Expression *interpret_length(InterState *istate, Expression *earg); 52 Expression *interpret_keys(InterState *istate, Expression *earg, FuncDeclaration *fd); 53 Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclaration *fd); 54 51 55 /************************************* 52 56 * Attempt to interpret a function given the arguments. 53 57 * Input: 54 58 * istate state for calling function (NULL if none) 55 59 * arguments function arguments 56 60 * thisarg 'this', if a needThis() function, NULL if not. 57 61 * 58 62 * Return result expression if successful, NULL if not. 59 63 */ 60 64 61 65 Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments, Expression *thisarg) 62 66 { 63 67 #if LOG 64 68 printf("\n********\nFuncDeclaration::interpret(istate = %p) %s\n", istate, toChars()); 65 69 printf("cantInterpret = %d, semanticRun = %d\n", cantInterpret, semanticRun); 66 70 #endif 67 71 if (global.errors) 68 72 return NULL; 73 74 #if DMDV1 69 75 if (ident == Id::aaLen) 70 76 return interpret_aaLen(istate, arguments); 71 77 else if (ident == Id::aaKeys) 72 78 return interpret_aaKeys(istate, arguments); 73 79 else if (ident == Id::aaValues) 74 80 return interpret_aaValues(istate, arguments); 81 #endif 82 #if DMDV2 83 if (thisarg && 84 (!arguments || arguments->dim == 0)) 85 { 86 if (ident == Id::length) 87 return interpret_length(istate, thisarg); 88 else if (ident == Id::keys) 89 return interpret_keys(istate, thisarg, this); 90 else if (ident == Id::values) 91 return interpret_values(istate, thisarg, this); 92 } 93 #endif 75 94 76 95 if (cantInterpret || semanticRun == 3) 77 96 return NULL; 78 97 79 98 if (!fbody) 80 99 { cantInterpret = 1; 81 100 return NULL; 82 101 } 83 102 84 103 if (semanticRun < 3 && scope) 85 104 { 86 105 semantic3(scope); 87 106 if (global.errors) // if errors compiling this function 88 107 return NULL; 89 108 } 90 109 if (semanticRun < 4) 91 110 return NULL; 92 111 93 112 Type *tb = type->toBasetype(); 94 113 assert(tb->ty == Tfunction); 95 114 TypeFunction *tf = (TypeFunction *)tb; 96 115 Type *tret = tf->next->toBasetype(); 97 if (tf->varargs )116 if (tf->varargs && arguments && parameters && arguments->dim != parameters->dim) 98 117 { cantInterpret = 1; 99 error(" Variadic functions are not yet implemented in CTFE");118 error("C-style variadic functions are not yet implemented in CTFE"); 100 119 return NULL; 101 120 } 102 121 103 122 // Ensure there are no lazy parameters 104 123 if (tf->parameters) 105 124 { size_t dim = Parameter::dim(tf->parameters); 106 125 for (size_t i = 0; i < dim; i++) 107 126 { Parameter *arg = Parameter::getNth(tf->parameters, i); 108 127 if (arg->storageClass & STClazy) 109 128 { cantInterpret = 1; 110 129 return NULL; 111 130 } 112 131 } 113 132 } 114 133 115 134 InterState istatex; 116 135 istatex.caller = istate; 117 136 istatex.fd = this; 118 137 istatex.localThis = thisarg; 119 138 … … 987 1006 } 988 1007 989 1008 Expression *getVarExp(Loc loc, InterState *istate, Declaration *d) 990 1009 { 991 1010 Expression *e = EXP_CANT_INTERPRET; 992 1011 VarDeclaration *v = d->isVarDeclaration(); 993 1012 SymbolDeclaration *s = d->isSymbolDeclaration(); 994 1013 if (v) 995 1014 { 996 1015 #if DMDV2 997 1016 if ((v->isConst() || v->isImmutable() || v->storage_class & STCmanifest) && v->init && !v->value) 998 1017 #else 999 1018 if (v->isConst() && v->init) 1000 1019 #endif 1001 1020 { e = v->init->toExpression(); 1002 1021 if (e && !e->type) 1003 1022 e->type = v->type; 1004 1023 } 1005 1024 else 1006 1025 { e = v->value; 1007 if ( v->isDataseg())1026 if (!v->isCTFE()) 1008 1027 { error(loc, "static variable %s cannot be read at compile time", v->toChars()); 1009 1028 e = EXP_CANT_INTERPRET; 1010 1029 } 1011 1030 else if (!e) 1012 1031 error(loc, "variable %s is used before initialization", v->toChars()); 1013 1032 else if (e != EXP_CANT_INTERPRET) 1014 1033 e = e->interpret(istate); 1015 1034 } 1016 1035 if (!e) 1017 1036 e = EXP_CANT_INTERPRET; 1018 1037 } 1019 1038 else if (s) 1020 1039 { 1021 1040 if (s->dsym->toInitializer() == s->sym) 1022 1041 { Expressions *exps = new Expressions(); 1023 1042 e = new StructLiteralExp(0, s->dsym, exps); 1024 1043 e = e->semantic(NULL); 1025 1044 } 1026 1045 } 1027 1046 return e; … … 1579 1598 } 1580 1599 1581 1600 // To reduce code complexity of handling dotvar expressions, 1582 1601 // extract the aggregate now. 1583 1602 Expression *aggregate; 1584 1603 if (e1->op == TOKdotvar) { 1585 1604 aggregate = ((DotVarExp *)e1)->e1; 1586 1605 // Get rid of 'this'. 1587 1606 if (aggregate->op == TOKthis && istate->localThis) 1588 1607 aggregate = istate->localThis; 1589 1608 } 1590 1609 1591 1610 /* Assignment to variable of the form: 1592 1611 * v = e2 1593 1612 */ 1594 1613 if (e1->op == TOKvar) 1595 1614 { 1596 1615 VarExp *ve = (VarExp *)e1; 1597 1616 VarDeclaration *v = ve->var->isVarDeclaration(); 1598 1617 assert(v); 1599 if (v && v->isDataseg())1618 if (v && !v->isCTFE()) 1600 1619 { // Can't modify global or static data 1601 1620 error("%s cannot be modified at compile time", v->toChars()); 1602 1621 return EXP_CANT_INTERPRET; 1603 1622 } 1604 if (v && !v->isDataseg())1623 if (v && v->isCTFE()) 1605 1624 { 1606 1625 Expression *ev = v->value; 1607 1626 if (fp && !ev) 1608 1627 { error("variable %s is used before initialization", v->toChars()); 1609 1628 return e; 1610 1629 } 1611 1630 if (fp) 1612 1631 e2 = (*fp)(v->type, ev, e2); 1613 1632 else 1614 1633 { /* Look for special case of struct being initialized with 0. 1615 1634 */ 1616 1635 if (v->type->toBasetype()->ty == Tstruct && e2->op == TOKint64) 1617 1636 { 1618 1637 e2 = v->type->defaultInit(); 1619 1638 } 1620 1639 e2 = Cast(v->type, v->type, e2); 1621 1640 } 1622 1641 if (e2 == EXP_CANT_INTERPRET) 1623 1642 return e2; 1624 1643 1625 1644 addVarToInterstate(istate, v); 1626 1645 v->value = e2; 1627 1646 e = Cast(type, type, post ? ev : e2); 1628 1647 } 1629 1648 } 1630 1649 else if (e1->op == TOKdotvar && aggregate->op == TOKdotvar) 1631 1650 { // eg v.u.var = e2, v[3].u.var = e2, etc. 1632 1651 error("Nested struct assignment %s is not yet supported in CTFE", toChars()); 1633 1652 } 1634 1653 /* Assignment to struct member of the form: 1635 1654 * v.var = e2 1636 1655 */ 1637 1656 else if (e1->op == TOKdotvar && aggregate->op == TOKvar) 1638 1657 { VarDeclaration *v = ((VarExp *)aggregate)->var->isVarDeclaration(); 1639 1658 1640 if ( v->isDataseg())1659 if (!v->isCTFE()) 1641 1660 { // Can't modify global or static data 1642 1661 error("%s cannot be modified at compile time", v->toChars()); 1643 1662 return EXP_CANT_INTERPRET; 1644 1663 } else { 1645 1664 // Chase down rebinding of out and ref 1646 1665 if (v->value && v->value->op == TOKvar) 1647 1666 { 1648 1667 VarExp *ve2 = (VarExp *)v->value; 1649 1668 if (ve2->var->isSymbolDeclaration()) 1650 1669 { // This can happen if v is a struct initialized to 1651 1670 // 0 using an __initZ SymbolDeclaration from 1652 1671 // TypeStruct::defaultInit() 1653 1672 } 1654 1673 else 1655 1674 v = ve2->var->isVarDeclaration(); 1656 1675 assert(v); 1657 1676 } 1658 1677 } 1659 1678 if (fp && !v->value) 1660 1679 { error("variable %s is used before initialization", v->toChars()); … … 1692 1711 if (e2 == EXP_CANT_INTERPRET) 1693 1712 return e2; 1694 1713 1695 1714 addVarToInterstate(istate, v); 1696 1715 1697 1716 /* Create new struct literal reflecting updated fieldi 1698 1717 */ 1699 1718 Expressions *expsx = changeOneElement(se->elements, fieldi, e2); 1700 1719 v->value = new StructLiteralExp(se->loc, se->sd, expsx); 1701 1720 v->value->type = se->type; 1702 1721 1703 1722 e = Cast(type, type, post ? ev : e2); 1704 1723 } 1705 1724 /* Assignment to struct member of the form: 1706 1725 * *(symoffexp) = e2 1707 1726 */ 1708 1727 else if (e1->op == TOKstar && ((PtrExp *)e1)->e1->op == TOKsymoff) 1709 1728 { SymOffExp *soe = (SymOffExp *)((PtrExp *)e1)->e1; 1710 1729 VarDeclaration *v = soe->var->isVarDeclaration(); 1711 1730 1712 if ( v->isDataseg())1731 if (!v->isCTFE()) 1713 1732 { 1714 1733 error("%s cannot be modified at compile time", v->toChars()); 1715 1734 return EXP_CANT_INTERPRET; 1716 1735 } 1717 1736 if (fp && !v->value) 1718 1737 { error("variable %s is used before initialization", v->toChars()); 1719 1738 return e; 1720 1739 } 1721 1740 Expression *vie = v->value; 1722 1741 if (vie->op == TOKvar) 1723 1742 { 1724 1743 Declaration *d = ((VarExp *)vie)->var; 1725 1744 vie = getVarExp(e1->loc, istate, d); 1726 1745 } 1727 1746 if (vie->op != TOKstructliteral) 1728 1747 return EXP_CANT_INTERPRET; 1729 1748 StructLiteralExp *se = (StructLiteralExp *)vie; 1730 1749 int fieldi = se->getFieldIndex(type, soe->offset); 1731 1750 if (fieldi == -1) 1732 1751 return EXP_CANT_INTERPRET; … … 1738 1757 if (e2 == EXP_CANT_INTERPRET) 1739 1758 return e2; 1740 1759 1741 1760 addVarToInterstate(istate, v); 1742 1761 1743 1762 /* Create new struct literal reflecting updated fieldi 1744 1763 */ 1745 1764 Expressions *expsx = changeOneElement(se->elements, fieldi, e2); 1746 1765 v->value = new StructLiteralExp(se->loc, se->sd, expsx); 1747 1766 v->value->type = se->type; 1748 1767 1749 1768 e = Cast(type, type, post ? ev : e2); 1750 1769 } 1751 1770 /* Assignment to array element of the form: 1752 1771 * a[i] = e2 1753 1772 */ 1754 1773 else if (e1->op == TOKindex && ((IndexExp *)e1)->e1->op == TOKvar) 1755 1774 { IndexExp *ie = (IndexExp *)e1; 1756 1775 VarExp *ve = (VarExp *)ie->e1; 1757 1776 VarDeclaration *v = ve->var->isVarDeclaration(); 1758 if (!v || v->isDataseg())1777 if (!v || !v->isCTFE()) 1759 1778 { 1760 1779 error("%s cannot be modified at compile time", v ? v->toChars(): "void"); 1761 1780 return EXP_CANT_INTERPRET; 1762 1781 } 1763 1782 if (v->value && v->value->op == TOKvar) 1764 1783 { 1765 1784 VarExp *ve2 = (VarExp *)v->value; 1766 1785 if (ve2->var->isSymbolDeclaration()) 1767 1786 { // This can happen if v is a struct initialized to 1768 1787 // 0 using an __initZ SymbolDeclaration from 1769 1788 // TypeStruct::defaultInit() 1770 1789 } 1771 1790 else 1772 1791 v = ve2->var->isVarDeclaration(); 1773 1792 assert(v); 1774 1793 } 1775 1794 if (!v->value) 1776 1795 { 1777 1796 if (fp) 1778 1797 { error("variable %s is used before initialization", v->toChars()); … … 1901 1920 se2->committed = se->committed; 1902 1921 se2->postfix = se->postfix; 1903 1922 se2->type = se->type; 1904 1923 v->value = se2; 1905 1924 } 1906 1925 else 1907 1926 assert(0); 1908 1927 1909 1928 e = Cast(type, type, post ? ev : e2); 1910 1929 } 1911 1930 1912 1931 /* Assignment to struct element in array, of the form: 1913 1932 * a[i].var = e2 1914 1933 */ 1915 1934 else if (e1->op == TOKdotvar && aggregate->op == TOKindex && 1916 1935 ((IndexExp *)aggregate)->e1->op == TOKvar) 1917 1936 { 1918 1937 IndexExp * ie = (IndexExp *)aggregate; 1919 1938 VarExp *ve = (VarExp *)(ie->e1); 1920 1939 VarDeclaration *v = ve->var->isVarDeclaration(); 1921 if (!v || v->isDataseg())1940 if (!v || !v->isCTFE()) 1922 1941 { 1923 1942 error("%s cannot be modified at compile time", v ? v->toChars(): "void"); 1924 1943 return EXP_CANT_INTERPRET; 1925 1944 } 1926 1945 Type *t = ve->type->toBasetype(); 1927 1946 ArrayLiteralExp *ae = (ArrayLiteralExp *)v->value; 1928 1947 if (!ae) 1929 1948 { 1930 1949 // assignment to one element in an uninitialized (static) array. 1931 1950 // This is quite difficult, because defaultInit() for a struct is a VarExp, 1932 1951 // not a StructLiteralExp. 1933 1952 Type *t = v->type->toBasetype(); 1934 1953 if (t->ty != Tsarray) 1935 1954 { 1936 1955 error("Cannot index an uninitialized variable"); 1937 1956 return EXP_CANT_INTERPRET; 1938 1957 } 1939 1958 1940 1959 Type *telem = ((TypeSArray *)t)->nextOf()->toBasetype(); 1941 1960 if (telem->ty != Tstruct) { return EXP_CANT_INTERPRET; } … … 1993 2012 e2 = Cast(type, type, e2); 1994 2013 if (e2 == EXP_CANT_INTERPRET) 1995 2014 return e2; 1996 2015 1997 2016 // Create new struct literal reflecting updated field 1998 2017 Expressions *expsx = changeOneElement(se->elements, fieldi, e2); 1999 2018 Expression * newstruct = new StructLiteralExp(se->loc, se->sd, expsx); 2000 2019 2001 2020 // Create new array literal reflecting updated struct elem 2002 2021 ae->elements = changeOneElement(ae->elements, elemi, newstruct); 2003 2022 return ae; 2004 2023 } 2005 2024 /* Slice assignment, initialization of static arrays 2006 2025 * a[] = e 2007 2026 */ 2008 2027 else if (e1->op == TOKslice && ((SliceExp *)e1)->e1->op==TOKvar) 2009 2028 { 2010 2029 SliceExp * sexp = (SliceExp *)e1; 2011 2030 VarExp *ve = (VarExp *)(sexp->e1); 2012 2031 VarDeclaration *v = ve->var->isVarDeclaration(); 2013 if (!v || v->isDataseg())2032 if (!v || !v->isCTFE()) 2014 2033 { 2015 2034 error("%s cannot be modified at compile time", v->toChars()); 2016 2035 return EXP_CANT_INTERPRET; 2017 2036 } 2018 2037 // Chase down rebinding of out and ref 2019 2038 if (v->value && v->value->op == TOKvar) 2020 2039 { 2021 2040 VarExp *ve2 = (VarExp *)v->value; 2022 2041 if (ve2->var->isSymbolDeclaration()) 2023 2042 { // This can happen if v is a struct initialized to 2024 2043 // 0 using an __initZ SymbolDeclaration from 2025 2044 // TypeStruct::defaultInit() 2026 2045 } 2027 2046 else 2028 2047 v = ve2->var->isVarDeclaration(); 2029 2048 assert(v); 2030 2049 } 2031 2050 /* Set the $ variable 2032 2051 */ 2033 2052 Expression *ee = v->value ? ArrayLength(Type::tsize_t, v->value) … … 2621 2640 { StructLiteralExp *se = (StructLiteralExp *)ex; 2622 2641 VarDeclaration *v = var->isVarDeclaration(); 2623 2642 if (v) 2624 2643 { e = se->getField(type, v->offset); 2625 2644 if (!e) 2626 2645 e = EXP_CANT_INTERPRET; 2627 2646 return e; 2628 2647 } 2629 2648 } else error("%s.%s is not yet implemented at compile time", ex->toChars(), var->toChars()); 2630 2649 } 2631 2650 2632 2651 #if LOG 2633 2652 if (e == EXP_CANT_INTERPRET) 2634 2653 printf("DotVarExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars()); 2635 2654 #endif 2636 2655 return e; 2637 2656 } 2638 2657 2639 2658 /******************************* Special Functions ***************************/ 2640 2659 2660 #if DMDV1 2661 2641 2662 Expression *interpret_aaLen(InterState *istate, Expressions *arguments) 2642 2663 { 2643 2664 if (!arguments || arguments->dim != 1) 2644 2665 return NULL; 2645 2666 Expression *earg = (Expression *)arguments->data[0]; 2646 2667 earg = earg->interpret(istate); 2647 2668 if (earg == EXP_CANT_INTERPRET) 2648 2669 return NULL; 2649 2670 if (earg->op != TOKassocarrayliteral) 2650 2671 return NULL; 2651 2672 AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; 2652 2673 Expression *e = new IntegerExp(aae->loc, aae->keys->dim, Type::tsize_t); 2653 2674 return e; 2654 2675 } 2655 2676 2656 2677 Expression *interpret_aaKeys(InterState *istate, Expressions *arguments) 2657 2678 { 2658 2679 #if LOG 2659 2680 printf("interpret_aaKeys()\n"); 2660 2681 #endif … … 2675 2696 2676 2697 Expression *interpret_aaValues(InterState *istate, Expressions *arguments) 2677 2698 { 2678 2699 //printf("interpret_aaValues()\n"); 2679 2700 if (!arguments || arguments->dim != 3) 2680 2701 return NULL; 2681 2702 Expression *earg = (Expression *)arguments->data[0]; 2682 2703 earg = earg->interpret(istate); 2683 2704 if (earg == EXP_CANT_INTERPRET) 2684 2705 return NULL; 2685 2706 if (earg->op != TOKassocarrayliteral) 2686 2707 return NULL; 2687 2708 AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; 2688 2709 Expression *e = new ArrayLiteralExp(aae->loc, aae->values); 2689 2710 Type *elemType = ((TypeAArray *)aae->type)->next; 2690 2711 e->type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments->dim : 0)); 2691 2712 //printf("result is %s\n", e->toChars()); 2692 2713 return e; 2693 2714 } 2694 2715 2716 #endif 2717 2718 #if DMDV2 2719 2720 Expression *interpret_length(InterState *istate, Expression *earg) 2721 { 2722 //printf("interpret_length()\n"); 2723 earg = earg->interpret(istate); 2724 if (earg == EXP_CANT_INTERPRET) 2725 return NULL; 2726 if (earg->op != TOKassocarrayliteral) 2727 return NULL; 2728 AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; 2729 Expression *e = new IntegerExp(aae->loc, aae->keys->dim, Type::tsize_t); 2730 return e; 2731 } 2732 2733 Expression *interpret_keys(InterState *istate, Expression *earg, FuncDeclaration *fd) 2734 { 2735 #if LOG 2736 printf("interpret_keys()\n"); 2737 #endif 2738 earg = earg->interpret(istate); 2739 if (earg == EXP_CANT_INTERPRET) 2740 return NULL; 2741 if (earg->op != TOKassocarrayliteral) 2742 return NULL; 2743 AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; 2744 Expression *e = new ArrayLiteralExp(aae->loc, aae->keys); 2745 assert(fd->type->ty == Tfunction); 2746 assert(fd->type->nextOf()->ty == Tarray); 2747 Type *elemType = ((TypeFunction *)fd->type)->nextOf()->nextOf(); 2748 e->type = new TypeSArray(elemType, new IntegerExp(aae->keys->dim)); 2749 return e; 2750 } 2751 2752 Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclaration *fd) 2753 { 2754 //printf("interpret_values()\n"); 2755 earg = earg->interpret(istate); 2756 if (earg == EXP_CANT_INTERPRET) 2757 return NULL; 2758 if (earg->op != TOKassocarrayliteral) 2759 return NULL; 2760 AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; 2761 Expression *e = new ArrayLiteralExp(aae->loc, aae->values); 2762 assert(fd->type->ty == Tfunction); 2763 assert(fd->type->nextOf()->ty == Tarray); 2764 Type *elemType = ((TypeFunction *)fd->type)->nextOf()->nextOf(); 2765 e->type = new TypeSArray(elemType, new IntegerExp(aae->values->dim)); 2766 //printf("result is %s\n", e->toChars()); 2767 return e; 2768 } 2769 2770 #endif 2771 trunk/src/constfold.c
r199 r314 1075 1075 if (e1->type->equals(type) && type->equals(to)) 1076 1076 return e1; 1077 1077 if (e1->type->implicitConvTo(to) >= MATCHconst || 1078 1078 to->implicitConvTo(e1->type) >= MATCHconst) 1079 1079 return expType(to, e1); 1080 1080 1081 1081 Type *tb = to->toBasetype(); 1082 1082 Type *typeb = type->toBasetype(); 1083 1083 1084 1084 /* Allow casting from one string type to another 1085 1085 */ 1086 1086 if (e1->op == TOKstring) 1087 1087 { 1088 1088 if (tb->ty == Tarray && typeb->ty == Tarray && 1089 1089 tb->nextOf()->size() == typeb->nextOf()->size()) 1090 1090 { 1091 1091 return expType(to, e1); 1092 1092 } 1093 1093 } 1094 1094 1095 if (e1->op == TOKarrayliteral && typeb == tb) 1096 return e1; 1097 1095 1098 if (e1->isConst() != 1) 1096 1099 return EXP_CANT_INTERPRET; 1097 1100 1098 1101 if (tb->ty == Tbool) 1099 1102 e = new IntegerExp(loc, e1->toInteger() != 0, type); 1100 1103 else if (type->isintegral()) 1101 1104 { 1102 1105 if (e1->type->isfloating()) 1103 1106 { dinteger_t result; 1104 1107 real_t r = e1->toReal(); 1105 1108 1106 1109 switch (typeb->ty) 1107 1110 { 1108 1111 case Tint8: result = (d_int8)r; break; 1109 1112 case Tchar: 1110 1113 case Tuns8: result = (d_uns8)r; break; 1111 1114 case Tint16: result = (d_int16)r; break; 1112 1115 case Twchar: 1113 1116 case Tuns16: result = (d_uns16)r; break; 1114 1117 case Tint32: result = (d_int32)r; break; trunk/src/declaration.c
r307 r314 1427 1427 ) 1428 1428 { 1429 1429 return 0; 1430 1430 } 1431 1431 #else 1432 1432 if (storage_class & STCmanifest) 1433 1433 return 0; 1434 1434 #endif 1435 1435 return 1; 1436 1436 } 1437 1437 1438 1438 /******************************* 1439 1439 * Does symbol go into data segment? 1440 1440 * Includes extern variables. 1441 1441 */ 1442 1442 1443 1443 int VarDeclaration::isDataseg() 1444 1444 { 1445 1445 #if 0 1446 1446 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars()); 1447 printf("% x, %p,%p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance());1447 printf("%llx, isModule: %p, isTemplateInstance: %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance()); 1448 1448 printf("parent = '%s'\n", parent->toChars()); 1449 1449 #endif 1450 1450 if (storage_class & STCmanifest) 1451 1451 return 0; 1452 1452 Dsymbol *parent = this->toParent(); 1453 1453 if (!parent && !(storage_class & STCstatic)) 1454 1454 { error("forward referenced"); 1455 1455 type = Type::terror; 1456 1456 return 0; 1457 1457 } 1458 1458 return canTakeAddressOf() && 1459 1459 (storage_class & (STCstatic | STCextern | STCtls | STCgshared) || 1460 1460 toParent()->isModule() || 1461 1461 toParent()->isTemplateInstance()); 1462 1462 } 1463 1463 1464 1464 /************************************ 1465 1465 * Does symbol go into thread local storage? 1466 1466 */ 1467 1467 1468 1468 int VarDeclaration::isThreadlocal() 1469 1469 { 1470 1470 //printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars()); 1471 1471 #if 0 || TARGET_OSX 1472 1472 /* To be thread-local, must use the __thread storage class. 1473 1473 * BUG: OSX doesn't support thread local yet. 1474 1474 */ 1475 1475 return isDataseg() && 1476 1476 (storage_class & (STCtls | STCconst | STCimmutable | STCshared | STCgshared)) == STCtls; 1477 1477 #else 1478 1478 /* Data defaults to being thread-local. It is not thread-local 1479 1479 * if it is immutable, const or shared. 1480 1480 */ 1481 1481 int i = isDataseg() && 1482 1482 !(storage_class & (STCimmutable | STCconst | STCshared | STCgshared)); 1483 1483 //printf("\treturn %d\n", i); 1484 1484 return i; 1485 1485 #endif 1486 1486 } 1487 1487 1488 /******************************************** 1489 * Can variable be read and written by CTFE? 1490 */ 1491 1492 int VarDeclaration::isCTFE() 1493 { 1494 return (storage_class & STCctfe) || !isDataseg(); 1495 } 1496 1488 1497 int VarDeclaration::hasPointers() 1489 1498 { 1490 1499 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type->ty); 1491 1500 return (!isDataseg() && type->hasPointers()); 1492 1501 } 1493 1502 1494 1503 /****************************************** 1495 1504 * Return TRUE if variable needs to call the destructor. 1496 1505 */ 1497 1506 1498 1507 int VarDeclaration::needsAutoDtor() 1499 1508 { 1500 1509 //printf("VarDeclaration::needsAutoDtor() %s\n", toChars()); 1501 1510 1502 1511 if (noauto || storage_class & STCnodtor) 1503 1512 return FALSE; 1504 1513 1505 1514 // Destructors for structs and arrays of structs 1506 1515 Type *tv = type->toBasetype(); 1507 1516 while (tv->ty == Tsarray) trunk/src/declaration.h
r305 r314 64 64 STCimmutable = 0x100000, 65 65 STCref = 0x200000, 66 66 STCinit = 0x400000, // has explicit initializer 67 67 STCmanifest = 0x800000, // manifest constant 68 68 STCnodtor = 0x1000000, // don't run destructor 69 69 STCnothrow = 0x2000000, // never throws exceptions 70 70 STCpure = 0x4000000, // pure function 71 71 STCtls = 0x8000000, // thread local 72 72 STCalias = 0x10000000, // alias parameter 73 73 STCshared = 0x20000000, // accessible from multiple threads 74 74 STCgshared = 0x40000000, // accessible from multiple threads 75 75 // but not typed as "shared" 76 76 STCwild = 0x80000000, // for "wild" type constructor 77 77 STC_TYPECTOR = (STCconst | STCimmutable | STCshared | STCwild), 78 78 }; 79 79 80 80 #define STCproperty 0x100000000LL 81 81 #define STCsafe 0x200000000LL 82 82 #define STCtrusted 0x400000000LL 83 83 #define STCsystem 0x800000000LL 84 #define STCctfe 0x1000000000LL // can be used in CTFE, even if it is static 84 85 85 86 struct Match 86 87 { 87 88 int count; // number of matches found 88 89 MATCH last; // match level of lastf 89 90 FuncDeclaration *lastf; // last matching function we found 90 91 FuncDeclaration *nextf; // current matching function 91 92 FuncDeclaration *anyf; // pick a func, any func, to use for error recovery 92 93 }; 93 94 94 95 void overloadResolveX(Match *m, FuncDeclaration *f, 95 96 Expression *ethis, Expressions *arguments); 96 97 int overloadApply(FuncDeclaration *fstart, 97 98 int (*fp)(void *, FuncDeclaration *), 98 99 void *param); 99 100 100 101 /**************************************************************/ 101 102 102 103 struct Declaration : Dsymbol 103 104 { … … 251 252 #if DMDV2 252 253 VarDeclaration *rundtor; // if !NULL, rundtor is tested at runtime to see 253 254 // if the destructor should be run. Used to prevent 254 255 // dtor calls on postblitted vars 255 256 #endif 256 257 257 258 VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init); 258 259 Dsymbol *syntaxCopy(Dsymbol *); 259 260 void semantic(Scope *sc); 260 261 void semantic2(Scope *sc); 261 262 const char *kind(); 262 263 void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 263 264 #ifdef _DH 264 265 Type *htype; 265 266 Initializer *hinit; 266 267 #endif 267 268 int needThis(); 268 269 int isImportedSymbol(); 269 270 int isDataseg(); 270 271 int isThreadlocal(); 272 int isCTFE(); 271 273 int hasPointers(); 272 274 #if DMDV2 273 275 int canTakeAddressOf(); 274 276 int needsAutoDtor(); 275 277 #endif 276 278 Expression *callAutoDtor(Scope *sc); 277 279 ExpInitializer *getExpInitializer(); 278 280 Expression *getConstInitializer(); 279 281 void checkCtorConstInit(); 280 282 void checkNestedReference(Scope *sc, Loc loc); 281 283 Dsymbol *toAlias(); 282 284 283 285 Symbol *toSymbol(); 284 286 void toObjFile(int multiobj); // compile to .obj file 285 287 int cvMember(unsigned char *p); 286 288 287 289 // Eliminate need for dynamic_cast 288 290 VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; } 289 291 }; 290 292 trunk/src/expression.c
r313 r314 696 696 Type *tret = p->isLazyArray(); 697 697 switch (tb->ty) 698 698 { 699 699 case Tsarray: 700 700 case Tarray: 701 701 { // Create a static array variable v of type arg->type 702 702 #ifdef IN_GCC 703 703 /* GCC 4.0 does not like zero length arrays used like 704 704 this; pass a null array value instead. Could also 705 705 just make a one-element array. */ 706 706 if (nargs - i == 0) 707 707 { 708 708 arg = new NullExp(loc); 709 709 break; 710 710 } 711 711 #endif 712 712 Identifier *id = Lexer::uniqueId("__arrayArg"); 713 713 Type *t = new TypeSArray(((TypeArray *)tb)->next, new IntegerExp(nargs - i)); 714 714 t = t->semantic(loc, sc); 715 715 VarDeclaration *v = new VarDeclaration(loc, t, id, new VoidInitializer(loc)); 716 v->storage_class |= STCctfe; 716 717 v->semantic(sc); 717 718 v->parent = sc->parent; 718 719 //sc->insert(v); 719 720 720 721 Expression *c = new DeclarationExp(0, v); 721 722 c->type = v->type; 722 723 723 724 for (size_t u = i; u < nargs; u++) 724 725 { Expression *a = (Expression *)arguments->data[u]; 725 726 if (tret && !((TypeArray *)tb)->next->equals(a->type)) 726 727 a = a->toDelegate(sc, tret); 727 728 728 729 Expression *e = new VarExp(loc, v); 729 730 e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams)); 730 731 AssignExp *ae = new AssignExp(loc, e, a); 731 732 #if DMDV2 732 733 ae->op = TOKconstruct; 733 734 #endif 734 735 if (c) 735 736 c = new CommaExp(loc, c, ae); trunk/src/interpret.c
r310 r314 96 96 return NULL; 97 97 98 98 if (!fbody) 99 99 { cantInterpret = 1; 100 100 return NULL; 101 101 } 102 102 103 103 if (semanticRun < 3 && scope) 104 104 { 105 105 semantic3(scope); 106 106 if (global.errors) // if errors compiling this function 107 107 return NULL; 108 108 } 109 109 if (semanticRun < 4) 110 110 return NULL; 111 111 112 112 Type *tb = type->toBasetype(); 113 113 assert(tb->ty == Tfunction); 114 114 TypeFunction *tf = (TypeFunction *)tb; 115 115 Type *tret = tf->next->toBasetype(); 116 if (tf->varargs )116 if (tf->varargs && arguments && parameters && arguments->dim != parameters->dim) 117 117 { cantInterpret = 1; 118 error(" Variadic functions are not yet implemented in CTFE");118 error("C-style variadic functions are not yet implemented in CTFE"); 119 119 return NULL; 120 120 } 121 121 122 122 // Ensure there are no lazy parameters 123 123 if (tf->parameters) 124 124 { size_t dim = Parameter::dim(tf->parameters); 125 125 for (size_t i = 0; i < dim; i++) 126 126 { Parameter *arg = Parameter::getNth(tf->parameters, i); 127 127 if (arg->storageClass & STClazy) 128 128 { cantInterpret = 1; 129 129 return NULL; 130 130 } 131 131 } 132 132 } 133 133 134 134 InterState istatex; 135 135 istatex.caller = istate; 136 136 istatex.fd = this; 137 137 istatex.localThis = thisarg; 138 138 … … 1006 1006 } 1007 1007 1008 1008 Expression *getVarExp(Loc loc, InterState *istate, Declaration *d) 1009 1009 { 1010 1010 Expression *e = EXP_CANT_INTERPRET; 1011 1011 VarDeclaration *v = d->isVarDeclaration(); 1012 1012 SymbolDeclaration *s = d->isSymbolDeclaration(); 1013 1013 if (v) 1014 1014 { 1015 1015 #if DMDV2 1016 1016 if ((v->isConst() || v->isImmutable() || v->storage_class & STCmanifest) && v->init && !v->value) 1017 1017 #else 1018 1018 if (v->isConst() && v->init) 1019 1019 #endif 1020 1020 { e = v->init->toExpression(); 1021 1021 if (e && !e->type) 1022 1022 e->type = v->type; 1023 1023 } 1024 1024 else 1025 1025 { e = v->value; 1026 if ( v->isDataseg())1026 if (!v->isCTFE()) 1027 1027 { error(loc, "static variable %s cannot be read at compile time", v->toChars()); 1028 1028 e = EXP_CANT_INTERPRET; 1029 1029 } 1030 1030 else if (!e) 1031 1031 error(loc, "variable %s is used before initialization", v->toChars()); 1032 1032 else if (e != EXP_CANT_INTERPRET) 1033 1033 e = e->interpret(istate); 1034 1034 } 1035 1035 if (!e) 1036 1036 e = EXP_CANT_INTERPRET; 1037 1037 } 1038 1038 else if (s) 1039 1039 { 1040 1040 if (s->dsym->toInitializer() == s->sym) 1041 1041 { Expressions *exps = new Expressions(); 1042 1042 e = new StructLiteralExp(0, s->dsym, exps); 1043 1043 e = e->semantic(NULL); 1044 1044 } 1045 1045 } 1046 1046 return e; … … 1598 1598 } 1599 1599 1600 1600 // To reduce code complexity of handling dotvar expressions, 1601 1601 // extract the aggregate now. 1602 1602 Expression *aggregate; 1603 1603 if (e1->op == TOKdotvar) { 1604 1604 aggregate = ((DotVarExp *)e1)->e1; 1605 1605 // Get rid of 'this'. 1606 1606 if (aggregate->op == TOKthis && istate->localThis) 1607 1607 aggregate = istate->localThis; 1608 1608 } 1609 1609 1610 1610 /* Assignment to variable of the form: 1611 1611 * v = e2 1612 1612 */ 1613 1613 if (e1->op == TOKvar) 1614 1614 { 1615 1615 VarExp *ve = (VarExp *)e1; 1616 1616 VarDeclaration *v = ve->var->isVarDeclaration(); 1617 1617 assert(v); 1618 if (v && v->isDataseg())1618 if (v && !v->isCTFE()) 1619 1619 { // Can't modify global or static data 1620 1620 error("%s cannot be modified at compile time", v->toChars()); 1621 1621 return EXP_CANT_INTERPRET; 1622 1622 } 1623 if (v && !v->isDataseg())1623 if (v && v->isCTFE()) 1624 1624 { 1625 1625 Expression *ev = v->value; 1626 1626 if (fp && !ev) 1627 1627 { error("variable %s is used before initialization", v->toChars()); 1628 1628 return e; 1629 1629 } 1630 1630 if (fp) 1631 1631 e2 = (*fp)(v->type, ev, e2); 1632 1632 else 1633 1633 { /* Look for special case of struct being initialized with 0. 1634 1634 */ 1635 1635 if (v->type->toBasetype()->ty == Tstruct && e2->op == TOKint64) 1636 1636 { 1637 1637 e2 = v->type->defaultInit(); 1638 1638 } 1639 1639 e2 = Cast(v->type, v->type, e2); 1640 1640 } 1641 1641 if (e2 == EXP_CANT_INTERPRET) 1642 1642 return e2; 1643 1643 1644 1644 addVarToInterstate(istate, v); 1645 1645 v->value = e2; 1646 1646 e = Cast(type, type, post ? ev : e2); 1647 1647 } 1648 1648 } 1649 1649 else if (e1->op == TOKdotvar && aggregate->op == TOKdotvar) 1650 1650 { // eg v.u.var = e2, v[3].u.var = e2, etc. 1651 1651 error("Nested struct assignment %s is not yet supported in CTFE", toChars()); 1652 1652 } 1653 1653 /* Assignment to struct member of the form: 1654 1654 * v.var = e2 1655 1655 */ 1656 1656 else if (e1->op == TOKdotvar && aggregate->op == TOKvar) 1657 1657 { VarDeclaration *v = ((VarExp *)aggregate)->var->isVarDeclaration(); 1658 1658 1659 if ( v->isDataseg())1659 if (!v->isCTFE()) 1660 1660 { // Can't modify global or static data 1661 1661 error("%s cannot be modified at compile time", v->toChars()); 1662 1662 return EXP_CANT_INTERPRET; 1663 1663 } else { 1664 1664 // Chase down rebinding of out and ref 1665 1665 if (v->value && v->value->op == TOKvar) 1666 1666 { 1667 1667 VarExp *ve2 = (VarExp *)v->value; 1668 1668 if (ve2->var->isSymbolDeclaration()) 1669 1669 { // This can happen if v is a struct initialized to 1670 1670 // 0 using an __initZ SymbolDeclaration from 1671 1671 // TypeStruct::defaultInit() 1672 1672 } 1673 1673 else 1674 1674 v = ve2->var->isVarDeclaration(); 1675 1675 assert(v); 1676 1676 } 1677 1677 } 1678 1678 if (fp && !v->value) 1679 1679 { error("variable %s is used before initialization", v->toChars()); … … 1711 1711 if (e2 == EXP_CANT_INTERPRET) 1712 1712 return e2; 1713 1713 1714 1714 addVarToInterstate(istate, v); 1715 1715 1716 1716 /* Create new struct literal reflecting updated fieldi 1717 1717 */ 1718 1718 Expressions *expsx = changeOneElement(se->elements, fieldi, e2); 1719 1719 v->value = new StructLiteralExp(se->loc, se->sd, expsx); 1720 1720 v->value->type = se->type; 1721 1721 1722 1722 e = Cast(type, type, post ? ev : e2); 1723 1723 } 1724 1724 /* Assignment to struct member of the form: 1725 1725 * *(symoffexp) = e2 1726 1726 */ 1727 1727 else if (e1->op == TOKstar && ((PtrExp *)e1)->e1->op == TOKsymoff) 1728 1728 { SymOffExp *soe = (SymOffExp *)((PtrExp *)e1)->e1; 1729 1729 VarDeclaration *v = soe->var->isVarDeclaration(); 1730 1730 1731 if ( v->isDataseg())1731 if (!v->isCTFE()) 1732 1732 { 1733 1733 error("%s cannot be modified at compile time", v->toChars()); 1734 1734 return EXP_CANT_INTERPRET; 1735 1735 } 1736 1736 if (fp && !v->value) 1737 1737 { error("variable %s is used before initialization", v->toChars()); 1738 1738 return e; 1739 1739 } 1740 1740 Expression *vie = v->value; 1741 1741 if (vie->op == TOKvar) 1742 1742 { 1743 1743 Declaration *d = ((VarExp *)vie)->var; 1744 1744 vie = getVarExp(e1->loc, istate, d); 1745 1745 } 1746 1746 if (vie->op != TOKstructliteral) 1747 1747 return EXP_CANT_INTERPRET; 1748 1748 StructLiteralExp *se = (StructLiteralExp *)vie; 1749 1749 int fieldi = se->getFieldIndex(type, soe->offset); 1750 1750 if (fieldi == -1) 1751 1751 return EXP_CANT_INTERPRET; … … 1757 1757 if (e2 == EXP_CANT_INTERPRET) 1758 1758 return e2; 1759 1759 1760 1760 addVarToInterstate(istate, v); 1761 1761 1762 1762 /* Create new struct literal reflecting updated fieldi 1763 1763 */ 1764 1764 Expressions *expsx = changeOneElement(se->elements, fieldi, e2); 1765 1765 v->value = new StructLiteralExp(se->loc, se->sd, expsx); 1766 1766 v->value->type = se->type; 1767 1767 1768 1768 e = Cast(type, type, post ? ev : e2); 1769 1769 } 1770 1770 /* Assignment to array element of the form: 1771 1771 * a[i] = e2 1772 1772 */ 1773 1773 else if (e1->op == TOKindex && ((IndexExp *)e1)->e1->op == TOKvar) 1774 1774 { IndexExp *ie = (IndexExp *)e1; 1775 1775 VarExp *ve = (VarExp *)ie->e1; 1776 1776 VarDeclaration *v = ve->var->isVarDeclaration(); 1777 if (!v || v->isDataseg())1777 if (!v || !v->isCTFE()) 1778 1778 { 1779 1779 error("%s cannot be modified at compile time", v ? v->toChars(): "void"); 1780 1780 return EXP_CANT_INTERPRET; 1781 1781 } 1782 1782 if (v->value && v->value->op == TOKvar) 1783 1783 { 1784 1784 VarExp *ve2 = (VarExp *)v->value; 1785 1785 if (ve2->var->isSymbolDeclaration()) 1786 1786 { // This can happen if v is a struct initialized to 1787 1787 // 0 using an __initZ SymbolDeclaration from 1788 1788 // TypeStruct::defaultInit() 1789 1789 } 1790 1790 else 1791 1791 v = ve2->var->isVarDeclaration(); 1792 1792 assert(v); 1793 1793 } 1794 1794 if (!v->value) 1795 1795 { 1796 1796 if (fp) 1797 1797 { error("variable %s is used before initialization", v->toChars()); … … 1920 1920 se2->committed = se->committed; 1921 1921 se2->postfix = se->postfix; 1922 1922 se2->type = se->type; 1923 1923 v->value = se2; 1924 1924 } 1925 1925 else 1926 1926 assert(0); 1927 1927 1928 1928 e = Cast(type, type, post ? ev : e2); 1929 1929 } 1930 1930 1931 1931 /* Assignment to struct element in array, of the form: 1932 1932 * a[i].var = e2 1933 1933 */ 1934 1934 else if (e1->op == TOKdotvar && aggregate->op == TOKindex && 1935 1935 ((IndexExp *)aggregate)->e1->op == TOKvar) 1936 1936 { 1937 1937 IndexExp * ie = (IndexExp *)aggregate; 1938 1938 VarExp *ve = (VarExp *)(ie->e1); 1939 1939 VarDeclaration *v = ve->var->isVarDeclaration(); 1940 if (!v || v->isDataseg())1940 if (!v || !v->isCTFE()) 1941 1941 { 1942 1942 error("%s cannot be modified at compile time", v ? v->toChars(): "void"); 1943 1943 return EXP_CANT_INTERPRET; 1944 1944 } 1945 1945 Type *t = ve->type->toBasetype(); 1946 1946 ArrayLiteralExp *ae = (ArrayLiteralExp *)v->value; 1947 1947 if (!ae) 1948 1948 { 1949 1949 // assignment to one element in an uninitialized (static) array. 1950 1950 // This is quite difficult, because defaultInit() for a struct is a VarExp, 1951 1951 // not a StructLiteralExp. 1952 1952 Type *t = v->type->toBasetype(); 1953 1953 if (t->ty != Tsarray) 1954 1954 { 1955 1955 error("Cannot index an uninitialized variable"); 1956 1956 return EXP_CANT_INTERPRET; 1957 1957 } 1958 1958 1959 1959 Type *telem = ((TypeSArray *)t)->nextOf()->toBasetype(); 1960 1960 if (telem->ty != Tstruct) { return EXP_CANT_INTERPRET; } … … 2012 2012 e2 = Cast(type, type, e2); 2013 2013 if (e2 == EXP_CANT_INTERPRET) 2014 2014 return e2; 2015 2015 2016 2016 // Create new struct literal reflecting updated field 2017 2017 Expressions *expsx = changeOneElement(se->elements, fieldi, e2); 2018 2018 Expression * newstruct = new StructLiteralExp(se->loc, se->sd, expsx); 2019 2019 2020 2020 // Create new array literal reflecting updated struct elem 2021 2021 ae->elements = changeOneElement(ae->elements, elemi, newstruct); 2022 2022 return ae; 2023 2023 } 2024 2024 /* Slice assignment, initialization of static arrays 2025 2025 * a[] = e 2026 2026 */ 2027 2027 else if (e1->op == TOKslice && ((SliceExp *)e1)->e1->op==TOKvar) 2028 2028 { 2029 2029 SliceExp * sexp = (SliceExp *)e1; 2030 2030 VarExp *ve = (VarExp *)(sexp->e1); 2031 2031 VarDeclaration *v = ve->var->isVarDeclaration(); 2032 if (!v || v->isDataseg())2032 if (!v || !v->isCTFE()) 2033 2033 { 2034 2034 error("%s cannot be modified at compile time", v->toChars()); 2035 2035 return EXP_CANT_INTERPRET; 2036 2036 } 2037 2037 // Chase down rebinding of out and ref 2038 2038 if (v->value && v->value->op == TOKvar) 2039 2039 { 2040 2040 VarExp *ve2 = (VarExp *)v->value; 2041 2041 if (ve2->var->isSymbolDeclaration()) 2042 2042 { // This can happen if v is a struct initialized to 2043 2043 // 0 using an __initZ SymbolDeclaration from 2044 2044 // TypeStruct::defaultInit() 2045 2045 } 2046 2046 else 2047 2047 v = ve2->var->isVarDeclaration(); 2048 2048 assert(v); 2049 2049 } 2050 2050 /* Set the $ variable 2051 2051 */ 2052 2052 Expression *ee = v->value ? ArrayLength(Type::tsize_t, v->value)
