Ticket #125: forwardref-new2.diff
File forwardref-new2.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 687 687 int inferred = 0; 688 688 if (!type) 689 689 { inuse++; 690 type = init->inferType(sc); 690 try { 691 type = init->inferType(sc); 692 } catch (DeferException* deferexc) { 693 inuse--; 694 throw deferexc; 695 } 691 696 inuse--; 692 697 inferred = 1; 693 698 … … 1008 1013 Expression *e; 1009 1014 Initializer *i2 = init; 1010 1015 inuse++; 1011 if (ei) 1012 { 1013 e = ei->exp->syntaxCopy(); 1014 e = e->semantic(sc); 1015 e = e->implicitCastTo(sc, type); 1016 } 1017 else if (si || ai) 1018 { i2 = init->syntaxCopy(); 1019 i2 = i2->semantic(sc, type); 1016 try { 1017 if (ei) 1018 { 1019 e = ei->exp->syntaxCopy(); 1020 e = e->semantic(sc); 1021 e = e->implicitCastTo(sc, type); 1022 } 1023 else if (si || ai) 1024 { i2 = init->syntaxCopy(); 1025 i2 = i2->semantic(sc, type); 1026 } 1027 } catch (DeferException* deferexc) { 1028 inuse--; 1029 global.gag--; 1030 throw deferexc; 1020 1031 } 1021 1032 inuse--; 1022 1033 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 326 326 break; 327 327 328 328 case -2: // can't determine because of fwd refs 329 cd->sizeok = 2; // can't finish due to forward reference 330 return; 329 throw new DeferException(loc, "cannot determine vtbl index of %s because of forward references", toChars()); 331 330 332 331 default: 333 332 { FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi]; … … 400 399 break; 401 400 402 401 case -2: 403 cd->sizeok = 2; // can't finish due to forward reference 404 return; 402 throw new DeferException(loc, "cannot determine vtbl index of %s because of forward references", toChars()); 405 403 406 404 default: 407 405 { FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi]; … … 496 494 } 497 495 if (cov == 3) 498 496 { 499 cd->sizeok = 2; // can't finish due to forward reference 500 return; 497 throw new DeferException(loc, "cannot finish due to forward reference"); 501 498 } 502 499 } 503 500 } -
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 1151 1151 m = (Module *)modules.data[i]; 1152 1152 if (global.params.verbose) 1153 1153 printf("semantic %s\n", m->toChars()); 1154 m->semantic(); 1154 try { 1155 m->semantic(); 1156 } catch (DeferException* deferexc) { 1157 error("Couldn't resolve error though deferring:\n%s", deferexc->errormessage); 1158 } 1155 1159 } 1156 1160 if (global.errors) 1157 1161 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 3957 3957 #ifdef DEBUG 3958 3958 printf("2: "); 3959 3959 #endif 3960 error(sym->loc, "enum %s is forward referenced", sym->toChars()); 3960 //error(sym->loc, "enum %s is forward referenced", sym->toChars()); 3961 throw new DeferException(sym->loc, "enum %s is forward referenced", sym->toChars()); 3961 3962 return tint32; 3962 3963 } 3963 3964 return sym->memtype->toBasetype(); … … 4644 4645 Type *TypeClass::semantic(Loc loc, Scope *sc) 4645 4646 { 4646 4647 //printf("TypeClass::semantic(%s)\n", sym->toChars()); 4647 if (sym->scope)4648 sym->semantic(sym->scope);4649 4648 return merge(); 4650 4649 } 4651 4650 -
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 2874 2874 this->isnested = NULL; 2875 2875 this->errors = 0; 2876 2876 this->tinst = NULL; 2877 this->deferState = 0; 2877 2878 } 2878 2879 2879 2880 /***************** … … 2902 2903 this->isnested = NULL; 2903 2904 this->errors = 0; 2904 2905 this->tinst = NULL; 2906 this->deferState = 0; 2905 2907 2906 2908 assert((size_t)tempdecl->scope > 0x10000); 2907 2909 } … … 2947 2949 2948 2950 void TemplateInstance::semantic(Scope *sc) 2949 2951 { 2952 int memnum = 0; 2953 int dosemantic3 = 0; 2954 unsigned errorsave; 2955 int tempdecl_instance_idx; 2956 2957 int continueAt = deferState; 2958 if (deferState > 0) 2959 deferState = 0; 2960 switch (continueAt) { 2961 case 0: 2950 2962 if (global.errors) 2951 2963 { 2952 2964 if (!global.gag) … … 3003 3015 semanticTiargs(sc); 3004 3016 3005 3017 tempdecl = findTemplateDeclaration(sc); 3006 if (tempdecl) 3007 tempdecl = findBestMatch(sc); 3018 if (tempdecl) { 3019 try { 3020 tempdecl = findBestMatch(sc); 3021 } catch(DeferException* deferexc) { 3022 semanticdone = 0; 3023 throw deferexc; 3024 } 3025 } 3008 3026 if (!tempdecl || global.errors) 3009 3027 { inst = this; 3010 3028 //printf("error return %p, %d\n", tempdecl, global.errors); … … 3057 3075 #if LOG 3058 3076 printf("\timplement template instance '%s'\n", toChars()); 3059 3077 #endif 3060 unsignederrorsave = global.errors;3078 errorsave = global.errors; 3061 3079 inst = this; 3062 inttempdecl_instance_idx = tempdecl->instances.dim;3080 tempdecl_instance_idx = tempdecl->instances.dim; 3063 3081 tempdecl->instances.push(this); 3064 3082 parent = tempdecl->parent; 3065 3083 //printf("parent = '%s'\n", parent->kind()); … … 3075 3093 // Add 'this' to the enclosing scope's members[] so the semantic routines 3076 3094 // will get called on the instance members 3077 3095 #if 1 3078 int dosemantic3 = 0;3079 3096 { Array *a; 3080 3097 3081 3098 Scope *scx = sc; … … 3121 3138 // Copy the syntax trees from the TemplateDeclaration 3122 3139 members = Dsymbol::arraySyntaxCopy(tempdecl->members); 3123 3140 3141 case 1: 3142 semanticdone = 1; 3124 3143 // Create our own scope for the template parameters 3125 Scope *scope = tempdecl->scope;3144 scope = tempdecl->scope; 3126 3145 if (!scope) 3127 3146 { 3128 error("forward reference to template declaration %s\n", tempdecl->toChars()); 3129 return; 3147 semanticdone = 0; 3148 deferState = 1; 3149 throw new DeferException(loc, "forward reference to template declaration %s\n", tempdecl->toChars()); 3130 3150 } 3131 3151 3132 3152 #if LOG … … 3142 3162 // Add members of template instance to template instance symbol table 3143 3163 // parent = scope->scopesym; 3144 3164 symtab = new DsymbolTable(); 3145 int memnum = 0;3146 3165 for (int i = 0; i < members->dim; i++) 3147 3166 { 3148 3167 Dsymbol *s = (Dsymbol *)members->data[i]; … … 3180 3199 #if LOG 3181 3200 printf("\tdo semantic() on template instance members '%s'\n", toChars()); 3182 3201 #endif 3183 Scope *sc2;3184 3202 sc2 = scope->push(this); 3185 3203 //printf("isnested = %d, sc->parent = %s\n", isnested, sc->parent->toChars()); 3186 3204 sc2->parent = /*isnested ? sc->parent :*/ this; 3187 3205 sc2->tinst = this; 3188 3206 3189 #if !IN_LLVM 3190 #if _WIN32 3191 __try 3192 { 3193 #endif 3194 #endif 3195 for (int i = 0; i < members->dim; i++) 3196 { 3197 Dsymbol *s = (Dsymbol *)members->data[i]; 3198 //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars()); 3199 //printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars()); 3200 // if (isnested) 3201 // s->parent = sc->parent; 3202 //printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); 3203 s->semantic(sc2); 3204 //printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); 3205 sc2->module->runDeferredSemantic(); 3206 } 3207 #if !IN_LLVM 3208 #if _WIN32 3209 } 3210 __except (__ehfilter(GetExceptionInformation())) 3211 { 3212 global.gag = 0; // ensure error message gets printed 3213 error("recursive expansion"); 3214 fatal(); 3215 } 3216 #endif 3217 #endif 3207 case 2: 3208 semanticdone = 1; 3209 try { 3210 callSemanticOnMembers(sc2); 3211 } catch (DeferException* deferexc) { 3212 deferState = 2; 3213 semanticdone = 0; 3214 throw deferexc; 3215 } 3218 3216 3219 3217 /* If any of the instantiation members didn't get semantic() run 3220 3218 * on them due to forward references, we cannot run semantic2() 3221 3219 * or semantic3() yet. 3222 3220 */ 3223 for (size_t i = 0; i < Module::deferred. dim; i++)3224 { Dsymbol *sd = (Dsymbol *)Module::deferred .data[i];3221 for (size_t i = 0; i < Module::deferred.size(); i++) 3222 { Dsymbol *sd = (Dsymbol *)Module::deferred[i].sym; 3225 3223 3226 3224 if (sd->parent == this) 3227 3225 goto Laftersemantic; … … 3263 3261 #if LOG 3264 3262 printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); 3265 3263 #endif 3264 3265 deferState = -1; 3266 case -1: 3267 break; 3268 default: 3269 assert(0 && "deferState for template instances must be between -1 and 2"); 3270 } // switch for deferring 3266 3271 } 3267 3272 3268 3273 … … 3508 3513 dedtypes.zero(); 3509 3514 if (!td->scope) 3510 3515 { 3511 error("forward reference to template declaration %s", td->toChars()); 3512 return NULL; 3516 throw new DeferException(loc, "forward reference to template declaration %s", td->toChars()); 3513 3517 } 3514 3518 m = td->matchWithInstance(this, &dedtypes, 0); 3515 3519 //printf("matchWithInstance = %d\n", m); … … 3999 4003 } 4000 4004 } 4001 4005 4006 void TemplateInstance::postMemberSemantic(Scope *sc) 4007 { 4008 sc->module->runDeferredSemantic(); 4009 } 4010 4002 4011 /* ======================== TemplateMixin ================================ */ 4003 4012 4004 4013 TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual, … … 4011 4020 this->idents = idents; 4012 4021 this->tiargs = tiargs ? tiargs : new Objects(); 4013 4022 this->scope = NULL; 4023 this->deferState = 0; 4014 4024 } 4015 4025 4016 4026 Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s) … … 4040 4050 4041 4051 void TemplateMixin::semantic(Scope *sc) 4042 4052 { 4053 unsigned errorsave; 4054 4055 int continueAt = deferState; 4056 if (deferState > 0) 4057 deferState = 0; 4058 switch (continueAt) { 4059 case 0: 4060 4043 4061 #if LOG 4044 4062 printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this); 4045 4063 fflush(stdout); … … 4065 4083 util_progress(); 4066 4084 #endif 4067 4085 4068 Scope *scx = NULL;4086 scx = NULL; 4069 4087 if (scope) 4070 4088 { sc = scope; 4071 4089 scx = scope; // save so we don't make redundant copies … … 4140 4158 */ 4141 4159 semanticdone = 0; 4142 4160 AggregateDeclaration *ad = toParent()->isAggregateDeclaration(); 4143 if (ad) 4144 ad->sizeok = 2; 4145 else 4146 { 4147 // Forward reference 4148 //printf("forward reference - deferring\n"); 4149 scope = scx ? scx : new Scope(*sc); 4150 scope->setNoFree(); 4151 scope->module->addDeferredSemantic(this); 4152 } 4153 return; 4161 4162 // Forward reference 4163 //printf("forward reference - deferring\n"); 4164 //scope = scx ? scx : new Scope(*sc); 4165 //scope->setNoFree(); 4166 //scope->module->addDeferredSemantic(this); 4167 throw new DeferException(loc, "%s at %s is forward referenced", td->toChars(), td->loc.toChars()); 4154 4168 } 4155 4169 } 4156 4170 … … 4238 4252 #if LOG 4239 4253 printf("\tcreate scope for template parameters '%s'\n", toChars()); 4240 4254 #endif 4241 Scope *scy = sc;4255 scy = sc; 4242 4256 scy = sc->push(this); 4243 4257 scy->parent = this; 4244 4258 4245 4259 argsym = new ScopeDsymbol(); 4246 4260 argsym->parent = scy->parent; 4247 Scope *scope = scy->push(argsym);4248 4249 unsignederrorsave = global.errors;4261 scope = scy->push(argsym); 4262 4263 errorsave = global.errors; 4250 4264 4251 4265 // Declare each template parameter as an alias for the argument type 4252 4266 declareParameters(scope); … … 4266 4280 #if LOG 4267 4281 printf("\tdo semantic() on template instance members '%s'\n", toChars()); 4268 4282 #endif 4269 Scope *sc2;4270 4283 sc2 = scope->push(this); 4271 4284 sc2->offset = sc->offset; 4272 for (int i = 0; i < members->dim; i++) 4273 { 4274 Dsymbol *s = (Dsymbol *)members->data[i]; 4275 s->semantic(sc2); 4285 4286 case 1: 4287 try { 4288 callSemanticOnMembers(sc2); 4289 } catch (DeferException* deferexc) { 4290 deferState = 1; 4291 semanticdone = 0; 4292 throw deferexc; 4276 4293 } 4277 4294 sc->offset = sc2->offset; 4295 4296 /* If any of the instantiation members didn't get semantic() run 4297 * on them due to forward references, error! 4298 */ 4299 for (size_t i = 0; i < Module::deferred.size(); i++) 4300 { Dsymbol *sd = (Dsymbol *)Module::deferred[i].sym; 4301 4302 if (sd->parent == this) 4303 error("semantic failed due to forward references in %s", sd->toPrettyChars()); 4304 } 4278 4305 4279 4306 /* The problem is when to parse the initializer for a variable. 4280 4307 * Perhaps VarDeclaration::semantic() should do it like it does … … 4306 4333 #if LOG 4307 4334 printf("-TemplateMixin::semantic('%s', this=%p)\n", toChars(), this); 4308 4335 #endif 4336 4337 deferState = -1; 4338 case -1: 4339 break; 4340 default: 4341 assert(0 && "deferState for template mixins must be between -1 and 1"); 4342 } // switch for deferring 4309 4343 } 4310 4344 4311 4345 void TemplateMixin::semantic2(Scope *sc) -
a/dmd/template.h
old new 325 325 AliasDeclaration *isAliasDeclaration(); 326 326 327 327 // LDC 328 void postMemberSemantic(Scope* sc); 328 329 TemplateInstance *tinst; // enclosing template instance 329 330 void printInstantiationTrace(); 331 int deferState; 332 Scope *sc2; 333 Scope *scope; 330 334 }; 331 335 332 336 struct TemplateMixin : TemplateInstance … … 352 356 void toObjFile(int multiobj); // compile to .obj file 353 357 354 358 TemplateMixin *isTemplateMixin() { return this; } 359 360 // LDC 361 int deferState; 362 Scope *sc2, *scy, *scx; 355 363 }; 356 364 357 365 Expression *isExpression(Object *o);