Ticket #125: forwardref-965.diff
File forwardref-965.diff, 51.5 kB (added by ChristianK, 15 years ago) |
---|
-
a/dmd/aggregate.h
old new 62 62 // 1: size is correct 63 63 // 2: cannot determine size; fwd referenced 64 64 int isdeprecated; // !=0 if deprecated 65 Scope *scope; // !=NULL means context to use66 65 67 66 // Special member functions 68 67 InvariantDeclaration *inv; // invariant … … 104 103 Symbol *toInitializer(); 105 104 106 105 AggregateDeclaration *isAggregateDeclaration() { return this; } 106 107 // LDC 108 int sc_offset; // saved next offset in aggregate 107 109 }; 108 110 109 111 struct AnonymousAggregateDeclaration : AggregateDeclaration … … 131 133 Dsymbol *syntaxCopy(Dsymbol *s); 132 134 void semantic(Scope *sc); 133 135 void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 136 137 //LDC, override to allow searching in partially semantic'ed structs 138 Dsymbol *search(Loc, Identifier *ident, int flags); 139 140 //LDC, for deferring 141 int deferState; 142 virtual bool isMemberReorderable(Dsymbol* s); 143 134 144 char *mangle(); 135 145 const char *kind(); 136 146 Expression *cloneMembers(); … … 152 162 const char *kind(); 153 163 154 164 UnionDeclaration *isUnionDeclaration() { return this; } 165 166 // LDC, overload to reset offset to zero after each member 167 virtual void postMemberSemantic(Scope* sc); 155 168 }; 156 169 157 170 // warning: two classes with the same base class share the same … … 216 229 VarDeclaration *vthis; // 'this' parameter if this class is nested 217 230 218 231 int inuse; // to prevent recursive attempts 232 233 //LDC, for deferring 234 int deferState; 219 235 220 236 ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses); 221 237 Dsymbol *syntaxCopy(Dsymbol *s); -
a/dmd/attrib.c
old new 43 43 : Dsymbol() 44 44 { 45 45 this->decl = decl; 46 member_semantic_started = false; 47 included_decls = NULL; 46 48 } 47 49 48 50 Array *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd) … … 65 67 return m; 66 68 } 67 69 70 // shares code with ScopeDsymbol::callSemanticOnMembers 71 void AttribDeclaration::callSemanticOnMembers(Scope* sc, Array* members) 72 { 73 if (!members) 74 return; 75 76 // first add everything to remaining_semantic 77 if (!member_semantic_started) { 78 for (int i = 0; i < members->dim; i++) 79 remaining_semantic.push_back( (Dsymbol*)members->data[i] ); 80 member_semantic_started = true; 81 } 82 83 int failed = 0; 84 85 // last defer exception that was caught. stored for the error message inside 86 DeferException* lastdefer; 87 88 // if we deferred an order dependent member, save it here 89 // we will then skip all order dependent members until this is reached again 90 Dsymbol *deferredOrderDependent = NULL; 91 92 while (!remaining_semantic.empty() && failed != remaining_semantic.size()) 93 { Dsymbol *s; 94 s = remaining_semantic[0]; 95 remaining_semantic.pop_front(); 96 97 // if we deferred something order dependent, skip other 98 // order dependent ones for one iteration 99 if (deferredOrderDependent == s) 100 deferredOrderDependent = NULL; 101 if (deferredOrderDependent && !isMemberReorderable(s)) { 102 ++failed; 103 remaining_semantic.push_back(s); 104 continue; 105 } 106 107 try { 108 runSemantic(s, sc); 109 } catch (DeferException* deferexc) { 110 lastdefer = deferexc; 111 ++failed; 112 remaining_semantic.push_back(s); 113 if (!isMemberReorderable(s)) 114 deferredOrderDependent = s; 115 continue; 116 } 117 118 failed = 0; 119 postMemberSemantic(sc); 120 } 121 122 if (!remaining_semantic.empty()) 123 { 124 assert(lastdefer); 125 126 // reorder members into a valid state if necessary 127 if (deferredOrderDependent) 128 while (remaining_semantic[0] != deferredOrderDependent) { 129 Dsymbol* s = remaining_semantic[0]; 130 remaining_semantic.pop_front(); 131 remaining_semantic.push_back(s); 132 } 133 134 throw lastdefer; 135 } 136 } 137 68 138 void AttribDeclaration::semantic(Scope *sc) 69 139 { 70 Array *d = include(sc, NULL); 140 if (!included_decls) 141 included_decls = include(sc, NULL); 71 142 72 143 //printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d); 73 if (d) 74 { 75 for (unsigned i = 0; i < d->dim; i++) 76 { 77 Dsymbol *s = (Dsymbol *)d->data[i]; 78 79 s->semantic(sc); 80 } 81 } 144 callSemanticOnMembers(sc, included_decls); 82 145 } 83 146 84 147 void AttribDeclaration::semantic2(Scope *sc) … … 290 353 if (stc & (STCauto | STCscope | STCstatic | STCextern)) 291 354 sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern); 292 355 sc->stc |= stc; 293 for (unsigned i = 0; i < decl->dim; i++) 294 { 295 Dsymbol *s = (Dsymbol *)decl->data[i]; 296 297 s->semantic(sc); 298 } 356 callSemanticOnMembers(sc, decl); 299 357 sc->stc = stc_save; 300 358 } 301 359 else … … 364 422 { enum LINK linkage_save = sc->linkage; 365 423 366 424 sc->linkage = linkage; 367 for (unsigned i = 0; i < decl->dim; i++) 368 { 369 Dsymbol *s = (Dsymbol *)decl->data[i]; 370 371 s->semantic(sc); 372 } 425 callSemanticOnMembers(sc, decl); 373 426 sc->linkage = linkage_save; 374 427 } 375 428 else … … 454 507 455 508 sc->protection = protection; 456 509 sc->explicitProtection = 1; 457 for (unsigned i = 0; i < decl->dim; i++) 458 { 459 Dsymbol *s = (Dsymbol *)decl->data[i]; 460 461 s->semantic(sc); 462 } 510 callSemanticOnMembers(sc, decl); 463 511 sc->protection = protection_save; 464 512 sc->explicitProtection = explicitProtection_save; 465 513 } … … 513 561 514 562 //printf("\tAlignDeclaration::semantic '%s'\n",toChars()); 515 563 if (decl) 516 { unsigned salign_save = sc->structalign; 517 518 for (unsigned i = 0; i < decl->dim; i++) 519 { 520 Dsymbol *s = (Dsymbol *)decl->data[i]; 521 522 if (s->isStructDeclaration() && salign == 1) 523 { 524 sc->structalign = salign; 525 s->semantic(sc); 526 sc->structalign = salign_save; 527 } 528 else 529 { 530 s->semantic(sc); 531 } 532 } 533 sc->structalign = salign_save; 564 { 565 callSemanticOnMembers(sc, decl); 534 566 } 535 567 else 536 568 assert(0 && "what kind of align use triggers this?"); 537 569 } 538 570 571 void AlignDeclaration::runSemantic(Dsymbol* s, Scope* sc) 572 { 573 unsigned salign_save = sc->structalign; 574 575 if (s->isStructDeclaration() && salign == 1) 576 { 577 sc->structalign = salign; 578 s->semantic(sc); 579 sc->structalign = salign_save; 580 } 581 else 582 { 583 s->semantic(sc); 584 } 585 } 539 586 540 587 void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 541 588 { … … 550 597 { 551 598 this->loc = loc; 552 599 this->isunion = isunion; 553 this->scope = NULL;554 600 this->sem = 0; 601 602 sc_offset = -1; 555 603 } 556 604 557 605 Dsymbol *AnonDeclaration::syntaxCopy(Dsymbol *s) … … 563 611 return ad; 564 612 } 565 613 614 // copied from StructDeclaration::isMemberReorderable 615 bool AnonDeclaration::isMemberReorderable(Dsymbol* s) 616 { 617 if ( 618 s->isVarDeclaration() || 619 s->isAttribDeclaration() 620 ) 621 return false; 622 return true; 623 } 624 625 void AnonDeclaration::postMemberSemantic(Scope* sc) 626 { 627 if (isunion) 628 sc->offset = 0; 629 } 630 566 631 void AnonDeclaration::semantic(Scope *sc) 567 632 { 568 633 //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this); 569 570 Scope *scx = NULL;571 if (scope)572 { sc = scope;573 scx = scope;574 scope = NULL;575 }576 634 577 635 assert(sc->parent); 578 636 … … 587 645 588 646 if (decl) 589 647 { 590 AnonymousAggregateDeclaration aad;591 648 int adisunion; 592 649 593 650 if (sc->anonAgg) … … 606 663 sc->stc &= ~(STCauto | STCscope | STCstatic); 607 664 sc->inunion = isunion; 608 665 sc->offset = 0; 666 if (sc_offset >= 0) 667 sc->offset = sc_offset; 668 609 669 sc->flags = 0; 610 670 aad.structalign = sc->structalign; 611 671 aad.parent = ad; 612 672 613 for (unsigned i = 0; i < decl->dim; i++) 614 { 615 Dsymbol *s = (Dsymbol *)decl->data[i]; 616 617 s->semantic(sc); 618 if (isunion) 619 sc->offset = 0; 620 if (aad.sizeok == 2) 621 { 622 break; 623 } 673 try { 674 callSemanticOnMembers(sc, decl); 675 } catch (DeferException* deferexc) { 676 sc_offset = sc->offset; 677 sc->pop(); 678 throw deferexc; 624 679 } 680 625 681 sc = sc->pop(); 626 682 627 // If failed due to forward references, unwind and try again later628 if (aad.sizeok == 2)629 {630 ad->sizeok = 2;631 //printf("\tsetting ad->sizeok %p to 2\n", ad);632 if (!sc->anonAgg)633 {634 scope = scx ? scx : new Scope(*sc);635 scope->setNoFree();636 scope->module->addDeferredSemantic(this);637 }638 //printf("\tforward reference %p\n", this);639 return;640 }641 683 if (sem == 0) 642 684 { Module::dprogress++; 643 685 sem = 1; … … 1338 1380 1339 1381 void StaticIfDeclaration::semantic(Scope *sc) 1340 1382 { 1341 Array *d = include(sc, sd); 1383 if (!included_decls) 1384 included_decls = include(sc, sd); 1342 1385 1343 1386 //printf("\tStaticIfDeclaration::semantic '%s', d = %p\n",toChars(), d); 1344 if ( d)1387 if (included_decls) 1345 1388 { 1346 1389 if (!addisdone) 1347 1390 { AttribDeclaration::addMember(sc, sd, 1); 1348 1391 addisdone = 1; 1349 1392 } 1350 1393 1351 for (unsigned i = 0; i < d->dim; i++) 1352 { 1353 Dsymbol *s = (Dsymbol *)d->data[i]; 1354 1355 s->semantic(sc); 1356 } 1394 callSemanticOnMembers(sc, included_decls); 1357 1395 } 1358 1396 } 1359 1397 -
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 virtual 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); … … 110 122 111 123 // LDC 112 124 void toObjFile(int multiobj); // compile to .obj file 125 126 void postMemberSemantic(Scope* sc); 127 bool isMemberReorderable(Dsymbol* sym); 128 int sc_offset; // saved next offset in aggregate 129 AnonymousAggregateDeclaration aad; 113 130 }; 114 131 115 132 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 = 2*PTRSIZE; // allow room for vptr[] and monitor 546 alignsize = PTRSIZE; 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); … … 552 569 sc->protection = PROTpublic; 553 570 sc->explicitProtection = 0; 554 571 sc->structalign = 8; 555 structalign = sc->structalign;556 if (baseClass)557 { sc->offset = baseClass->structsize;558 alignsize = baseClass->alignsize;559 // if (isnested)560 // sc->offset += PTRSIZE; // room for uplevel context pointer561 }562 else563 { sc->offset = 2*PTRSIZE; // allow room for vptr[] and monitor564 alignsize = PTRSIZE;565 }566 structsize = sc->offset;567 Scope scsave = *sc;568 int members_dim = members->dim;569 sizeok = 0;570 for (i = 0; i < members_dim; i++)571 {572 Dsymbol *s = (Dsymbol *)members->data[i];573 s->semantic(sc);574 }575 572 576 if (sizeok == 2) 577 { // semantic() failed because of forward references. 578 // Unwind what we did, and defer it for later 579 fields.setDim(0); 580 structsize = 0; 581 alignsize = 0; 582 structalign = 0; 573 if (sc_offset >= 0) 574 sc->offset = sc_offset; 583 575 576 scsave = *sc; 577 578 try { 579 callSemanticOnMembers(sc); 580 } catch (DeferException* deferexc) { 581 sc_offset = sc->offset; 582 deferState = 3; 584 583 sc = sc->pop(); 585 586 scope = scx ? scx : new Scope(*sc); 587 scope->setNoFree(); 588 scope->module->addDeferredSemantic(this); 589 590 //printf("\tsemantic('%s') failed due to forward references\n", toChars()); 591 return; 584 throw deferexc; 592 585 } 593 586 594 587 //printf("\tsemantic('%s') successful\n", toChars()); … … 679 672 } 680 673 #endif 681 674 //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type); 675 676 deferState = -1; 677 case -1: 678 break; 679 default: 680 assert(0 && "deferState for classes must be between -1 and 3"); 681 } // switch for deferred calling 682 682 } 683 683 684 684 void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) … … 775 775 Dsymbol *s; 776 776 777 777 //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars()); 778 if (scope) 779 semantic(scope); 778 s = ScopeDsymbol::search(loc, ident, flags); 780 779 781 if (!members || !symtab || scope) 782 { error("is forward referenced when looking for '%s'", ident->toChars()); 783 //*(char*)0=0; 784 return NULL; 780 if (!s && (!members || !symtab || deferState > 0)) 781 { 782 throw new DeferException(loc, "%s is forward referenced when looking for '%s'", toChars(), ident->toChars()); 785 783 } 786 784 787 s = ScopeDsymbol::search(loc, ident, flags);788 785 if (!s) 789 786 { 790 787 // Search bases classes in depth-first, left to right order … … 996 993 997 994 void InterfaceDeclaration::semantic(Scope *sc) 998 995 { int i; 996 Scope *scx = NULL; 999 997 998 int continueAt = deferState; 999 if (deferState > 0) 1000 deferState = 0; 1001 switch (continueAt) { 1002 case 0: 1000 1003 //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); 1001 1004 if (inuse) 1002 1005 return; 1003 if (!scope) 1004 {type = type->semantic(loc, sc);1005 1006 } 1006 1007 type = type->semantic(loc, sc); 1008 handle = handle->semantic(loc, sc); 1009 1007 1010 if (!members) // if forward reference 1008 1011 { //printf("\tinterface '%s' is forward referenced\n", toChars()); 1009 1012 return; 1010 1013 } 1011 1014 if (symtab) // if already done 1012 { if (!scope)1013 1015 { 1016 return; 1014 1017 } 1015 1018 else 1016 1019 symtab = new DsymbolTable(); 1017 1018 Scope *scx = NULL;1019 if (scope)1020 { sc = scope;1021 scx = scope; // save so we don't make redundant copies1022 scope = NULL;1023 }1024 1020 1025 1021 if (sc->stc & STCdeprecated) 1026 1022 { … … 1048 1044 i++; 1049 1045 } 1050 1046 1047 case 1: 1051 1048 // Check for errors, handle forward references 1052 1049 for (i = 0; i < baseclasses.dim; ) 1053 1050 { TypeClass *tc; … … 1084 1081 baseclasses.remove(i); 1085 1082 continue; 1086 1083 } 1087 if (!b->base->symtab || b->base-> scope|| b->base->inuse)1084 if (!b->base->symtab || b->base->deferState > 0 || b->base->inuse) 1088 1085 { 1089 1086 //error("forward reference of base class %s", baseClass->toChars()); 1090 1087 // Forward reference of base, try again later 1091 1088 //printf("\ttry later, forward reference of base %s\n", b->base->toChars()); 1092 scope = scx ? scx : new Scope(*sc); 1093 scope->setNoFree(); 1094 scope->module->addDeferredSemantic(this); 1089 deferState = 1; 1090 sc->module->addDeferredSemantic(this, sc); 1095 1091 return; 1092 //throw new DeferException(loc, "forward reference of interface %s", baseClass->toChars()); 1096 1093 } 1097 1094 } 1098 1095 i++; … … 1142 1139 s->addMember(sc, this, 1); 1143 1140 } 1144 1141 1142 case 2: 1145 1143 sc = sc->push(this); 1146 1144 sc->parent = this; 1147 1145 if (isCOMinterface()) … … 1149 1147 sc->structalign = 8; 1150 1148 structalign = sc->structalign; 1151 1149 sc->offset = 2*PTRSIZE; 1150 if (sc_offset >= 0) 1151 sc->offset = sc_offset; 1152 1152 1153 inuse++; 1153 for (i = 0; i < members->dim; i++) 1154 { 1155 Dsymbol *s = (Dsymbol *)members->data[i]; 1156 s->semantic(sc); 1154 1155 try { 1156 callSemanticOnMembers(sc); 1157 } catch (DeferException* deferexc) { 1158 sc_offset = sc->offset; 1159 deferState = 2; 1160 sc = sc->pop(); 1161 inuse--; 1162 throw deferexc; 1157 1163 } 1164 1158 1165 inuse--; 1159 1166 //members->print(); 1160 1167 sc->pop(); 1161 1168 //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); 1169 1170 deferState = -1; 1171 case -1: 1172 break; 1173 default: 1174 assert(0 && "deferState for interfaces must be between -1 and 2"); 1175 } // switch for deferStatus 1162 1176 } 1163 1177 1164 1178 -
a/dmd/declaration.c
old new 688 688 int inferred = 0; 689 689 if (!type) 690 690 { inuse++; 691 type = init->inferType(sc); 691 try { 692 type = init->inferType(sc); 693 } catch (DeferException* deferexc) { 694 inuse--; 695 throw deferexc; 696 } 692 697 inuse--; 693 698 inferred = 1; 694 699 … … 1009 1014 Expression *e; 1010 1015 Initializer *i2 = init; 1011 1016 inuse++; 1012 if (ei) 1013 { 1014 e = ei->exp->syntaxCopy(); 1015 e = e->semantic(sc); 1016 e = e->implicitCastTo(sc, type); 1017 } 1018 else if (si || ai) 1019 { i2 = init->syntaxCopy(); 1020 i2 = i2->semantic(sc, type); 1017 try { 1018 if (ei) 1019 { 1020 e = ei->exp->syntaxCopy(); 1021 e = e->semantic(sc); 1022 e = e->implicitCastTo(sc, type); 1023 } 1024 else if (si || ai) 1025 { i2 = init->syntaxCopy(); 1026 i2 = i2->semantic(sc, type); 1027 } 1028 } catch (DeferException* deferexc) { 1029 inuse--; 1030 global.gag--; 1031 throw deferexc; 1021 1032 } 1022 1033 inuse--; 1023 1034 global.gag--; -
a/dmd/dsymbol.c
old new 644 644 symtab = NULL; 645 645 imports = NULL; 646 646 prots = NULL; 647 member_semantic_started = false; 647 648 } 648 649 649 650 ScopeDsymbol::ScopeDsymbol(Identifier *id) … … 653 654 symtab = NULL; 654 655 imports = NULL; 655 656 prots = NULL; 657 member_semantic_started = false; 656 658 } 657 659 658 660 Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s) … … 765 767 } 766 768 } 767 769 } 768 imports->push(s); 769 prots = (unsigned char *)mem.realloc(prots, imports->dim * sizeof(prots[0])); 770 prots[imports->dim - 1] = protection; 770 bool in_imports = false; 771 for (int i = 0; i < imports->dim; ++i) 772 if (imports->data[i] == s) 773 in_imports = true; 774 if (!in_imports) 775 { 776 imports->push(s); 777 prots = (unsigned char *)mem.realloc(prots, imports->dim * sizeof(prots[0])); 778 prots[imports->dim - 1] = protection; 779 } 771 780 } 772 781 } 773 782 … … 833 842 const char *ScopeDsymbol::kind() 834 843 { 835 844 return "ScopeDsymbol"; 845 } 846 847 // shares code with AttribDeclaration::callSemanticOnMembers 848 void ScopeDsymbol::callSemanticOnMembers(Scope* sc) 849 { 850 // first add everything to remaining_semantic 851 if (!member_semantic_started) { 852 for (int i = 0; i < members->dim; i++) 853 remaining_semantic.push_back( (Dsymbol*)members->data[i] ); 854 member_semantic_started = true; 855 } 856 857 int failed = 0; 858 859 // last defer exception that was caught. stored for the error message inside 860 DeferException* lastdefer; 861 862 // if we deferred an order dependent member, save it here 863 // we will then skip all order dependent members until this is reached again 864 Dsymbol *deferredOrderDependent = NULL; 865 866 while (!remaining_semantic.empty() && failed != remaining_semantic.size()) 867 { Dsymbol *s; 868 s = remaining_semantic[0]; 869 remaining_semantic.pop_front(); 870 871 // if we deferred something order dependent, skip other 872 // order dependent ones for one iteration 873 if (deferredOrderDependent == s) 874 deferredOrderDependent = NULL; 875 if (deferredOrderDependent && !isMemberReorderable(s)) { 876 ++failed; 877 remaining_semantic.push_back(s); 878 continue; 879 } 880 881 try { 882 s->semantic(sc); 883 } catch (DeferException* deferexc) { 884 lastdefer = deferexc; 885 ++failed; 886 remaining_semantic.push_back(s); 887 if (!isMemberReorderable(s)) 888 deferredOrderDependent = s; 889 continue; 890 } 891 892 failed = 0; 893 postMemberSemantic(sc); 894 } 895 896 if (!remaining_semantic.empty()) 897 { 898 assert(lastdefer); 899 900 // reorder members into a valid state if necessary 901 if (deferredOrderDependent) 902 while (remaining_semantic[0] != deferredOrderDependent) { 903 Dsymbol* s = remaining_semantic[0]; 904 remaining_semantic.pop_front(); 905 remaining_semantic.push_back(s); 906 } 907 908 throw lastdefer; 909 } 836 910 } 837 911 838 912 … … 1002 1076 return NULL; 1003 1077 } 1004 1078 1005 1006 1079 /****************************** DsymbolTable ******************************/ 1007 1080 1008 1081 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" … … 252 253 void emitMemberComments(Scope *sc); 253 254 254 255 ScopeDsymbol *isScopeDsymbol() { return this; } 256 257 // LDC 258 std::deque<Dsymbol*> remaining_semantic; // Dsymbols where semantic remains to be called 259 bool member_semantic_started; 260 void callSemanticOnMembers(Scope* sc); 261 virtual void postMemberSemantic(Scope* sc) {} 262 virtual bool isMemberReorderable(Dsymbol* sym) { return true; } 255 263 }; 256 264 257 265 // With statement scope -
a/dmd/func.c
old new 327 327 break; 328 328 329 329 case -2: // can't determine because of fwd refs 330 cd->sizeok = 2; // can't finish due to forward reference 331 return; 330 throw new DeferException(loc, "cannot determine vtbl index of %s because of forward references", toChars()); 332 331 333 332 default: 334 333 { FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi]; … … 401 400 break; 402 401 403 402 case -2: 404 cd->sizeok = 2; // can't finish due to forward reference 405 return; 403 throw new DeferException(loc, "cannot determine vtbl index of %s because of forward references", toChars()); 406 404 407 405 default: 408 406 { FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi]; … … 497 495 } 498 496 if (cov == 3) 499 497 { 500 cd->sizeok = 2; // can't finish due to forward reference 501 return; 498 throw new DeferException(loc, "cannot finish due to forward reference"); 502 499 } 503 500 } 504 501 } -
a/dmd/import.c
old new 121 121 { 122 122 //printf("Import::semantic('%s')\n", toChars()); 123 123 124 load(sc); 124 DeferException* defer = NULL; 125 try { 126 load(sc); 127 } catch (DeferException* exc) { 128 defer = exc; 129 } 125 130 126 131 if (mod) 127 132 { … … 137 142 138 143 // Modules need a list of each imported module 139 144 //printf("%s imports %s\n", sc->module->toChars(), mod->toChars()); 140 sc->module->aimports.push(mod); 145 bool in_aimports = false; 146 for (int i = 0; i < sc->module->aimports.dim; ++i) 147 if (sc->module->aimports.data[i] == mod) 148 in_aimports = true; 149 if (!in_aimports) 150 sc->module->aimports.push(mod); 141 151 142 152 mod->semantic(); 143 153 … … 168 178 } 169 179 sc = sc->pop(); 170 180 } 181 182 if (defer) 183 throw defer; 171 184 //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg); 172 185 } 173 186 -
a/dmd/mars.c
old new 1154 1154 m = (Module *)modules.data[i]; 1155 1155 if (global.params.verbose) 1156 1156 printf("semantic %s\n", m->toChars()); 1157 m->semantic(); 1157 try { 1158 m->semantic(); 1159 } catch (DeferException* deferexc) { 1160 error("Couldn't resolve error though deferring:\n%s", deferexc->errormessage); 1161 } 1158 1162 } 1159 1163 if (global.errors) 1160 1164 fatal(); -
a/dmd/module.c
old new 50 50 DsymbolTable *Module::modules; 51 51 Array Module::amodules; 52 52 53 ArrayModule::deferred; // deferred Dsymbol's needing semantic() run on them53 std::deque<DeferredDsymbol> Module::deferred; // deferred Dsymbol's needing semantic() run on them 54 54 unsigned Module::dprogress; 55 55 56 56 void Module::init() … … 130 130 llvmForceLogging = false; 131 131 this->doDocComment = doDocComment; 132 132 this->doHdrGen = doHdrGen; 133 sc = NULL; 133 134 } 134 135 135 136 File* Module::buildFilePath(char* forcename, char* path, char* ext) … … 620 621 void Module::semantic(Scope* unused_sc) 621 622 { int i; 622 623 623 if (semanticstarted) 624 // if already done or circular, bail out 625 if (semanticdone || semanticstarted == 1) 624 626 return; 625 627 626 //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); 627 semanticstarted = 1; 628 if (semanticstarted == 0) 629 { 630 //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); 631 semanticstarted = 1; 628 632 629 630 631 632 Scope *sc = Scope::createGlobal(this); // create root scope633 // Note that modules get their own scope, from scratch. 634 // This is so regardless of where in the syntax a module 635 // gets imported, it is unaffected by context. 636 sc = Scope::createGlobal(this); // create root scope 633 637 634 638 //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage); 635 639 636 637 638 639 Import *im = new Import(0, NULL, Id::object, NULL, 0);640 members->shift(im);641 640 // Add import of "object" if this module isn't "object" 641 if (ident != Id::object) 642 { 643 Import *im = new Import(0, NULL, Id::object, NULL, 0); 644 members->shift(im); 645 } 642 646 643 644 645 646 647 // Add all symbols into module's symbol table 648 symtab = new DsymbolTable(); 649 for (i = 0; i < members->dim; i++) 650 { Dsymbol *s; 647 651 648 s = (Dsymbol *)members->data[i]; 649 s->addMember(NULL, sc->scopesym, 1); 652 s = (Dsymbol *)members->data[i]; 653 s->addMember(NULL, sc->scopesym, 1); 654 } 650 655 } 651 656 652 657 // Pass 1 semantic routines: do public side of the definition 653 for (i = 0; i < members->dim; i++) 654 { Dsymbol *s; 655 656 s = (Dsymbol *)members->data[i]; 657 //printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars()); 658 s->semantic(sc); 659 runDeferredSemantic(); 658 try { 659 callSemanticOnMembers(sc); 660 } catch (DeferException* deferexc) { 661 semanticstarted = -1; 662 throw deferexc; 660 663 } 661 664 662 665 sc = sc->pop(); 663 666 sc->pop(); 664 semanticdone = semanticstarted; 667 semanticstarted = 1; 668 semanticdone = 1; 665 669 //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); 666 670 } 667 671 668 672 void Module::semantic2(Scope* unused_sc) 669 673 { int i; 670 674 671 if ( deferred.dim)675 if (!deferred.empty()) 672 676 { 673 for (int i = 0; i < deferred. dim; i++)677 for (int i = 0; i < deferred.size(); i++) 674 678 { 675 Dsymbol *sd = (Dsymbol *)deferred.data[i];679 Dsymbol *sd = deferred[i].sym; 676 680 677 681 sd->error("unable to resolve forward reference in definition"); 678 682 } … … 814 818 s = ScopeDsymbol::search(loc, ident, flags); 815 819 insearch = 0; 816 820 821 if (!s && semanticstarted == -1) 822 error("Forward reference!"); 823 817 824 searchCacheIdent = ident; 818 825 searchCacheSymbol = s; 819 826 searchCacheFlags = flags; … … 825 832 * Can't run semantic on s now, try again later. 826 833 */ 827 834 828 void Module::addDeferredSemantic(Dsymbol *s )835 void Module::addDeferredSemantic(Dsymbol *sym, Scope *scope) 829 836 { 830 837 // Don't add it if it is already there 831 for (int i = 0; i < deferred. dim; i++)838 for (int i = 0; i < deferred.size(); i++) 832 839 { 833 Dsymbol *sd = (Dsymbol *)deferred .data[i];840 Dsymbol *sd = (Dsymbol *)deferred[i].sym; 834 841 835 if (sd == s )842 if (sd == sym) 836 843 return; 837 844 } 838 845 846 // copy scope 847 Scope* scx = new Scope(*scope); 848 scx->setNoFree(); 849 839 850 //printf("Module::addDeferredSemantic('%s')\n", s->toChars()); 840 deferred.push (s);851 deferred.push_back(DeferredDsymbol(sym, scx)); 841 852 } 842 853 843 854 … … 847 858 848 859 void Module::runDeferredSemantic() 849 860 { 850 size_t len;861 //if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); 851 862 852 863 static int nested; 853 864 if (nested) 854 865 return; 855 //if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);856 866 nested++; 857 867 858 do 859 { 860 dprogress = 0; 861 len = deferred.dim; 862 if (!len) 863 break; 868 int failed = 0; 864 869 865 Dsymbol **todo; 866 Dsymbol *tmp; 867 if (len == 1) 868 { 869 todo = &tmp; 870 // last defer exception that was caught. stored for the error message inside 871 DeferException* lastdefer; 872 873 // if we deferred an order dependent member, save it here 874 // we will then skip all order dependent members until this is reached again 875 Dsymbol *deferredOrderDependent = NULL; 876 877 while (!deferred.empty() && failed != deferred.size()) 878 { Dsymbol *s; 879 Scope *sc; 880 s = deferred[0].sym; 881 sc = deferred[0].scope; 882 deferred.pop_front(); 883 884 // if we deferred something order dependent, skip other 885 // order dependent ones for one iteration 886 if (deferredOrderDependent == s) 887 deferredOrderDependent = NULL; 888 if (deferredOrderDependent && !isMemberReorderable(s)) { 889 ++failed; 890 deferred.push_back(DeferredDsymbol(s, sc)); 891 continue; 870 892 } 871 else 872 { 873 todo = (Dsymbol **)alloca(len * sizeof(Dsymbol *)); 874 assert(todo); 893 894 try { 895 s->semantic(sc); 896 if (!deferred.empty() && deferred.rbegin()->sym == s) 897 ++failed; 898 else 899 failed = 0; 900 } catch (DeferException* deferexc) { 901 lastdefer = deferexc; 902 ++failed; 903 deferred.push_back(DeferredDsymbol(s, sc)); 904 if (!isMemberReorderable(s)) 905 deferredOrderDependent = s; 906 continue; 875 907 } 876 memcpy(todo, deferred.data, len * sizeof(Dsymbol *)); 877 deferred.setDim(0); 908 } 878 909 879 for (int i = 0; i < len; i++)880 {881 Dsymbol *s = todo[i];882 883 s->semantic(NULL);884 //printf("deferred: %s, parent = %s\n", s->toChars(), s->parent->toChars());885 }886 //printf("\tdeferred.dim = %d, len = %d, dprogress = %d\n", deferred.dim, len, dprogress);887 } while (deferred.dim < len || dprogress); // while making progress888 910 nested--; 889 911 //printf("-Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); 890 912 } -
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 int imports(Module *m); 145 159 … … 179 193 180 194 // array ops emitted in this module already 181 195 StringTable arrayfuncs; 196 197 // LDC 198 virtual void postMemberSemantic(Scope* sc) { runDeferredSemantic(); } 199 Scope* sc; 182 200 }; 183 201 184 202 -
a/dmd/mtype.c
old new 3960 3960 #ifdef DEBUG 3961 3961 printf("2: "); 3962 3962 #endif 3963 error(sym->loc, "enum %s is forward referenced", sym->toChars()); 3963 //error(sym->loc, "enum %s is forward referenced", sym->toChars()); 3964 throw new DeferException(sym->loc, "enum %s is forward referenced", sym->toChars()); 3964 3965 return tint32; 3965 3966 } 3966 3967 return sym->memtype->toBasetype(); … … 4645 4646 Type *TypeClass::semantic(Loc loc, Scope *sc) 4646 4647 { 4647 4648 //printf("TypeClass::semantic(%s)\n", sym->toChars()); 4648 if (sym->scope)4649 sym->semantic(sym->scope);4650 4649 return merge(); 4651 4650 } 4652 4651 -
a/dmd/root.c
old new 148 148 exit(EXIT_FAILURE); 149 149 } 150 150 #endif 151 152 DeferException::DeferException(Loc& loc, const char* format, ...) 153 { 154 errormessage = (char *)mem.malloc(200); 155 va_list ap; 156 157 va_start(ap, format); 158 size_t n = snprintf(errormessage, 200, "%s: ", loc.toChars()); 159 vsnprintf(errormessage+n, 200-n, format, ap); 160 va_end( ap ); 161 162 //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); 163 } 151 164 152 165 void error_mem() 153 166 { -
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 2877 2877 // LDC 2878 2878 this->tinst = NULL; 2879 2879 this->tmodule = NULL; 2880 this->deferState = 0; 2880 2881 } 2881 2882 2882 2883 /***************** … … 2908 2909 // LDC 2909 2910 this->tinst = NULL; 2910 2911 this->tmodule = NULL; 2912 this->deferState = 0; 2911 2913 2912 2914 assert((size_t)tempdecl->scope > 0x10000); 2913 2915 } … … 2953 2955 2954 2956 void TemplateInstance::semantic(Scope *sc) 2955 2957 { 2958 int memnum = 0; 2959 int dosemantic3 = 0; 2960 unsigned errorsave; 2961 int tempdecl_instance_idx; 2962 2963 int continueAt = deferState; 2964 if (deferState > 0) 2965 deferState = 0; 2966 switch (continueAt) { 2967 case 0: 2956 2968 if (global.errors) 2957 2969 { 2958 2970 if (!global.gag) … … 3016 3028 semanticTiargs(sc); 3017 3029 3018 3030 tempdecl = findTemplateDeclaration(sc); 3019 if (tempdecl) 3020 tempdecl = findBestMatch(sc); 3031 if (tempdecl) { 3032 try { 3033 tempdecl = findBestMatch(sc); 3034 } catch(DeferException* deferexc) { 3035 semanticdone = 0; 3036 throw deferexc; 3037 } 3038 } 3021 3039 if (!tempdecl || global.errors) 3022 3040 { inst = this; 3023 3041 //printf("error return %p, %d\n", tempdecl, global.errors); … … 3070 3088 #if LOG 3071 3089 printf("\timplement template instance '%s'\n", toChars()); 3072 3090 #endif 3073 unsignederrorsave = global.errors;3091 errorsave = global.errors; 3074 3092 inst = this; 3075 inttempdecl_instance_idx = tempdecl->instances.dim;3093 tempdecl_instance_idx = tempdecl->instances.dim; 3076 3094 tempdecl->instances.push(this); 3077 3095 parent = tempdecl->parent; 3078 3096 //printf("parent = '%s'\n", parent->kind()); … … 3088 3106 // Add 'this' to the enclosing scope's members[] so the semantic routines 3089 3107 // will get called on the instance members 3090 3108 #if 1 3091 int dosemantic3 = 0;3092 3109 { Array *a; 3093 3110 3094 3111 Scope *scx = sc; … … 3134 3151 // Copy the syntax trees from the TemplateDeclaration 3135 3152 members = Dsymbol::arraySyntaxCopy(tempdecl->members); 3136 3153 3154 case 1: 3155 semanticdone = 1; 3137 3156 // Create our own scope for the template parameters 3138 Scope *scope = tempdecl->scope;3157 scope = tempdecl->scope; 3139 3158 if (!scope) 3140 3159 { 3141 error("forward reference to template declaration %s\n", tempdecl->toChars()); 3142 return; 3160 semanticdone = 0; 3161 deferState = 1; 3162 throw new DeferException(loc, "forward reference to template declaration %s\n", tempdecl->toChars()); 3143 3163 } 3144 3164 3145 3165 #if LOG … … 3155 3175 // Add members of template instance to template instance symbol table 3156 3176 // parent = scope->scopesym; 3157 3177 symtab = new DsymbolTable(); 3158 int memnum = 0;3159 3178 for (int i = 0; i < members->dim; i++) 3160 3179 { 3161 3180 Dsymbol *s = (Dsymbol *)members->data[i]; … … 3193 3212 #if LOG 3194 3213 printf("\tdo semantic() on template instance members '%s'\n", toChars()); 3195 3214 #endif 3196 Scope *sc2;3197 3215 sc2 = scope->push(this); 3198 3216 //printf("isnested = %d, sc->parent = %s\n", isnested, sc->parent->toChars()); 3199 3217 sc2->parent = /*isnested ? sc->parent :*/ this; 3200 3218 sc2->tinst = this; 3201 3219 3202 #if !IN_LLVM 3203 #if _WIN32 3204 __try 3205 { 3206 #endif 3207 #endif 3208 for (int i = 0; i < members->dim; i++) 3209 { 3210 Dsymbol *s = (Dsymbol *)members->data[i]; 3211 //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars()); 3212 //printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars()); 3213 // if (isnested) 3214 // s->parent = sc->parent; 3215 //printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); 3216 s->semantic(sc2); 3217 //printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); 3218 sc2->module->runDeferredSemantic(); 3219 } 3220 #if !IN_LLVM 3221 #if _WIN32 3222 } 3223 __except (__ehfilter(GetExceptionInformation())) 3224 { 3225 global.gag = 0; // ensure error message gets printed 3226 error("recursive expansion"); 3227 fatal(); 3228 } 3229 #endif 3230 #endif 3220 case 2: 3221 semanticdone = 1; 3222 try { 3223 callSemanticOnMembers(sc2); 3224 } catch (DeferException* deferexc) { 3225 deferState = 2; 3226 semanticdone = 0; 3227 throw deferexc; 3228 } 3231 3229 3232 3230 /* If any of the instantiation members didn't get semantic() run 3233 3231 * on them due to forward references, we cannot run semantic2() 3234 3232 * or semantic3() yet. 3235 3233 */ 3236 for (size_t i = 0; i < Module::deferred. dim; i++)3237 { Dsymbol *sd = (Dsymbol *)Module::deferred .data[i];3234 for (size_t i = 0; i < Module::deferred.size(); i++) 3235 { Dsymbol *sd = (Dsymbol *)Module::deferred[i].sym; 3238 3236 3239 3237 if (sd->parent == this) 3240 3238 goto Laftersemantic; … … 3276 3274 #if LOG 3277 3275 printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); 3278 3276 #endif 3277 3278 deferState = -1; 3279 case -1: 3280 break; 3281 default: 3282 assert(0 && "deferState for template instances must be between -1 and 2"); 3283 } // switch for deferring 3279 3284 } 3280 3285 3281 3286 … … 3521 3526 dedtypes.zero(); 3522 3527 if (!td->scope) 3523 3528 { 3524 error("forward reference to template declaration %s", td->toChars()); 3525 return NULL; 3529 throw new DeferException(loc, "forward reference to template declaration %s", td->toChars()); 3526 3530 } 3527 3531 m = td->matchWithInstance(this, &dedtypes, 0); 3528 3532 //printf("matchWithInstance = %d\n", m); … … 4012 4016 } 4013 4017 } 4014 4018 4019 void TemplateInstance::postMemberSemantic(Scope *sc) 4020 { 4021 sc->module->runDeferredSemantic(); 4022 } 4023 4015 4024 /* ======================== TemplateMixin ================================ */ 4016 4025 4017 4026 TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual, … … 4024 4033 this->idents = idents; 4025 4034 this->tiargs = tiargs ? tiargs : new Objects(); 4026 4035 this->scope = NULL; 4036 this->deferState = 0; 4027 4037 } 4028 4038 4029 4039 Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s) … … 4053 4063 4054 4064 void TemplateMixin::semantic(Scope *sc) 4055 4065 { 4066 unsigned errorsave; 4067 4068 int continueAt = deferState; 4069 if (deferState > 0) 4070 deferState = 0; 4071 switch (continueAt) { 4072 case 0: 4073 4056 4074 #if LOG 4057 4075 printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this); 4058 4076 fflush(stdout); … … 4078 4096 util_progress(); 4079 4097 #endif 4080 4098 4081 Scope *scx = NULL;4099 scx = NULL; 4082 4100 if (scope) 4083 4101 { sc = scope; 4084 4102 scx = scope; // save so we don't make redundant copies … … 4153 4171 */ 4154 4172 semanticdone = 0; 4155 4173 AggregateDeclaration *ad = toParent()->isAggregateDeclaration(); 4156 if (ad) 4157 ad->sizeok = 2; 4158 else 4159 { 4160 // Forward reference 4161 //printf("forward reference - deferring\n"); 4162 scope = scx ? scx : new Scope(*sc); 4163 scope->setNoFree(); 4164 scope->module->addDeferredSemantic(this); 4165 } 4166 return; 4174 4175 // Forward reference 4176 //printf("forward reference - deferring\n"); 4177 //scope = scx ? scx : new Scope(*sc); 4178 //scope->setNoFree(); 4179 //scope->module->addDeferredSemantic(this); 4180 throw new DeferException(loc, "%s at %s is forward referenced", td->toChars(), td->loc.toChars()); 4167 4181 } 4168 4182 } 4169 4183 … … 4251 4265 #if LOG 4252 4266 printf("\tcreate scope for template parameters '%s'\n", toChars()); 4253 4267 #endif 4254 Scope *scy = sc;4268 scy = sc; 4255 4269 scy = sc->push(this); 4256 4270 scy->parent = this; 4257 4271 4258 4272 argsym = new ScopeDsymbol(); 4259 4273 argsym->parent = scy->parent; 4260 Scope *scope = scy->push(argsym);4261 4262 unsignederrorsave = global.errors;4274 scope = scy->push(argsym); 4275 4276 errorsave = global.errors; 4263 4277 4264 4278 // Declare each template parameter as an alias for the argument type 4265 4279 declareParameters(scope); … … 4279 4293 #if LOG 4280 4294 printf("\tdo semantic() on template instance members '%s'\n", toChars()); 4281 4295 #endif 4282 Scope *sc2;4283 4296 sc2 = scope->push(this); 4284 4297 sc2->offset = sc->offset; 4285 for (int i = 0; i < members->dim; i++) 4286 { 4287 Dsymbol *s = (Dsymbol *)members->data[i]; 4288 s->semantic(sc2); 4298 4299 case 1: 4300 try { 4301 callSemanticOnMembers(sc2); 4302 } catch (DeferException* deferexc) { 4303 deferState = 1; 4304 semanticdone = 0; 4305 throw deferexc; 4289 4306 } 4290 4307 sc->offset = sc2->offset; 4308 4309 /* If any of the instantiation members didn't get semantic() run 4310 * on them due to forward references, error! 4311 */ 4312 for (size_t i = 0; i < Module::deferred.size(); i++) 4313 { Dsymbol *sd = (Dsymbol *)Module::deferred[i].sym; 4314 4315 if (sd->parent == this) 4316 error("semantic failed due to forward references in %s", sd->toPrettyChars()); 4317 } 4291 4318 4292 4319 /* The problem is when to parse the initializer for a variable. 4293 4320 * Perhaps VarDeclaration::semantic() should do it like it does … … 4319 4346 #if LOG 4320 4347 printf("-TemplateMixin::semantic('%s', this=%p)\n", toChars(), this); 4321 4348 #endif 4349 4350 deferState = -1; 4351 case -1: 4352 break; 4353 default: 4354 assert(0 && "deferState for template mixins must be between -1 and 1"); 4355 } // switch for deferring 4322 4356 } 4323 4357 4324 4358 void TemplateMixin::semantic2(Scope *sc) -
a/dmd/template.h
old new 328 328 TemplateInstance *tinst; // enclosing template instance 329 329 Module* tmodule; // module from outermost enclosing template instantiation 330 330 void printInstantiationTrace(); 331 332 void postMemberSemantic(Scope* sc); 333 int deferState; 334 Scope *sc2; 335 Scope *scope; 331 336 }; 332 337 333 338 struct TemplateMixin : TemplateInstance … … 353 358 void toObjFile(int multiobj); // compile to .obj file 354 359 355 360 TemplateMixin *isTemplateMixin() { return this; } 361 362 // LDC 363 int deferState; 364 Scope *sc2, *scy, *scx; 356 365 }; 357 366 358 367 Expression *isExpression(Object *o);