Ticket #125: forwardref.diff
File forwardref.diff, 51.4 kB (added by ChristianK, 15 years ago) |
---|
-
a/dmd/aggregate.h
old new 63 63 // 1: size is correct 64 64 // 2: cannot determine size; fwd referenced 65 65 int isdeprecated; // !=0 if deprecated 66 Scope *scope; // !=NULL means context to use67 66 68 67 // Special member functions 69 68 InvariantDeclaration *inv; // invariant … … 105 104 Symbol *toInitializer(); 106 105 107 106 AggregateDeclaration *isAggregateDeclaration() { return this; } 107 108 // LDC 109 int sc_offset; // saved next offset in aggregate 108 110 }; 109 111 110 112 struct AnonymousAggregateDeclaration : AggregateDeclaration … … 132 134 Dsymbol *syntaxCopy(Dsymbol *s); 133 135 void semantic(Scope *sc); 134 136 void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 137 138 //LDC, override to allow searching in partially semantic'ed structs 139 Dsymbol *search(Loc, Identifier *ident, int flags); 140 141 //LDC, for deferring 142 int deferState; 143 virtual bool isMemberReorderable(Dsymbol* s); 144 135 145 char *mangle(); 136 146 const char *kind(); 137 147 Expression *cloneMembers(); … … 153 163 const char *kind(); 154 164 155 165 UnionDeclaration *isUnionDeclaration() { return this; } 166 167 // LDC, overload to reset offset to zero after each member 168 virtual void postMemberSemantic(Scope* sc); 156 169 }; 157 170 158 171 struct BaseClass … … 215 228 VarDeclaration *vthis; // 'this' parameter if this class is nested 216 229 217 230 int inuse; // to prevent recursive attempts 231 232 //LDC, for deferring 233 int deferState; 218 234 219 235 ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses); 220 236 Dsymbol *syntaxCopy(Dsymbol *s); -
a/dmd/attrib.c
old new 44 44 : Dsymbol() 45 45 { 46 46 this->decl = decl; 47 member_semantic_started = false; 48 included_decls = NULL; 47 49 } 48 50 49 51 Array *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd) … … 66 68 return m; 67 69 } 68 70 71 // shares code with ScopeDsymbol::callSemanticOnMembers 72 void AttribDeclaration::callSemanticOnMembers(Scope* sc, Array* members) 73 { 74 if (!members) 75 return; 76 77 // first add everything to remaining_semantic 78 if (!member_semantic_started) { 79 for (int i = 0; i < members->dim; i++) 80 remaining_semantic.push_back( (Dsymbol*)members->data[i] ); 81 member_semantic_started = true; 82 } 83 84 int failed = 0; 85 86 // last defer exception that was caught. stored for the error message inside 87 DeferException* lastdefer; 88 89 // if we deferred an order dependent member, save it here 90 // we will then skip all order dependent members until this is reached again 91 Dsymbol *deferredOrderDependent = NULL; 92 93 while (!remaining_semantic.empty() && failed != remaining_semantic.size()) 94 { Dsymbol *s; 95 s = remaining_semantic[0]; 96 remaining_semantic.pop_front(); 97 98 // if we deferred something order dependent, skip other 99 // order dependent ones for one iteration 100 if (deferredOrderDependent == s) 101 deferredOrderDependent = NULL; 102 if (deferredOrderDependent && !isMemberReorderable(s)) { 103 ++failed; 104 remaining_semantic.push_back(s); 105 continue; 106 } 107 108 try { 109 runSemantic(s, sc); 110 } catch (DeferException* deferexc) { 111 lastdefer = deferexc; 112 ++failed; 113 remaining_semantic.push_back(s); 114 if (!isMemberReorderable(s)) 115 deferredOrderDependent = s; 116 continue; 117 } 118 119 failed = 0; 120 postMemberSemantic(sc); 121 } 122 123 if (!remaining_semantic.empty()) 124 { 125 assert(lastdefer); 126 127 // reorder members into a valid state if necessary 128 if (deferredOrderDependent) 129 while (remaining_semantic[0] != deferredOrderDependent) { 130 Dsymbol* s = remaining_semantic[0]; 131 remaining_semantic.pop_front(); 132 remaining_semantic.push_back(s); 133 } 134 135 throw lastdefer; 136 } 137 } 138 69 139 void AttribDeclaration::semantic(Scope *sc) 70 140 { 71 Array *d = include(sc, NULL); 141 if (!included_decls) 142 included_decls = include(sc, NULL); 72 143 73 144 //printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d); 74 if (d) 75 { 76 for (unsigned i = 0; i < d->dim; i++) 77 { 78 Dsymbol *s = (Dsymbol *)d->data[i]; 79 80 s->semantic(sc); 81 } 82 } 145 callSemanticOnMembers(sc, included_decls); 83 146 } 84 147 85 148 void AttribDeclaration::semantic2(Scope *sc) … … 297 360 if (stc & (STCauto | STCscope | STCstatic | STCextern)) 298 361 sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern); 299 362 sc->stc |= stc; 300 for (unsigned i = 0; i < decl->dim; i++) 301 { 302 Dsymbol *s = (Dsymbol *)decl->data[i]; 303 304 s->semantic(sc); 305 } 363 callSemanticOnMembers(sc, decl); 306 364 sc->stc = stc_save; 307 365 } 308 366 else … … 371 429 { enum LINK linkage_save = sc->linkage; 372 430 373 431 sc->linkage = linkage; 374 for (unsigned i = 0; i < decl->dim; i++) 375 { 376 Dsymbol *s = (Dsymbol *)decl->data[i]; 377 378 s->semantic(sc); 379 } 432 callSemanticOnMembers(sc, decl); 380 433 sc->linkage = linkage_save; 381 434 } 382 435 else … … 461 514 462 515 sc->protection = protection; 463 516 sc->explicitProtection = 1; 464 for (unsigned i = 0; i < decl->dim; i++) 465 { 466 Dsymbol *s = (Dsymbol *)decl->data[i]; 467 468 s->semantic(sc); 469 } 517 callSemanticOnMembers(sc, decl); 470 518 sc->protection = protection_save; 471 519 sc->explicitProtection = explicitProtection_save; 472 520 } … … 520 568 521 569 //printf("\tAlignDeclaration::semantic '%s'\n",toChars()); 522 570 if (decl) 523 { unsigned salign_save = sc->structalign; 524 525 for (unsigned i = 0; i < decl->dim; i++) 526 { 527 Dsymbol *s = (Dsymbol *)decl->data[i]; 528 529 if (s->isStructDeclaration() && salign == 1) 530 { 531 sc->structalign = salign; 532 s->semantic(sc); 533 sc->structalign = salign_save; 534 } 535 else 536 { 537 s->semantic(sc); 538 } 539 } 540 sc->structalign = salign_save; 571 { 572 callSemanticOnMembers(sc, decl); 541 573 } 542 574 else 543 575 assert(0 && "what kind of align use triggers this?"); 544 576 } 545 577 578 void AlignDeclaration::runSemantic(Dsymbol* s, Scope* sc) 579 { 580 unsigned salign_save = sc->structalign; 581 582 if (s->isStructDeclaration() && salign == 1) 583 { 584 sc->structalign = salign; 585 s->semantic(sc); 586 sc->structalign = salign_save; 587 } 588 else 589 { 590 s->semantic(sc); 591 } 592 } 546 593 547 594 void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 548 595 { … … 557 604 { 558 605 this->loc = loc; 559 606 this->isunion = isunion; 560 this->scope = NULL;561 607 this->sem = 0; 608 609 sc_offset = -1; 562 610 } 563 611 564 612 Dsymbol *AnonDeclaration::syntaxCopy(Dsymbol *s) … … 570 618 return ad; 571 619 } 572 620 621 // copied from StructDeclaration::isMemberReorderable 622 bool AnonDeclaration::isMemberReorderable(Dsymbol* s) 623 { 624 if ( 625 s->isVarDeclaration() || 626 s->isAttribDeclaration() 627 ) 628 return false; 629 return true; 630 } 631 632 void AnonDeclaration::postMemberSemantic(Scope* sc) 633 { 634 if (isunion) 635 sc->offset = 0; 636 } 637 573 638 void AnonDeclaration::semantic(Scope *sc) 574 639 { 575 640 //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this); 576 577 Scope *scx = NULL;578 if (scope)579 { sc = scope;580 scx = scope;581 scope = NULL;582 }583 641 584 642 assert(sc->parent); 585 643 … … 594 652 595 653 if (decl) 596 654 { 597 AnonymousAggregateDeclaration aad;598 655 int adisunion; 599 656 600 657 if (sc->anonAgg) … … 613 670 sc->stc &= ~(STCauto | STCscope | STCstatic); 614 671 sc->inunion = isunion; 615 672 sc->offset = 0; 673 if (sc_offset >= 0) 674 sc->offset = sc_offset; 675 616 676 sc->flags = 0; 617 677 aad.structalign = sc->structalign; 618 678 aad.parent = ad; 619 679 620 for (unsigned i = 0; i < decl->dim; i++) 621 { 622 Dsymbol *s = (Dsymbol *)decl->data[i]; 680 try { 681 callSemanticOnMembers(sc, decl); 682 } catch (DeferException* deferexc) { 683 sc_offset = sc->offset; 684 sc->pop(); 685 throw deferexc; 686 } 623 687 624 s->semantic(sc);625 if (isunion)626 sc->offset = 0;627 if (aad.sizeok == 2)628 {629 break;630 }631 }632 688 sc = sc->pop(); 633 689 634 // If failed due to forward references, unwind and try again later635 if (aad.sizeok == 2)636 {637 ad->sizeok = 2;638 //printf("\tsetting ad->sizeok %p to 2\n", ad);639 if (!sc->anonAgg)640 {641 scope = scx ? scx : new Scope(*sc);642 scope->setNoFree();643 scope->module->addDeferredSemantic(this);644 }645 //printf("\tforward reference %p\n", this);646 return;647 }648 690 if (sem == 0) 649 691 { Module::dprogress++; 650 692 sem = 1; … … 1331 1373 1332 1374 void StaticIfDeclaration::semantic(Scope *sc) 1333 1375 { 1334 Array *d = include(sc, sd); 1376 if (!included_decls) 1377 included_decls = include(sc, sd); 1335 1378 1336 1379 //printf("\tStaticIfDeclaration::semantic '%s', d = %p\n",toChars(), d); 1337 if ( d)1380 if (included_decls) 1338 1381 { 1339 1382 if (!addisdone) 1340 1383 { AttribDeclaration::addMember(sc, sd, 1); 1341 1384 addisdone = 1; 1342 1385 } 1343 1386 1344 for (unsigned i = 0; i < d->dim; i++) 1345 { 1346 Dsymbol *s = (Dsymbol *)d->data[i]; 1347 1348 s->semantic(sc); 1349 } 1387 callSemanticOnMembers(sc, included_decls); 1350 1388 } 1351 1389 } 1352 1390 -
a/dmd/attrib.h
old new 16 16 #endif /* __DMC__ */ 17 17 18 18 #include "dsymbol.h" 19 #include "aggregate.h" 19 20 20 21 struct Expression; 21 22 struct Statement; … … 52 53 53 54 void toObjFile(int multiobj); // compile to .obj file 54 55 int cvMember(unsigned char *p); 56 57 // LDC 58 Array *included_decls; 59 std::deque<Dsymbol*> remaining_semantic; 60 bool member_semantic_started; 61 62 void callSemanticOnMembers(Scope* sc, Array* members); 63 virtual void runSemantic(Dsymbol* s, Scope* sc) { s->semantic(sc); } 64 virtual void postMemberSemantic(Scope* sc) {}; 65 virtual bool isMemberReorderable(Dsymbol* sym) { return true; } 55 66 }; 56 67 57 68 struct StorageClassDeclaration: AttribDeclaration … … 94 105 Dsymbol *syntaxCopy(Dsymbol *s); 95 106 void semantic(Scope *sc); 96 107 void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 108 109 void runSemantic(Dsymbol* s, Scope* sc); 97 110 }; 98 111 99 112 struct AnonDeclaration : AttribDeclaration 100 113 { 101 114 int isunion; 102 Scope *scope; // !=NULL means context to use103 115 int sem; // 1 if successful semantic() 104 116 105 117 AnonDeclaration(Loc loc, int isunion, Array *decl); … … 107 119 void semantic(Scope *sc); 108 120 void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 109 121 const char *kind(); 122 123 void postMemberSemantic(Scope* sc); 124 bool isMemberReorderable(Dsymbol* sym); 125 int sc_offset; // saved next offset in aggregate 126 AnonymousAggregateDeclaration aad; 110 127 }; 111 128 112 129 struct PragmaDeclaration : AttribDeclaration -
a/dmd/class.c
old new 40 40 if (baseclasses) 41 41 this->baseclasses = *baseclasses; 42 42 baseClass = NULL; 43 44 deferState = 0; 43 45 44 46 interfaces_dim = 0; 45 47 interfaces = NULL; … … 216 218 void ClassDeclaration::semantic(Scope *sc) 217 219 { int i; 218 220 unsigned offset; 221 Scope scsave; 222 Scope *scx = NULL; 219 223 220 224 //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this); 221 225 //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : ""); … … 223 227 224 228 //{ static int n; if (++n == 20) *(char*)0=0; } 225 229 230 int continueAt = deferState; 231 if (deferState > 0) 232 deferState = 0; 233 switch (continueAt) { 234 case 0: 235 226 236 if (!ident) // if anonymous class 227 237 { char *id = "__anonclass"; 228 238 229 239 ident = Identifier::generateId(id); 230 240 } 231 241 232 if (!scope) 233 { 234 if (!parent && sc->parent && !sc->parent->isModule()) 235 parent = sc->parent; 242 if (!parent && sc->parent && !sc->parent->isModule()) 243 parent = sc->parent; 236 244 237 238 239 } 245 type = type->semantic(loc, sc); 246 handle = handle->semantic(loc, sc); 247 240 248 if (!members) // if forward reference 241 249 { //printf("\tclass '%s' is forward referenced\n", toChars()); 242 250 return; 243 251 } 244 252 if (symtab) 245 { if (!scope) 246 { //printf("\tsemantic for '%s' is already completed\n", toChars()); 247 return; // semantic() already completed 248 } 253 { 254 return; // semantic() already completed 249 255 } 250 256 else 251 257 symtab = new DsymbolTable(); 252 258 253 Scope *scx = NULL;254 if (scope)255 { sc = scope;256 scx = scope; // save so we don't make redundant copies257 scope = NULL;258 }259 259 #ifdef IN_GCC 260 260 methods.setDim(0); 261 261 #endif … … 286 286 i++; 287 287 } 288 288 289 case 1: 289 290 // See if there's a base class as first in baseclasses[] 290 291 if (baseclasses.dim) 291 292 { TypeClass *tc; … … 327 328 goto L7; 328 329 } 329 330 } 330 if (!tc->sym->symtab || tc->sym-> scope|| tc->sym->sizeok == 0)331 if (!tc->sym->symtab || tc->sym->deferState > 0 || tc->sym->sizeok == 0) 331 332 { 332 333 //error("forward reference of base class %s", baseClass->toChars()); 333 334 // Forward reference of base class, try again later 334 335 //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars()); 335 scope = scx ? scx : new Scope(*sc); 336 scope->setNoFree(); 337 scope->module->addDeferredSemantic(this); 336 deferState = 1; 337 sc->module->addDeferredSemantic(this, sc); 338 338 return; 339 //throw new DeferException(loc, "forward reference of base class %s", tc->sym->toChars()); 339 340 } 340 341 else 341 342 { baseClass = tc->sym; … … 346 347 } 347 348 } 348 349 350 case 2: 349 351 // Treat the remaining entries in baseclasses as interfaces 350 352 // Check for errors, handle forward references 351 353 for (i = (baseClass ? 1 : 0); i < baseclasses.dim; ) … … 388 390 } 389 391 390 392 b->base = tc->sym; 391 if (!b->base->symtab || b->base-> scope)393 if (!b->base->symtab || b->base->deferState > 0) 392 394 { 393 395 //error("forward reference of base class %s", baseClass->toChars()); 394 396 // Forward reference of base, try again later 395 397 //printf("\ttry later, forward reference of base %s\n", baseClass->toChars()); 396 scope = scx ? scx : new Scope(*sc); 397 scope->setNoFree(); 398 scope->module->addDeferredSemantic(this); 398 deferState = 2; 399 sc->module->addDeferredSemantic(this, sc); 399 400 return; 401 //throw new DeferException(loc, "forward reference of interface %s", baseClass->toChars()); 400 402 } 401 403 } 402 404 i++; … … 532 534 if (storage_class & STCabstract) 533 535 isabstract = 1; 534 536 537 structalign = 8; 538 if (baseClass) 539 { sc_offset = baseClass->structsize; 540 alignsize = baseClass->alignsize; 541 // if (isnested) 542 // sc->offset += PTRSIZE; // room for uplevel context pointer 543 } 544 else 545 { sc_offset = 8; // allow room for vptr[] and monitor 546 alignsize = 4; 547 } 548 structsize = sc_offset; 549 sizeok = 0; 550 551 case 3: 535 552 sc = sc->push(this); 536 553 sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic | 537 554 STCabstract | STCdeprecated); … … 543 560 sc->protection = PROTpublic; 544 561 sc->explicitProtection = 0; 545 562 sc->structalign = 8; 546 structalign = sc->structalign;547 if (baseClass)548 { sc->offset = baseClass->structsize;549 alignsize = baseClass->alignsize;550 // if (isnested)551 // sc->offset += PTRSIZE; // room for uplevel context pointer552 }553 else554 { sc->offset = 8; // allow room for vptr[] and monitor555 alignsize = 4;556 }557 structsize = sc->offset;558 Scope scsave = *sc;559 int members_dim = members->dim;560 sizeok = 0;561 for (i = 0; i < members_dim; i++)562 {563 Dsymbol *s = (Dsymbol *)members->data[i];564 s->semantic(sc);565 }566 563 567 if (sizeok == 2) 568 { // semantic() failed because of forward references. 569 // Unwind what we did, and defer it for later 570 fields.setDim(0); 571 structsize = 0; 572 alignsize = 0; 573 structalign = 0; 564 if (sc_offset >= 0) 565 sc->offset = sc_offset; 574 566 567 scsave = *sc; 568 569 try { 570 callSemanticOnMembers(sc); 571 } catch (DeferException* deferexc) { 572 sc_offset = sc->offset; 573 deferState = 3; 575 574 sc = sc->pop(); 576 577 scope = scx ? scx : new Scope(*sc); 578 scope->setNoFree(); 579 scope->module->addDeferredSemantic(this); 580 581 //printf("\tsemantic('%s') failed due to forward references\n", toChars()); 582 return; 575 throw deferexc; 583 576 } 584 577 585 578 //printf("\tsemantic('%s') successful\n", toChars()); … … 670 663 } 671 664 #endif 672 665 //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type); 666 667 deferState = -1; 668 case -1: 669 break; 670 default: 671 assert(0 && "deferState for classes must be between -1 and 3"); 672 } // switch for deferred calling 673 673 } 674 674 675 675 void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) … … 766 766 Dsymbol *s; 767 767 768 768 //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars()); 769 if (scope) 770 semantic(scope); 769 s = ScopeDsymbol::search(loc, ident, flags); 771 770 772 if (!members || !symtab || scope) 773 { error("is forward referenced when looking for '%s'", ident->toChars()); 774 //*(char*)0=0; 775 return NULL; 771 if (!s && (!members || !symtab || deferState > 0)) 772 { 773 throw new DeferException(loc, "%s is forward referenced when looking for '%s'", toChars(), ident->toChars()); 776 774 } 777 775 778 s = ScopeDsymbol::search(loc, ident, flags);779 776 if (!s) 780 777 { 781 778 // Search bases classes in depth-first, left to right order … … 987 984 988 985 void InterfaceDeclaration::semantic(Scope *sc) 989 986 { int i; 987 Scope *scx = NULL; 990 988 989 int continueAt = deferState; 990 if (deferState > 0) 991 deferState = 0; 992 switch (continueAt) { 993 case 0: 991 994 //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); 992 995 if (inuse) 993 996 return; 994 if (!scope) 995 {type = type->semantic(loc, sc);996 997 } 997 998 type = type->semantic(loc, sc); 999 handle = handle->semantic(loc, sc); 1000 998 1001 if (!members) // if forward reference 999 1002 { //printf("\tinterface '%s' is forward referenced\n", toChars()); 1000 1003 return; 1001 1004 } 1002 1005 if (symtab) // if already done 1003 { if (!scope)1004 1006 { 1007 return; 1005 1008 } 1006 1009 else 1007 1010 symtab = new DsymbolTable(); 1008 1009 Scope *scx = NULL;1010 if (scope)1011 { sc = scope;1012 scx = scope; // save so we don't make redundant copies1013 scope = NULL;1014 }1015 1011 1016 1012 if (sc->stc & STCdeprecated) 1017 1013 { … … 1039 1035 i++; 1040 1036 } 1041 1037 1038 case 1: 1042 1039 // Check for errors, handle forward references 1043 1040 for (i = 0; i < baseclasses.dim; ) 1044 1041 { TypeClass *tc; … … 1075 1072 baseclasses.remove(i); 1076 1073 continue; 1077 1074 } 1078 if (!b->base->symtab || b->base-> scope|| b->base->inuse)1075 if (!b->base->symtab || b->base->deferState > 0 || b->base->inuse) 1079 1076 { 1080 1077 //error("forward reference of base class %s", baseClass->toChars()); 1081 1078 // Forward reference of base, try again later 1082 1079 //printf("\ttry later, forward reference of base %s\n", b->base->toChars()); 1083 scope = scx ? scx : new Scope(*sc); 1084 scope->setNoFree(); 1085 scope->module->addDeferredSemantic(this); 1080 deferState = 1; 1081 sc->module->addDeferredSemantic(this, sc); 1086 1082 return; 1083 //throw new DeferException(loc, "forward reference of interface %s", baseClass->toChars()); 1087 1084 } 1088 1085 } 1089 1086 i++; … … 1133 1130 s->addMember(sc, this, 1); 1134 1131 } 1135 1132 1133 case 2: 1136 1134 sc = sc->push(this); 1137 1135 sc->parent = this; 1138 1136 if (isCOMinterface()) … … 1140 1138 sc->structalign = 8; 1141 1139 structalign = sc->structalign; 1142 1140 sc->offset = 8; 1141 if (sc_offset >= 0) 1142 sc->offset = sc_offset; 1143 1143 1144 inuse++; 1144 for (i = 0; i < members->dim; i++) 1145 { 1146 Dsymbol *s = (Dsymbol *)members->data[i]; 1147 s->semantic(sc); 1145 1146 try { 1147 callSemanticOnMembers(sc); 1148 } catch (DeferException* deferexc) { 1149 sc_offset = sc->offset; 1150 deferState = 2; 1151 sc = sc->pop(); 1152 inuse--; 1153 throw deferexc; 1148 1154 } 1155 1149 1156 inuse--; 1150 1157 //members->print(); 1151 1158 sc->pop(); 1152 1159 //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); 1160 deferState = -1; 1161 case -1: 1162 break; 1163 default: 1164 assert(0 && "deferState for interfaces must be between -1 and 2"); 1165 } // switch for deferStatus 1153 1166 } 1154 1167 1155 1168 -
a/dmd/declaration.c
old new 686 686 int inferred = 0; 687 687 if (!type) 688 688 { inuse++; 689 type = init->inferType(sc); 689 try { 690 type = init->inferType(sc); 691 } catch (DeferException* deferexc) { 692 inuse--; 693 throw deferexc; 694 } 690 695 inuse--; 691 696 inferred = 1; 692 697 … … 1007 1012 Expression *e; 1008 1013 Initializer *i2 = init; 1009 1014 inuse++; 1010 if (ei) 1011 { 1012 e = ei->exp->syntaxCopy(); 1013 e = e->semantic(sc); 1014 e = e->implicitCastTo(sc, type); 1015 } 1016 else if (si || ai) 1017 { i2 = init->syntaxCopy(); 1018 i2 = i2->semantic(sc, type); 1015 try { 1016 if (ei) 1017 { 1018 e = ei->exp->syntaxCopy(); 1019 e = e->semantic(sc); 1020 e = e->implicitCastTo(sc, type); 1021 } 1022 else if (si || ai) 1023 { i2 = init->syntaxCopy(); 1024 i2 = i2->semantic(sc, type); 1025 } 1026 } catch (DeferException* deferexc) { 1027 inuse--; 1028 global.gag--; 1029 throw deferexc; 1019 1030 } 1020 1031 inuse--; 1021 1032 global.gag--; -
a/dmd/dsymbol.c
old new 616 616 symtab = NULL; 617 617 imports = NULL; 618 618 prots = NULL; 619 member_semantic_started = false; 619 620 } 620 621 621 622 ScopeDsymbol::ScopeDsymbol(Identifier *id) … … 625 626 symtab = NULL; 626 627 imports = NULL; 627 628 prots = NULL; 629 member_semantic_started = false; 628 630 } 629 631 630 632 Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s) … … 737 739 } 738 740 } 739 741 } 740 imports->push(s); 741 prots = (unsigned char *)mem.realloc(prots, imports->dim * sizeof(prots[0])); 742 prots[imports->dim - 1] = protection; 742 bool in_imports = false; 743 for (int i = 0; i < imports->dim; ++i) 744 if (imports->data[i] == s) 745 in_imports = true; 746 if (!in_imports) 747 { 748 imports->push(s); 749 prots = (unsigned char *)mem.realloc(prots, imports->dim * sizeof(prots[0])); 750 prots[imports->dim - 1] = protection; 751 } 743 752 } 744 753 } 745 754 … … 805 814 const char *ScopeDsymbol::kind() 806 815 { 807 816 return "ScopeDsymbol"; 817 } 818 819 // shares code with AttribDeclaration::callSemanticOnMembers 820 void ScopeDsymbol::callSemanticOnMembers(Scope* sc) 821 { 822 // first add everything to remaining_semantic 823 if (!member_semantic_started) { 824 for (int i = 0; i < members->dim; i++) 825 remaining_semantic.push_back( (Dsymbol*)members->data[i] ); 826 member_semantic_started = true; 827 } 828 829 int failed = 0; 830 831 // last defer exception that was caught. stored for the error message inside 832 DeferException* lastdefer; 833 834 // if we deferred an order dependent member, save it here 835 // we will then skip all order dependent members until this is reached again 836 Dsymbol *deferredOrderDependent = NULL; 837 838 while (!remaining_semantic.empty() && failed != remaining_semantic.size()) 839 { Dsymbol *s; 840 s = remaining_semantic[0]; 841 remaining_semantic.pop_front(); 842 843 // if we deferred something order dependent, skip other 844 // order dependent ones for one iteration 845 if (deferredOrderDependent == s) 846 deferredOrderDependent = NULL; 847 if (deferredOrderDependent && !isMemberReorderable(s)) { 848 ++failed; 849 remaining_semantic.push_back(s); 850 continue; 851 } 852 853 try { 854 s->semantic(sc); 855 } catch (DeferException* deferexc) { 856 lastdefer = deferexc; 857 ++failed; 858 remaining_semantic.push_back(s); 859 if (!isMemberReorderable(s)) 860 deferredOrderDependent = s; 861 continue; 862 } 863 864 failed = 0; 865 postMemberSemantic(sc); 866 } 867 868 if (!remaining_semantic.empty()) 869 { 870 assert(lastdefer); 871 872 // reorder members into a valid state if necessary 873 if (deferredOrderDependent) 874 while (remaining_semantic[0] != deferredOrderDependent) { 875 Dsymbol* s = remaining_semantic[0]; 876 remaining_semantic.pop_front(); 877 remaining_semantic.push_back(s); 878 } 879 880 throw lastdefer; 881 } 808 882 } 809 883 810 884 … … 974 1048 return NULL; 975 1049 } 976 1050 977 978 1051 /****************************** DsymbolTable ******************************/ 979 1052 980 1053 DsymbolTable::DsymbolTable() -
a/dmd/dsymbol.h
old new 20 20 21 21 #include "mars.h" 22 22 #include "arraytypes.h" 23 #include <deque> 23 24 24 25 // llvm 25 26 #include "../ir/irsymbol.h" … … 251 252 void emitMemberComments(Scope *sc); 252 253 253 254 ScopeDsymbol *isScopeDsymbol() { return this; } 255 256 // LDC 257 std::deque<Dsymbol*> remaining_semantic; // Dsymbols where semantic remains to be called 258 bool member_semantic_started; 259 void callSemanticOnMembers(Scope* sc); 260 virtual void postMemberSemantic(Scope* sc) {} 261 virtual bool isMemberReorderable(Dsymbol* sym) { return true; } 254 262 }; 255 263 256 264 // With statement scope -
a/dmd/func.c
old new 324 324 break; 325 325 326 326 case -2: // can't determine because of fwd refs 327 cd->sizeok = 2; // can't finish due to forward reference 328 return; 327 throw new DeferException(loc, "cannot determine vtbl index of %s because of forward references", toChars()); 329 328 330 329 default: 331 330 { FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi]; … … 398 397 break; 399 398 400 399 case -2: 401 cd->sizeok = 2; // can't finish due to forward reference 402 return; 400 throw new DeferException(loc, "cannot determine vtbl index of %s because of forward references", toChars()); 403 401 404 402 default: 405 403 { FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi]; … … 494 492 } 495 493 if (cov == 3) 496 494 { 497 cd->sizeok = 2; // can't finish due to forward reference 498 return; 495 throw new DeferException(loc, "cannot finish due to forward reference"); 499 496 } 500 497 } 501 498 } -
a/dmd/import.c
old new 122 122 { 123 123 //printf("Import::semantic('%s')\n", toChars()); 124 124 125 load(sc); 125 DeferException* defer = NULL; 126 try { 127 load(sc); 128 } catch (DeferException* exc) { 129 defer = exc; 130 } 126 131 127 132 if (mod) 128 133 { … … 148 153 } 149 154 150 155 // Modules need a list of each imported module 151 sc->module->aimports.push(mod); 156 bool in_aimports = false; 157 for (int i = 0; i < sc->module->aimports.dim; ++i) 158 if (sc->module->aimports.data[i] == mod) 159 in_aimports = true; 160 if (!in_aimports) 161 sc->module->aimports.push(mod); 152 162 153 163 if (mod->needmoduleinfo) 154 164 sc->module->needmoduleinfo = 1; … … 166 176 } 167 177 sc = sc->pop(); 168 178 } 179 180 if (defer) 181 throw defer; 169 182 //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg); 170 183 } 171 184 -
a/dmd/mars.c
old new 1133 1133 m = (Module *)modules.data[i]; 1134 1134 if (global.params.verbose) 1135 1135 printf("semantic %s\n", m->toChars()); 1136 m->semantic(); 1136 try { 1137 m->semantic(); 1138 } catch (DeferException* deferexc) { 1139 error("Couldn't resolve error though deferring:\n%s", deferexc->errormessage); 1140 } 1137 1141 } 1138 1142 if (global.errors) 1139 1143 fatal(); -
a/dmd/module.c
old new 46 46 DsymbolTable *Module::modules; 47 47 Array Module::amodules; 48 48 49 ArrayModule::deferred; // deferred Dsymbol's needing semantic() run on them49 std::deque<DeferredDsymbol> Module::deferred; // deferred Dsymbol's needing semantic() run on them 50 50 unsigned Module::dprogress; 51 51 52 52 void Module::init() … … 126 126 llvmForceLogging = false; 127 127 this->doDocComment = doDocComment; 128 128 this->doHdrGen = doHdrGen; 129 sc = NULL; 129 130 } 130 131 131 132 File* Module::buildFilePath(char* forcename, char* path, char* ext) … … 616 617 void Module::semantic(Scope* unused_sc) 617 618 { int i; 618 619 619 if (semanticstarted) 620 // if already done or circular, bail out 621 if (semanticdone || semanticstarted == 1) 620 622 return; 621 623 622 //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); 623 semanticstarted = 1; 624 if (semanticstarted == 0) 625 { 626 //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); 627 semanticstarted = 1; 624 628 625 626 627 628 Scope *sc = Scope::createGlobal(this); // create root scope629 // Note that modules get their own scope, from scratch. 630 // This is so regardless of where in the syntax a module 631 // gets imported, it is unaffected by context. 632 sc = Scope::createGlobal(this); // create root scope 629 633 630 634 //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage); 631 635 632 633 634 635 Import *im = new Import(0, NULL, Id::object, NULL, 0);636 members->shift(im);637 636 // Add import of "object" if this module isn't "object" 637 if (ident != Id::object) 638 { 639 Import *im = new Import(0, NULL, Id::object, NULL, 0); 640 members->shift(im); 641 } 638 642 639 640 641 642 643 // Add all symbols into module's symbol table 644 symtab = new DsymbolTable(); 645 for (i = 0; i < members->dim; i++) 646 { Dsymbol *s; 643 647 644 s = (Dsymbol *)members->data[i]; 645 s->addMember(NULL, sc->scopesym, 1); 648 s = (Dsymbol *)members->data[i]; 649 s->addMember(NULL, sc->scopesym, 1); 650 } 646 651 } 647 652 648 653 // Pass 1 semantic routines: do public side of the definition 649 for (i = 0; i < members->dim; i++) 650 { Dsymbol *s; 651 652 s = (Dsymbol *)members->data[i]; 653 //printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars()); 654 s->semantic(sc); 655 runDeferredSemantic(); 654 try { 655 callSemanticOnMembers(sc); 656 } catch (DeferException* deferexc) { 657 semanticstarted = -1; 658 throw deferexc; 656 659 } 657 660 658 661 sc = sc->pop(); 659 662 sc->pop(); 660 semanticdone = semanticstarted; 663 semanticstarted = 1; 664 semanticdone = 1; 661 665 //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); 662 666 } 663 667 664 668 void Module::semantic2(Scope* unused_sc) 665 669 { int i; 666 670 667 if ( deferred.dim)671 if (!deferred.empty()) 668 672 { 669 for (int i = 0; i < deferred. dim; i++)673 for (int i = 0; i < deferred.size(); i++) 670 674 { 671 Dsymbol *sd = (Dsymbol *)deferred.data[i];675 Dsymbol *sd = deferred[i].sym; 672 676 673 677 sd->error("unable to resolve forward reference in definition"); 674 678 } … … 810 814 s = ScopeDsymbol::search(loc, ident, flags); 811 815 insearch = 0; 812 816 817 if (!s && semanticstarted == -1) 818 error("Forward reference!"); 819 813 820 searchCacheIdent = ident; 814 821 searchCacheSymbol = s; 815 822 searchCacheFlags = flags; … … 821 828 * Can't run semantic on s now, try again later. 822 829 */ 823 830 824 void Module::addDeferredSemantic(Dsymbol *s )831 void Module::addDeferredSemantic(Dsymbol *sym, Scope *scope) 825 832 { 826 833 // Don't add it if it is already there 827 for (int i = 0; i < deferred. dim; i++)834 for (int i = 0; i < deferred.size(); i++) 828 835 { 829 Dsymbol *sd = (Dsymbol *)deferred .data[i];836 Dsymbol *sd = (Dsymbol *)deferred[i].sym; 830 837 831 if (sd == s )838 if (sd == sym) 832 839 return; 833 840 } 834 841 842 // copy scope 843 Scope* scx = new Scope(*scope); 844 scx->setNoFree(); 845 835 846 //printf("Module::addDeferredSemantic('%s')\n", s->toChars()); 836 deferred.push (s);847 deferred.push_back(DeferredDsymbol(sym, scx)); 837 848 } 838 849 839 850 … … 843 854 844 855 void Module::runDeferredSemantic() 845 856 { 846 size_t len;857 //if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); 847 858 848 859 static int nested; 849 860 if (nested) 850 861 return; 851 //if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);852 862 nested++; 853 863 854 do 855 { 856 dprogress = 0; 857 len = deferred.dim; 858 if (!len) 859 break; 864 int failed = 0; 860 865 861 Dsymbol **todo; 862 Dsymbol *tmp; 863 if (len == 1) 864 { 865 todo = &tmp; 866 // last defer exception that was caught. stored for the error message inside 867 DeferException* lastdefer; 868 869 // if we deferred an order dependent member, save it here 870 // we will then skip all order dependent members until this is reached again 871 Dsymbol *deferredOrderDependent = NULL; 872 873 while (!deferred.empty() && failed != deferred.size()) 874 { Dsymbol *s; 875 Scope *sc; 876 s = deferred[0].sym; 877 sc = deferred[0].scope; 878 deferred.pop_front(); 879 880 // if we deferred something order dependent, skip other 881 // order dependent ones for one iteration 882 if (deferredOrderDependent == s) 883 deferredOrderDependent = NULL; 884 if (deferredOrderDependent && !isMemberReorderable(s)) { 885 ++failed; 886 deferred.push_back(DeferredDsymbol(s, sc)); 887 continue; 866 888 } 867 else 868 { 869 todo = (Dsymbol **)alloca(len * sizeof(Dsymbol *)); 870 assert(todo); 889 890 try { 891 s->semantic(sc); 892 if (!deferred.empty() && deferred.rbegin()->sym == s) 893 ++failed; 894 else 895 failed = 0; 896 } catch (DeferException* deferexc) { 897 lastdefer = deferexc; 898 ++failed; 899 deferred.push_back(DeferredDsymbol(s, sc)); 900 if (!isMemberReorderable(s)) 901 deferredOrderDependent = s; 902 continue; 871 903 } 872 memcpy(todo, deferred.data, len * sizeof(Dsymbol *)); 873 deferred.setDim(0); 904 } 874 905 875 for (int i = 0; i < len; i++)876 {877 Dsymbol *s = todo[i];878 879 s->semantic(NULL);880 //printf("deferred: %s, parent = %s\n", s->toChars(), s->parent->toChars());881 }882 //printf("\tdeferred.dim = %d, len = %d, dprogress = %d\n", deferred.dim, len, dprogress);883 } while (deferred.dim < len || dprogress); // while making progress884 906 nested--; 885 907 //printf("-Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); 886 908 } -
a/dmd/module.h
old new 17 17 18 18 #include "root.h" 19 19 #include "dsymbol.h" 20 #include <deque> 20 21 21 22 struct ModuleInfoDeclaration; 22 23 struct ClassDeclaration; … … 38 39 #endif 39 40 #endif 40 41 42 // The global list of out-of-order deferred Dsymbols 43 // contains elements of this type. In addition to the 44 // Dsymbol, they hold the scope that's to be used for 45 // the deferred semantic call. 46 struct DeferredDsymbol 47 { 48 DeferredDsymbol(Dsymbol* sym_, Scope* scope_) 49 : sym(sym_), scope(scope_) {} 50 51 Dsymbol* sym; 52 Scope* scope; 53 }; 54 41 55 struct Package : ScopeDsymbol 42 56 { 43 57 Package(Identifier *ident); … … 55 69 static Module *rootModule; 56 70 static DsymbolTable *modules; // symbol table of all modules 57 71 static Array amodules; // array of all modules 58 static Arraydeferred; // deferred Dsymbol's needing semantic() run on them72 static std::deque<DeferredDsymbol> deferred; // deferred Dsymbol's needing semantic() run on them 59 73 static unsigned dprogress; // progress resolving the deferred list 60 74 static void init(); 61 75 … … 139 153 int needModuleInfo(); 140 154 Dsymbol *search(Loc loc, Identifier *ident, int flags); 141 155 void deleteObjFile(); 142 void addDeferredSemantic(Dsymbol *s );156 void addDeferredSemantic(Dsymbol *sym, Scope* scope); 143 157 void runDeferredSemantic(); 144 158 145 159 // Back end … … 178 192 179 193 // array ops emitted in this module already 180 194 StringTable arrayfuncs; 195 196 // LDC 197 virtual void postMemberSemantic(Scope* sc) { runDeferredSemantic(); } 198 Scope* sc; 181 199 }; 182 200 183 201 -
a/dmd/mtype.c
old new 3913 3913 #ifdef DEBUG 3914 3914 printf("2: "); 3915 3915 #endif 3916 error(sym->loc, "enum %s is forward referenced", sym->toChars()); 3916 //error(sym->loc, "enum %s is forward referenced", sym->toChars()); 3917 throw new DeferException(sym->loc, "enum %s is forward referenced", sym->toChars()); 3917 3918 return tint32; 3918 3919 } 3919 3920 return sym->memtype->toBasetype(); … … 4585 4586 Type *TypeClass::semantic(Loc loc, Scope *sc) 4586 4587 { 4587 4588 //printf("TypeClass::semantic(%s)\n", sym->toChars()); 4588 if (sym->scope)4589 sym->semantic(sym->scope);4590 4589 return merge(); 4591 4590 } 4592 4591 -
a/dmd/root.c
old new 142 142 exit(EXIT_FAILURE); 143 143 } 144 144 #endif 145 146 DeferException::DeferException(Loc& loc, const char* format, ...) 147 { 148 errormessage = (char *)mem.malloc(200); 149 va_list ap; 150 151 va_start(ap, format); 152 size_t n = snprintf(errormessage, 200, "%s: ", loc.toChars()); 153 vsnprintf(errormessage+n, 200-n, format, ap); 154 va_end( ap ); 155 156 //warning("Avoided a forward reference error:\n %s\n This might not be safe. If you run into issues, this may be the cause!", errormessage); 157 } 145 158 146 159 void error_mem() 147 160 { -
a/dmd/root.h
old new 32 32 void error(const char *format, ...); 33 33 void error(const wchar_t *format, ...); 34 34 void warning(const char *format, ...); 35 36 struct Loc; 37 38 // Thrown when deferring the current Dsymbol is desired. 39 // Hopes to eventually transfer control to 40 // ScopeDsymbol/AnonDecl::callSemanticOnMembers, which will 41 // reschedule the Dsymbol to have semantic() run after other 42 // members have completed theirs. 43 struct DeferException 44 { 45 char* errormessage; 46 DeferException(Loc& loc, const char* format, ...); 47 }; 35 48 36 49 #ifndef TYPEDEFS 37 50 #define TYPEDEFS -
a/dmd/struct.c
old new 43 43 44 44 stag = NULL; 45 45 sinit = NULL; 46 scope = NULL; 46 47 sc_offset = -1; 47 48 } 48 49 49 50 enum PROT AggregateDeclaration::prot() … … 54 55 void AggregateDeclaration::semantic2(Scope *sc) 55 56 { 56 57 //printf("AggregateDeclaration::semantic2(%s)\n", toChars()); 57 if (scope)58 { error("has forward references");59 return;60 }61 58 if (members) 62 59 { 63 60 sc = sc->push(this); … … 171 168 172 169 if (ts->sym->sizeok != 1) 173 170 { 174 sizeok = 2; // cannot finish; flag as forward referenced175 return;171 sizeok = 2; 172 throw new DeferException(v->loc, "forward reference to struct %s", v->toChars()); 176 173 } 177 174 } 178 175 if (t->ty == Tident) 179 176 { 180 sizeok = 2; // cannot finish; flag as forward referenced181 return;177 sizeok = 2; 178 throw new DeferException(v->loc, "forward reference to %s", v->toChars()); 182 179 } 183 180 184 181 memsize = v->type->size(loc); … … 210 207 211 208 // For forward references 212 209 type = new TypeStruct(this); 210 211 // LDC 212 deferState = 0; 213 213 } 214 214 215 215 Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s) … … 227 227 void StructDeclaration::semantic(Scope *sc) 228 228 { int i; 229 229 Scope *sc2; 230 230 Identifier* id; 231 Scope *scx = NULL; 231 232 //printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars()); 232 233 233 234 //static int count; if (++count == 20) *(char*)0=0; 234 235 236 int continueAt = deferState; 237 if (deferState > 0) 238 deferState = 0; 239 switch (continueAt) { 240 case 0: 235 241 assert(type); 236 242 if (!members) // if forward reference 237 243 return; 238 244 239 245 if (symtab) 240 { if (!scope)241 246 { 247 return; // semantic() already completed 242 248 } 243 249 else 244 250 symtab = new DsymbolTable(); 245 246 Scope *scx = NULL;247 if (scope)248 { sc = scope;249 scx = scope; // save so we don't make redundant copies250 scope = NULL;251 }252 251 253 252 parent = sc->parent; 254 253 handle = type->pointerTo(); … … 270 269 } 271 270 } 272 271 272 case 1: 273 273 sizeok = 0; 274 274 sc2 = sc->push(this); 275 275 sc2->stc = 0; … … 279 279 sc2->protection = PROTpublic; 280 280 sc2->explicitProtection = 0; 281 281 282 int members_dim = members->dim; 283 for (i = 0; i < members_dim; i++) 284 { 285 Dsymbol *s = (Dsymbol *)members->data[i]; 286 s->semantic(sc2); 287 if (isUnionDeclaration()) 288 sc2->offset = 0; 289 #if 0 290 if (sizeok == 2) 291 { //printf("forward reference\n"); 292 break; 282 if (sc_offset >= 0) 283 sc2->offset = sc_offset; 284 285 try { 286 callSemanticOnMembers(sc2); 287 } catch (DeferException* deferexc) { 288 sc_offset = sc2->offset; 289 deferState = 1; 290 sc2->pop(); 291 if (sizeok == 2) { 292 sc->module->addDeferredSemantic(this, sc); 293 return; 293 294 } 294 #endif 295 else 296 throw deferexc; 295 297 } 296 297 298 /* The TypeInfo_Struct is expecting an opEquals and opCmp with 298 299 * a parameter that is a pointer to the struct. But if there 299 300 * isn't one, but is an opEquals or opCmp with a value, write … … 321 322 tfeq = (TypeFunction *)tfeq->semantic(0, sc); 322 323 } 323 324 324 Identifier *id = Id::eq;325 for (i nt i= 0; i < 2; i++)325 id = Id::eq; 326 for (i = 0; i < 2; i++) 326 327 { 327 328 Dsymbol *s = search_function(this, id); 328 329 FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL; … … 354 355 355 356 356 357 sc2->pop(); 357 358 if (sizeok == 2)359 { // semantic() failed because of forward references.360 // Unwind what we did, and defer it for later361 fields.setDim(0);362 structsize = 0;363 alignsize = 0;364 structalign = 0;365 366 scope = scx ? scx : new Scope(*sc);367 scope->setNoFree();368 scope->module->addDeferredSemantic(this);369 //printf("\tdeferring %s\n", toChars());370 return;371 }372 358 373 359 // 0 sized struct's are set to 1 byte 374 360 if (structsize == 0) … … 423 409 semantic2(sc); 424 410 semantic3(sc); 425 411 } 412 deferState = -1; 413 case -1: 414 break; 415 default: 416 assert(0 && "deferState for structs must be between -1 and 1"); 417 } // switch for deferring 426 418 } 427 419 428 420 void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) … … 457 449 return "struct"; 458 450 } 459 451 452 Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags) 453 { 454 Dsymbol *s; 455 456 //printf("%s.StructDeclaration::search('%s')\n", toChars(), ident->toChars()); 457 458 s = ScopeDsymbol::search(loc, ident, flags); 459 460 if (!s && (!members || !symtab || deferState > 0)) 461 { 462 throw new DeferException(loc, "%s is forward referenced when looking for '%s'", toChars(), ident->toChars()); 463 } 464 return s; 465 } 466 467 bool StructDeclaration::isMemberReorderable(Dsymbol* s) 468 { 469 if ( 470 s->isVarDeclaration() || 471 s->isAttribDeclaration() 472 ) 473 return false; 474 return true; 475 } 476 460 477 /********************************* UnionDeclaration ****************************/ 461 478 462 479 UnionDeclaration::UnionDeclaration(Loc loc, Identifier *id) … … 482 499 return "union"; 483 500 } 484 501 485 502 void UnionDeclaration::postMemberSemantic(Scope* sc) 503 { 504 sc->offset = 0; 505 } -
a/dmd/template.c
old new 2776 2776 this->isnested = NULL; 2777 2777 this->errors = 0; 2778 2778 this->tinst = NULL; 2779 this->deferState = 0; 2779 2780 } 2780 2781 2781 2782 … … 2800 2801 this->isnested = NULL; 2801 2802 this->errors = 0; 2802 2803 this->tinst = NULL; 2804 this->deferState = 0; 2803 2805 2804 2806 assert((size_t)tempdecl->scope > 0x10000); 2805 2807 } … … 2846 2848 2847 2849 void TemplateInstance::semantic(Scope *sc) 2848 2850 { 2851 int memnum = 0; 2852 int dosemantic3 = 0; 2853 unsigned errorsave; 2854 int tempdecl_instance_idx; 2855 2856 int continueAt = deferState; 2857 if (deferState > 0) 2858 deferState = 0; 2859 switch (continueAt) { 2860 case 0: 2849 2861 if (global.errors) 2850 2862 { 2851 2863 if (!global.gag) … … 2900 2912 semanticTiargs(sc); 2901 2913 2902 2914 tempdecl = findTemplateDeclaration(sc); 2903 if (tempdecl) 2904 tempdecl = findBestMatch(sc); 2915 if (tempdecl) { 2916 try { 2917 tempdecl = findBestMatch(sc); 2918 } catch(DeferException* deferexc) { 2919 semanticdone = 0; 2920 throw deferexc; 2921 } 2922 } 2905 2923 if (!tempdecl || global.errors) 2906 2924 { inst = this; 2907 2925 //printf("error return %p, %d\n", tempdecl, global.errors); … … 2954 2972 #if LOG 2955 2973 printf("\timplement template instance '%s'\n", toChars()); 2956 2974 #endif 2957 unsignederrorsave = global.errors;2975 errorsave = global.errors; 2958 2976 inst = this; 2959 inttempdecl_instance_idx = tempdecl->instances.dim;2977 tempdecl_instance_idx = tempdecl->instances.dim; 2960 2978 tempdecl->instances.push(this); 2961 2979 parent = tempdecl->parent; 2962 2980 //printf("parent = '%s'\n", parent->kind()); … … 2972 2990 // Add 'this' to the enclosing scope's members[] so the semantic routines 2973 2991 // will get called on the instance members 2974 2992 #if 1 2975 int dosemantic3 = 0;2976 2993 { Array *a; 2977 2994 int i; 2978 2995 … … 3004 3021 // Copy the syntax trees from the TemplateDeclaration 3005 3022 members = Dsymbol::arraySyntaxCopy(tempdecl->members); 3006 3023 3024 case 1: 3025 semanticdone = 1; 3007 3026 // Create our own scope for the template parameters 3008 Scope *scope = tempdecl->scope;3027 scope = tempdecl->scope; 3009 3028 if (!scope) 3010 3029 { 3011 error("forward reference to template declaration %s\n", tempdecl->toChars()); 3012 return; 3030 semanticdone = 0; 3031 deferState = 1; 3032 throw new DeferException(loc, "forward reference to template declaration %s\n", tempdecl->toChars()); 3013 3033 } 3014 3034 3015 3035 #if LOG … … 3025 3045 // Add members of template instance to template instance symbol table 3026 3046 // parent = scope->scopesym; 3027 3047 symtab = new DsymbolTable(); 3028 int memnum = 0;3029 3048 for (int i = 0; i < members->dim; i++) 3030 3049 { 3031 3050 Dsymbol *s = (Dsymbol *)members->data[i]; … … 3063 3082 #if LOG 3064 3083 printf("\tdo semantic() on template instance members '%s'\n", toChars()); 3065 3084 #endif 3066 Scope *sc2;3067 3085 sc2 = scope->push(this); 3068 3086 //printf("isnested = %d, sc->parent = %s\n", isnested, sc->parent->toChars()); 3069 3087 sc2->parent = /*isnested ? sc->parent :*/ this; 3070 3088 sc2->tinst = this; 3071 3089 3072 #if !IN_LLVM 3073 #if _WIN32 3074 __try 3075 { 3076 #endif 3077 #endif 3078 for (int i = 0; i < members->dim; i++) 3079 { 3080 Dsymbol *s = (Dsymbol *)members->data[i]; 3081 //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars()); 3082 //printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars()); 3083 // if (isnested) 3084 // s->parent = sc->parent; 3085 //printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); 3086 s->semantic(sc2); 3087 //printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); 3088 sc2->module->runDeferredSemantic(); 3089 } 3090 #if !IN_LLVM 3091 #if _WIN32 3092 } 3093 __except (__ehfilter(GetExceptionInformation())) 3094 { 3095 global.gag = 0; // ensure error message gets printed 3096 error("recursive expansion"); 3097 fatal(); 3098 } 3099 #endif 3100 #endif 3090 case 2: 3091 semanticdone = 1; 3092 try { 3093 callSemanticOnMembers(sc2); 3094 } catch (DeferException* deferexc) { 3095 deferState = 2; 3096 semanticdone = 0; 3097 throw deferexc; 3098 } 3101 3099 3102 3100 /* If any of the instantiation members didn't get semantic() run 3103 3101 * on them due to forward references, we cannot run semantic2() 3104 3102 * or semantic3() yet. 3105 3103 */ 3106 for (size_t i = 0; i < Module::deferred. dim; i++)3107 { Dsymbol *sd = (Dsymbol *)Module::deferred .data[i];3104 for (size_t i = 0; i < Module::deferred.size(); i++) 3105 { Dsymbol *sd = (Dsymbol *)Module::deferred[i].sym; 3108 3106 3109 3107 if (sd->parent == this) 3110 3108 goto Laftersemantic; … … 3146 3144 #if LOG 3147 3145 printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); 3148 3146 #endif 3147 3148 deferState = -1; 3149 case -1: 3150 break; 3151 default: 3152 assert(0 && "deferState for template instances must be between -1 and 2"); 3153 } // switch for deferring 3149 3154 } 3150 3155 3151 3156 … … 3391 3396 dedtypes.zero(); 3392 3397 if (!td->scope) 3393 3398 { 3394 error("forward reference to template declaration %s", td->toChars()); 3395 return NULL; 3399 throw new DeferException(loc, "forward reference to template declaration %s", td->toChars()); 3396 3400 } 3397 3401 m = td->matchWithInstance(this, &dedtypes, 0); 3398 3402 //printf("m = %d\n", m); … … 3884 3888 } 3885 3889 } 3886 3890 3891 void TemplateInstance::postMemberSemantic(Scope *sc) 3892 { 3893 sc->module->runDeferredSemantic(); 3894 } 3895 3887 3896 /* ======================== TemplateMixin ================================ */ 3888 3897 3889 3898 TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual, … … 3896 3905 this->idents = idents; 3897 3906 this->tiargs = tiargs ? tiargs : new Objects(); 3898 3907 this->scope = NULL; 3908 this->deferState = 0; 3899 3909 } 3900 3910 3901 3911 Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s) … … 3925 3935 3926 3936 void TemplateMixin::semantic(Scope *sc) 3927 3937 { 3938 unsigned errorsave; 3939 3940 int continueAt = deferState; 3941 if (deferState > 0) 3942 deferState = 0; 3943 switch (continueAt) { 3944 case 0: 3945 3928 3946 #if LOG 3929 3947 printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this); 3930 3948 fflush(stdout); … … 3950 3968 util_progress(); 3951 3969 #endif 3952 3970 3953 Scope *scx = NULL;3971 scx = NULL; 3954 3972 if (scope) 3955 3973 { sc = scope; 3956 3974 scx = scope; // save so we don't make redundant copies … … 4025 4043 */ 4026 4044 semanticdone = 0; 4027 4045 AggregateDeclaration *ad = toParent()->isAggregateDeclaration(); 4028 if (ad) 4029 ad->sizeok = 2; 4030 else 4031 { 4032 // Forward reference 4033 //printf("forward reference - deferring\n"); 4034 scope = scx ? scx : new Scope(*sc); 4035 scope->setNoFree(); 4036 scope->module->addDeferredSemantic(this); 4037 } 4038 return; 4046 4047 // Forward reference 4048 //printf("forward reference - deferring\n"); 4049 //scope = scx ? scx : new Scope(*sc); 4050 //scope->setNoFree(); 4051 //scope->module->addDeferredSemantic(this); 4052 throw new DeferException(loc, "%s at %s is forward referenced", td->toChars(), td->loc.toChars()); 4039 4053 } 4040 4054 } 4041 4055 … … 4123 4137 #if LOG 4124 4138 printf("\tcreate scope for template parameters '%s'\n", toChars()); 4125 4139 #endif 4126 Scope *scy = sc;4140 scy = sc; 4127 4141 scy = sc->push(this); 4128 4142 scy->parent = this; 4129 4143 4130 4144 argsym = new ScopeDsymbol(); 4131 4145 argsym->parent = scy->parent; 4132 Scope *scope = scy->push(argsym);4133 4134 unsignederrorsave = global.errors;4146 scope = scy->push(argsym); 4147 4148 errorsave = global.errors; 4135 4149 4136 4150 // Declare each template parameter as an alias for the argument type 4137 4151 declareParameters(scope); … … 4151 4165 #if LOG 4152 4166 printf("\tdo semantic() on template instance members '%s'\n", toChars()); 4153 4167 #endif 4154 Scope *sc2;4155 4168 sc2 = scope->push(this); 4156 4169 sc2->offset = sc->offset; 4157 for (int i = 0; i < members->dim; i++) 4158 { 4159 Dsymbol *s = (Dsymbol *)members->data[i]; 4160 s->semantic(sc2); 4170 4171 case 1: 4172 try { 4173 callSemanticOnMembers(sc2); 4174 } catch (DeferException* deferexc) { 4175 deferState = 1; 4176 semanticdone = 0; 4177 throw deferexc; 4161 4178 } 4162 4179 sc->offset = sc2->offset; 4180 4181 /* If any of the instantiation members didn't get semantic() run 4182 * on them due to forward references, error! 4183 */ 4184 for (size_t i = 0; i < Module::deferred.size(); i++) 4185 { Dsymbol *sd = (Dsymbol *)Module::deferred[i].sym; 4186 4187 if (sd->parent == this) 4188 error("semantic failed due to forward references in %s", sd->toPrettyChars()); 4189 } 4163 4190 4164 4191 /* The problem is when to parse the initializer for a variable. 4165 4192 * Perhaps VarDeclaration::semantic() should do it like it does … … 4191 4218 #if LOG 4192 4219 printf("-TemplateMixin::semantic('%s', this=%p)\n", toChars(), this); 4193 4220 #endif 4221 4222 deferState = -1; 4223 case -1: 4224 break; 4225 default: 4226 assert(0 && "deferState for template mixins must be between -1 and 1"); 4227 } // switch for deferring 4194 4228 } 4195 4229 4196 4230 void TemplateMixin::semantic2(Scope *sc) -
a/dmd/template.h
old new 316 316 AliasDeclaration *isAliasDeclaration(); 317 317 318 318 // LDC 319 void postMemberSemantic(Scope* sc); 319 320 TemplateInstance *tinst; // enclosing template instance 320 321 void printInstantiationTrace(); 322 int deferState; 323 Scope *sc2; 324 Scope *scope; 321 325 }; 322 326 323 327 struct TemplateMixin : TemplateInstance … … 343 347 void toObjFile(int multiobj); // compile to .obj file 344 348 345 349 TemplateMixin *isTemplateMixin() { return this; } 350 351 // LDC 352 int deferState; 353 Scope *sc2, *scy, *scx; 346 354 }; 347 355 348 356 Expression *isExpression(Object *o);