Wiki Roadmap Timeline Tickets New Ticket Source Search Help / Guide About Trac Login

Ticket #125: forwardref-965.diff

File forwardref-965.diff, 51.5 kB (added by ChristianK, 12 years ago)

update for [965]

  • a/dmd/aggregate.h

    old new  
    6262                // 1: size is correct 
    6363                // 2: cannot determine size; fwd referenced 
    6464    int isdeprecated;       // !=0 if deprecated 
    65     Scope *scope;       // !=NULL means context to use 
    6665 
    6766    // Special member functions 
    6867    InvariantDeclaration *inv;      // invariant 
     
    104103    Symbol *toInitializer(); 
    105104 
    106105    AggregateDeclaration *isAggregateDeclaration() { return this; } 
     106 
     107    // LDC 
     108    int sc_offset;      // saved next offset in aggregate 
    107109}; 
    108110 
    109111struct AnonymousAggregateDeclaration : AggregateDeclaration 
     
    131133    Dsymbol *syntaxCopy(Dsymbol *s); 
    132134    void semantic(Scope *sc); 
    133135    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 
    134144    char *mangle(); 
    135145    const char *kind(); 
    136146    Expression *cloneMembers(); 
     
    152162    const char *kind(); 
    153163 
    154164    UnionDeclaration *isUnionDeclaration() { return this; } 
     165 
     166    // LDC, overload to reset offset to zero after each member 
     167    virtual void postMemberSemantic(Scope* sc); 
    155168}; 
    156169 
    157170// warning: two classes with the same base class share the same 
     
    216229    VarDeclaration *vthis;      // 'this' parameter if this class is nested 
    217230 
    218231    int inuse;              // to prevent recursive attempts 
     232 
     233    //LDC, for deferring 
     234    int deferState; 
    219235 
    220236    ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses); 
    221237    Dsymbol *syntaxCopy(Dsymbol *s); 
  • a/dmd/attrib.c

    old new  
    4343    : Dsymbol() 
    4444{ 
    4545    this->decl = decl; 
     46    member_semantic_started = false; 
     47    included_decls = NULL; 
    4648} 
    4749 
    4850Array *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd) 
     
    6567    return m; 
    6668} 
    6769 
     70// shares code with ScopeDsymbol::callSemanticOnMembers 
     71void 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 
    68138void AttribDeclaration::semantic(Scope *sc) 
    69139{ 
    70     Array *d = include(sc, NULL); 
     140    if (!included_decls) 
     141    included_decls = include(sc, NULL); 
    71142 
    72143    //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); 
    82145} 
    83146 
    84147void AttribDeclaration::semantic2(Scope *sc) 
     
    290353    if (stc & (STCauto | STCscope | STCstatic | STCextern)) 
    291354        sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern); 
    292355    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); 
    299357    sc->stc = stc_save; 
    300358    } 
    301359    else 
     
    364422    {   enum LINK linkage_save = sc->linkage; 
    365423 
    366424    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); 
    373426    sc->linkage = linkage_save; 
    374427    } 
    375428    else 
     
    454507 
    455508    sc->protection = protection; 
    456509    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); 
    463511    sc->protection = protection_save; 
    464512    sc->explicitProtection = explicitProtection_save; 
    465513    } 
     
    513561 
    514562    //printf("\tAlignDeclaration::semantic '%s'\n",toChars()); 
    515563    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); 
    534566    } 
    535567    else 
    536568    assert(0 && "what kind of align use triggers this?"); 
    537569} 
    538570 
     571void 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} 
    539586 
    540587void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 
    541588{ 
     
    550597{ 
    551598    this->loc = loc; 
    552599    this->isunion = isunion; 
    553     this->scope = NULL; 
    554600    this->sem = 0; 
     601 
     602    sc_offset = -1; 
    555603} 
    556604 
    557605Dsymbol *AnonDeclaration::syntaxCopy(Dsymbol *s) 
     
    563611    return ad; 
    564612} 
    565613 
     614// copied from StructDeclaration::isMemberReorderable 
     615bool AnonDeclaration::isMemberReorderable(Dsymbol* s) 
     616{ 
     617    if ( 
     618    s->isVarDeclaration() || 
     619    s->isAttribDeclaration() 
     620    ) 
     621    return false; 
     622    return true; 
     623} 
     624 
     625void AnonDeclaration::postMemberSemantic(Scope* sc) 
     626{ 
     627    if (isunion) 
     628    sc->offset = 0; 
     629} 
     630 
    566631void AnonDeclaration::semantic(Scope *sc) 
    567632{ 
    568633    //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     } 
    576634 
    577635    assert(sc->parent); 
    578636 
     
    587645 
    588646    if (decl) 
    589647    { 
    590     AnonymousAggregateDeclaration aad; 
    591648    int adisunion; 
    592649 
    593650    if (sc->anonAgg) 
     
    606663    sc->stc &= ~(STCauto | STCscope | STCstatic); 
    607664    sc->inunion = isunion; 
    608665    sc->offset = 0; 
     666    if (sc_offset >= 0) 
     667        sc->offset = sc_offset; 
     668  
    609669    sc->flags = 0; 
    610670    aad.structalign = sc->structalign; 
    611671    aad.parent = ad; 
    612672 
    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; 
    624679    } 
     680     
    625681    sc = sc->pop(); 
    626682 
    627     // If failed due to forward references, unwind and try again later 
    628     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     } 
    641683    if (sem == 0) 
    642684    {   Module::dprogress++; 
    643685        sem = 1; 
     
    13381380 
    13391381void StaticIfDeclaration::semantic(Scope *sc) 
    13401382{ 
    1341     Array *d = include(sc, sd); 
     1383    if (!included_decls) 
     1384    included_decls = include(sc, sd); 
    13421385 
    13431386    //printf("\tStaticIfDeclaration::semantic '%s', d = %p\n",toChars(), d); 
    1344     if (d
     1387    if (included_decls
    13451388    { 
    13461389    if (!addisdone) 
    13471390    {   AttribDeclaration::addMember(sc, sd, 1); 
    13481391        addisdone = 1; 
    13491392    } 
    13501393 
    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); 
    13571395    } 
    13581396} 
    13591397 
  • a/dmd/attrib.h

    old new  
    1616#endif /* __DMC__ */ 
    1717 
    1818#include "dsymbol.h" 
     19#include "aggregate.h" 
    1920 
    2021struct Expression; 
    2122struct Statement; 
     
    5253 
    5354    virtual void toObjFile(int multiobj);           // compile to .obj file 
    5455    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; } 
    5566}; 
    5667 
    5768struct StorageClassDeclaration: AttribDeclaration 
     
    94105    Dsymbol *syntaxCopy(Dsymbol *s); 
    95106    void semantic(Scope *sc); 
    96107    void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 
     108 
     109    void runSemantic(Dsymbol* s, Scope* sc); 
    97110}; 
    98111 
    99112struct AnonDeclaration : AttribDeclaration 
    100113{ 
    101114    int isunion; 
    102     Scope *scope;       // !=NULL means context to use 
    103115    int sem;            // 1 if successful semantic() 
    104116 
    105117    AnonDeclaration(Loc loc, int isunion, Array *decl); 
     
    110122 
    111123    // LDC 
    112124    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; 
    113130}; 
    114131 
    115132struct PragmaDeclaration : AttribDeclaration 
  • a/dmd/class.c

    old new  
    4040    if (baseclasses) 
    4141    this->baseclasses = *baseclasses; 
    4242    baseClass = NULL; 
     43 
     44    deferState = 0; 
    4345 
    4446    interfaces_dim = 0; 
    4547    interfaces = NULL; 
     
    216218void ClassDeclaration::semantic(Scope *sc) 
    217219{   int i; 
    218220    unsigned offset; 
     221    Scope scsave; 
     222    Scope *scx = NULL; 
    219223 
    220224    //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this); 
    221225    //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : ""); 
     
    223227 
    224228    //{ static int n;  if (++n == 20) *(char*)0=0; } 
    225229 
     230int continueAt = deferState; 
     231if (deferState > 0)  
     232    deferState = 0; 
     233switch (continueAt) { 
     234case 0: 
     235 
    226236    if (!ident)     // if anonymous class 
    227237    {   char *id = "__anonclass"; 
    228238 
    229239    ident = Identifier::generateId(id); 
    230240    } 
    231241 
    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; 
    236244 
    237    type = type->semantic(loc, sc); 
    238    handle = handle->semantic(loc, sc); 
    239     } 
     245    type = type->semantic(loc, sc); 
     246    handle = handle->semantic(loc, sc); 
     247 
    240248    if (!members)           // if forward reference 
    241249    {   //printf("\tclass '%s' is forward referenced\n", toChars()); 
    242250    return; 
    243251    } 
    244252    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 
    249255    } 
    250256    else 
    251257    symtab = new DsymbolTable(); 
    252258 
    253     Scope *scx = NULL; 
    254     if (scope) 
    255     {   sc = scope; 
    256     scx = scope;        // save so we don't make redundant copies 
    257     scope = NULL; 
    258     } 
    259259#ifdef IN_GCC 
    260260    methods.setDim(0); 
    261261#endif 
     
    286286        i++; 
    287287    } 
    288288 
     289case 1: 
    289290    // See if there's a base class as first in baseclasses[] 
    290291    if (baseclasses.dim) 
    291292    {   TypeClass *tc; 
     
    327328            goto L7; 
    328329            } 
    329330        } 
    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) 
    331332        { 
    332333            //error("forward reference of base class %s", baseClass->toChars()); 
    333334            // Forward reference of base class, try again later 
    334335            //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); 
    338338            return; 
     339            //throw new DeferException(loc, "forward reference of base class %s", tc->sym->toChars()); 
    339340        } 
    340341        else 
    341342        {   baseClass = tc->sym; 
     
    346347    } 
    347348    } 
    348349 
     350case 2: 
    349351    // Treat the remaining entries in baseclasses as interfaces 
    350352    // Check for errors, handle forward references 
    351353    for (i = (baseClass ? 1 : 0); i < baseclasses.dim; ) 
     
    388390        } 
    389391 
    390392        b->base = tc->sym; 
    391         if (!b->base->symtab || b->base->scope
     393        if (!b->base->symtab || b->base->deferState > 0
    392394        { 
    393395        //error("forward reference of base class %s", baseClass->toChars()); 
    394396        // Forward reference of base, try again later 
    395397        //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); 
    399400        return; 
     401        //throw new DeferException(loc, "forward reference of interface %s", baseClass->toChars()); 
    400402        } 
    401403    } 
    402404    i++; 
     
    532534    if (storage_class & STCabstract) 
    533535    isabstract = 1; 
    534536 
     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 
     551case 3: 
    535552    sc = sc->push(this); 
    536553    sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic | 
    537554         STCabstract | STCdeprecated); 
     
    552569    sc->protection = PROTpublic; 
    553570    sc->explicitProtection = 0; 
    554571    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 pointer 
    561     } 
    562     else 
    563     {   sc->offset = 2*PTRSIZE;     // allow room for vptr[] and monitor 
    564     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     } 
    575572 
    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; 
    583575 
     576    scsave = *sc; 
     577 
     578    try { 
     579    callSemanticOnMembers(sc); 
     580    } catch (DeferException* deferexc) { 
     581    sc_offset = sc->offset; 
     582    deferState = 3; 
    584583    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; 
    592585    } 
    593586 
    594587    //printf("\tsemantic('%s') successful\n", toChars()); 
     
    679672    } 
    680673#endif 
    681674    //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type); 
     675 
     676    deferState = -1; 
     677case -1: 
     678    break; 
     679default: 
     680    assert(0 && "deferState for classes must be between -1 and 3"); 
     681} // switch for deferred calling 
    682682} 
    683683 
    684684void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 
     
    775775    Dsymbol *s; 
    776776 
    777777    //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars()); 
    778     if (scope) 
    779     semantic(scope); 
     778    s = ScopeDsymbol::search(loc, ident, flags); 
    780779 
    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()); 
    785783    } 
    786784 
    787     s = ScopeDsymbol::search(loc, ident, flags); 
    788785    if (!s) 
    789786    { 
    790787    // Search bases classes in depth-first, left to right order 
     
    996993 
    997994void InterfaceDeclaration::semantic(Scope *sc) 
    998995{   int i; 
     996    Scope *scx = NULL; 
    999997 
     998int continueAt = deferState; 
     999if (deferState > 0) 
     1000    deferState = 0; 
     1001switch (continueAt) { 
     1002case 0: 
    10001003    //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); 
    10011004    if (inuse) 
    10021005    return; 
    1003     if (!scope) 
    1004     type = type->semantic(loc, sc); 
    1005    handle = handle->semantic(loc, sc); 
    1006     } 
     1006 
     1007    type = type->semantic(loc, sc); 
     1008    handle = handle->semantic(loc, sc); 
     1009 
    10071010    if (!members)           // if forward reference 
    10081011    {   //printf("\tinterface '%s' is forward referenced\n", toChars()); 
    10091012    return; 
    10101013    } 
    10111014    if (symtab)         // if already done 
    1012     {  if (!scope) 
    1013         return; 
     1015    { 
     1016    return; 
    10141017    } 
    10151018    else 
    10161019    symtab = new DsymbolTable(); 
    1017  
    1018     Scope *scx = NULL; 
    1019     if (scope) 
    1020     {   sc = scope; 
    1021     scx = scope;        // save so we don't make redundant copies 
    1022     scope = NULL; 
    1023     } 
    10241020 
    10251021    if (sc->stc & STCdeprecated) 
    10261022    { 
     
    10481044        i++; 
    10491045    } 
    10501046 
     1047case 1: 
    10511048    // Check for errors, handle forward references 
    10521049    for (i = 0; i < baseclasses.dim; ) 
    10531050    {   TypeClass *tc; 
     
    10841081        baseclasses.remove(i); 
    10851082        continue; 
    10861083        } 
    1087         if (!b->base->symtab || b->base->scope || b->base->inuse) 
     1084        if (!b->base->symtab || b->base->deferState > 0 || b->base->inuse) 
    10881085        { 
    10891086        //error("forward reference of base class %s", baseClass->toChars()); 
    10901087        // Forward reference of base, try again later 
    10911088        //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); 
    10951091        return; 
     1092        //throw new DeferException(loc, "forward reference of interface %s", baseClass->toChars()); 
    10961093        } 
    10971094    } 
    10981095    i++; 
     
    11421139    s->addMember(sc, this, 1); 
    11431140    } 
    11441141 
     1142case 2: 
    11451143    sc = sc->push(this); 
    11461144    sc->parent = this; 
    11471145    if (isCOMinterface()) 
     
    11491147    sc->structalign = 8; 
    11501148    structalign = sc->structalign; 
    11511149    sc->offset = 2*PTRSIZE; 
     1150    if (sc_offset >= 0) 
     1151    sc->offset = sc_offset; 
     1152 
    11521153    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; 
    11571163    } 
     1164 
    11581165    inuse--; 
    11591166    //members->print(); 
    11601167    sc->pop(); 
    11611168    //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); 
     1169 
     1170    deferState = -1; 
     1171case -1: 
     1172    break; 
     1173default: 
     1174    assert(0 && "deferState for interfaces must be between -1 and 2"); 
     1175} // switch for deferStatus 
    11621176} 
    11631177 
    11641178 
  • a/dmd/declaration.c

    old new  
    688688    int inferred = 0; 
    689689    if (!type) 
    690690    {   inuse++; 
    691     type = init->inferType(sc); 
     691    try { 
     692        type = init->inferType(sc); 
     693    } catch (DeferException* deferexc) { 
     694        inuse--; 
     695        throw deferexc; 
     696    } 
    692697    inuse--; 
    693698    inferred = 1; 
    694699 
     
    10091014        Expression *e; 
    10101015        Initializer *i2 = init; 
    10111016        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; 
    10211032        } 
    10221033        inuse--; 
    10231034        global.gag--; 
  • a/dmd/dsymbol.c

    old new  
    644644    symtab = NULL; 
    645645    imports = NULL; 
    646646    prots = NULL; 
     647    member_semantic_started = false; 
    647648} 
    648649 
    649650ScopeDsymbol::ScopeDsymbol(Identifier *id) 
     
    653654    symtab = NULL; 
    654655    imports = NULL; 
    655656    prots = NULL; 
     657    member_semantic_started = false; 
    656658} 
    657659 
    658660Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s) 
     
    765767        } 
    766768        } 
    767769    } 
    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    } 
    771780    } 
    772781} 
    773782 
     
    833842const char *ScopeDsymbol::kind() 
    834843{ 
    835844    return "ScopeDsymbol"; 
     845} 
     846 
     847// shares code with AttribDeclaration::callSemanticOnMembers 
     848void 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    } 
    836910} 
    837911 
    838912 
     
    10021076    return NULL; 
    10031077} 
    10041078 
    1005  
    10061079/****************************** DsymbolTable ******************************/ 
    10071080 
    10081081DsymbolTable::DsymbolTable() 
  • a/dmd/dsymbol.h

    old new  
    2020 
    2121#include "mars.h" 
    2222#include "arraytypes.h" 
     23#include <deque> 
    2324 
    2425// llvm 
    2526#include "../ir/irsymbol.h" 
     
    252253    void emitMemberComments(Scope *sc); 
    253254 
    254255    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; } 
    255263}; 
    256264 
    257265// With statement scope 
  • a/dmd/func.c

    old new  
    327327        break; 
    328328 
    329329        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()); 
    332331 
    333332        default: 
    334333        {   FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi]; 
     
    401400            break; 
    402401 
    403402        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()); 
    406404 
    407405        default: 
    408406        {   FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi]; 
     
    497495            } 
    498496            if (cov == 3) 
    499497            { 
    500             cd->sizeok = 2; // can't finish due to forward reference 
    501             return; 
     498            throw new DeferException(loc, "cannot finish due to forward reference"); 
    502499            } 
    503500        } 
    504501        } 
  • a/dmd/import.c

    old new  
    121121{ 
    122122    //printf("Import::semantic('%s')\n", toChars()); 
    123123 
    124     load(sc); 
     124    DeferException* defer = NULL; 
     125    try { 
     126    load(sc); 
     127    } catch (DeferException* exc) { 
     128    defer = exc; 
     129    } 
    125130 
    126131    if (mod) 
    127132    { 
     
    137142 
    138143    // Modules need a list of each imported module 
    139144    //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); 
    141151 
    142152    mod->semantic(); 
    143153 
     
    168178    } 
    169179    sc = sc->pop(); 
    170180    } 
     181 
     182    if (defer) 
     183    throw defer; 
    171184    //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg); 
    172185} 
    173186 
  • a/dmd/mars.c

    old new  
    11541154    m = (Module *)modules.data[i]; 
    11551155    if (global.params.verbose) 
    11561156        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    } 
    11581162    } 
    11591163    if (global.errors) 
    11601164    fatal(); 
  • a/dmd/module.c

    old new  
    5050DsymbolTable *Module::modules; 
    5151Array Module::amodules; 
    5252 
    53 Array Module::deferred;   // deferred Dsymbol's needing semantic() run on them 
     53std::deque<DeferredDsymbol> Module::deferred; // deferred Dsymbol's needing semantic() run on them 
    5454unsigned Module::dprogress; 
    5555 
    5656void Module::init() 
     
    130130    llvmForceLogging = false; 
    131131    this->doDocComment = doDocComment; 
    132132    this->doHdrGen = doHdrGen; 
     133    sc = NULL; 
    133134} 
    134135 
    135136File* Module::buildFilePath(char* forcename, char* path, char* ext) 
     
    620621void Module::semantic(Scope* unused_sc) 
    621622{   int i; 
    622623 
    623     if (semanticstarted) 
     624    // if already done or circular, bail out 
     625    if (semanticdone || semanticstarted == 1) 
    624626    return; 
    625627 
    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; 
    628632 
    629     // Note that modules get their own scope, from scratch. 
    630     // This is so regardless of where in the syntax a module 
    631     // gets imported, it is unaffected by context. 
    632     Scope *sc = Scope::createGlobal(this);    // create root scope 
     633   // 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 
    633637 
    634     //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage); 
     638   //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage); 
    635639 
    636     // Add import of "object" if this module isn't "object" 
    637     if (ident != Id::object) 
    638    
    639     Import *im = new Import(0, NULL, Id::object, NULL, 0); 
    640     members->shift(im); 
    641    
     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   
    642646 
    643     // Add all symbols into module's symbol table 
    644     symtab = new DsymbolTable(); 
    645     for (i = 0; i < members->dim; i++) 
    646     { Dsymbol *s; 
     647   // Add all symbols into module's symbol table 
     648   symtab = new DsymbolTable(); 
     649   for (i = 0; i < members->dim; i++) 
     650   {  Dsymbol *s; 
    647651 
    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    } 
    650655    } 
    651656 
    652657    // 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; 
    660663    } 
    661664 
    662665    sc = sc->pop(); 
    663666    sc->pop(); 
    664     semanticdone = semanticstarted; 
     667    semanticstarted = 1; 
     668    semanticdone = 1; 
    665669    //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); 
    666670} 
    667671 
    668672void Module::semantic2(Scope* unused_sc) 
    669673{   int i; 
    670674 
    671     if (deferred.dim
     675    if (!deferred.empty()
    672676    { 
    673     for (int i = 0; i < deferred.dim; i++) 
     677    for (int i = 0; i < deferred.size(); i++) 
    674678    { 
    675         Dsymbol *sd = (Dsymbol *)deferred.data[i]
     679        Dsymbol *sd = deferred[i].sym
    676680 
    677681        sd->error("unable to resolve forward reference in definition"); 
    678682    } 
     
    814818    s = ScopeDsymbol::search(loc, ident, flags); 
    815819    insearch = 0; 
    816820 
     821    if (!s && semanticstarted == -1) 
     822        error("Forward reference!"); 
     823 
    817824    searchCacheIdent = ident; 
    818825    searchCacheSymbol = s; 
    819826    searchCacheFlags = flags; 
     
    825832 * Can't run semantic on s now, try again later. 
    826833 */ 
    827834 
    828 void Module::addDeferredSemantic(Dsymbol *s
     835void Module::addDeferredSemantic(Dsymbol *sym, Scope *scope
    829836{ 
    830837    // 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++) 
    832839    { 
    833     Dsymbol *sd = (Dsymbol *)deferred.data[i]
     840    Dsymbol *sd = (Dsymbol *)deferred[i].sym
    834841 
    835     if (sd == s
     842    if (sd == sym
    836843        return; 
    837844    } 
    838845 
     846    // copy scope 
     847    Scope* scx = new Scope(*scope); 
     848    scx->setNoFree(); 
     849 
    839850    //printf("Module::addDeferredSemantic('%s')\n", s->toChars()); 
    840     deferred.push(s); 
     851    deferred.push_back(DeferredDsymbol(sym, scx)); 
    841852} 
    842853 
    843854 
     
    847858 
    848859void Module::runDeferredSemantic() 
    849860{ 
    850     size_t len
     861    //if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim)
    851862 
    852863    static int nested; 
    853864    if (nested) 
    854865    return; 
    855     //if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); 
    856866    nested++; 
    857867 
    858     do 
    859     { 
    860     dprogress = 0; 
    861     len = deferred.dim; 
    862     if (!len) 
    863         break; 
     868    int failed = 0; 
    864869 
    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; 
    870892    } 
    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; 
    875907    } 
    876     memcpy(todo, deferred.data, len * sizeof(Dsymbol *)); 
    877     deferred.setDim(0); 
     908    } 
    878909 
    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 progress 
    888910    nested--; 
    889911    //printf("-Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); 
    890912} 
  • a/dmd/module.h

    old new  
    1717 
    1818#include "root.h" 
    1919#include "dsymbol.h" 
     20#include <deque> 
    2021 
    2122struct ModuleInfoDeclaration; 
    2223struct ClassDeclaration; 
     
    3839#endif 
    3940#endif 
    4041 
     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. 
     46struct DeferredDsymbol 
     47{ 
     48    DeferredDsymbol(Dsymbol* sym_, Scope* scope_) 
     49    : sym(sym_), scope(scope_) {} 
     50 
     51    Dsymbol* sym; 
     52    Scope* scope; 
     53}; 
     54 
    4155struct Package : ScopeDsymbol 
    4256{ 
    4357    Package(Identifier *ident); 
     
    5569    static Module *rootModule; 
    5670    static DsymbolTable *modules;   // symbol table of all modules 
    5771    static Array amodules;      // array of all modules 
    58     static Array deferred;    // deferred Dsymbol's needing semantic() run on them 
     72    static std::deque<DeferredDsymbol> deferred;  // deferred Dsymbol's needing semantic() run on them 
    5973    static unsigned dprogress;  // progress resolving the deferred list 
    6074    static void init(); 
    6175 
     
    139153    int needModuleInfo(); 
    140154    Dsymbol *search(Loc loc, Identifier *ident, int flags); 
    141155    void deleteObjFile(); 
    142     void addDeferredSemantic(Dsymbol *s); 
     156    void addDeferredSemantic(Dsymbol *sym, Scope* scope); 
    143157    void runDeferredSemantic(); 
    144158    int imports(Module *m); 
    145159 
     
    179193 
    180194    // array ops emitted in this module already 
    181195    StringTable arrayfuncs; 
     196 
     197    // LDC 
     198    virtual void postMemberSemantic(Scope* sc) { runDeferredSemantic(); } 
     199    Scope* sc; 
    182200}; 
    183201 
    184202 
  • a/dmd/mtype.c

    old new  
    39603960#ifdef DEBUG 
    39613961    printf("2: "); 
    39623962#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()); 
    39643965    return tint32; 
    39653966    } 
    39663967    return sym->memtype->toBasetype(); 
     
    46454646Type *TypeClass::semantic(Loc loc, Scope *sc) 
    46464647{ 
    46474648    //printf("TypeClass::semantic(%s)\n", sym->toChars()); 
    4648     if (sym->scope) 
    4649     sym->semantic(sym->scope); 
    46504649    return merge(); 
    46514650} 
    46524651 
  • a/dmd/root.c

    old new  
    148148    exit(EXIT_FAILURE); 
    149149} 
    150150#endif 
     151 
     152DeferException::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} 
    151164 
    152165void error_mem() 
    153166{ 
  • a/dmd/root.h

    old new  
    3232void error(const char *format, ...); 
    3333void error(const wchar_t *format, ...); 
    3434void warning(const char *format, ...); 
     35 
     36struct 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. 
     43struct DeferException 
     44{ 
     45    char* errormessage; 
     46    DeferException(Loc& loc, const char* format, ...); 
     47}; 
    3548 
    3649#ifndef TYPEDEFS 
    3750#define TYPEDEFS 
  • a/dmd/struct.c

    old new  
    4343 
    4444    stag = NULL; 
    4545    sinit = NULL; 
    46     scope = NULL; 
     46 
     47    sc_offset = -1; 
    4748} 
    4849 
    4950enum PROT AggregateDeclaration::prot() 
     
    5455void AggregateDeclaration::semantic2(Scope *sc) 
    5556{ 
    5657    //printf("AggregateDeclaration::semantic2(%s)\n", toChars()); 
    57     if (scope) 
    58     {   error("has forward references"); 
    59     return; 
    60     } 
    6158    if (members) 
    6259    { 
    6360    sc = sc->push(this); 
     
    171168 
    172169    if (ts->sym->sizeok != 1) 
    173170    { 
    174         sizeok = 2;        // cannot finish; flag as forward referenced 
    175         return
     171        sizeok = 2; 
     172        throw new DeferException(v->loc, "forward reference to struct %s", v->toChars())
    176173    } 
    177174    } 
    178175    if (t->ty == Tident) 
    179176    { 
    180     sizeok = 2;        // cannot finish; flag as forward referenced 
    181     return
     177    sizeok = 2; 
     178    throw new DeferException(v->loc, "forward reference to %s", v->toChars())
    182179    } 
    183180 
    184181    memsize = v->type->size(loc); 
     
    210207 
    211208    // For forward references 
    212209    type = new TypeStruct(this); 
     210 
     211    // LDC 
     212    deferState = 0; 
    213213} 
    214214 
    215215Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s) 
     
    227227void StructDeclaration::semantic(Scope *sc) 
    228228{   int i; 
    229229    Scope *sc2; 
    230  
     230    Identifier* id; 
     231    Scope *scx = NULL; 
    231232    //printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars()); 
    232233 
    233234    //static int count; if (++count == 20) *(char*)0=0; 
    234235 
     236int continueAt = deferState; 
     237if (deferState > 0) 
     238    deferState = 0; 
     239switch (continueAt) { 
     240case 0: 
    235241    assert(type); 
    236242    if (!members)           // if forward reference 
    237243    return; 
    238244 
    239245    if (symtab) 
    240     {   if (!scope) 
    241             return;             // semantic() already completed 
     246    { 
     247   return;             // semantic() already completed 
    242248    } 
    243249    else 
    244250        symtab = new DsymbolTable(); 
    245  
    246     Scope *scx = NULL; 
    247     if (scope) 
    248     {   sc = scope; 
    249         scx = scope;            // save so we don't make redundant copies 
    250         scope = NULL; 
    251     } 
    252251 
    253252    parent = sc->parent; 
    254253    handle = type->pointerTo(); 
     
    270269    } 
    271270    } 
    272271 
     272case 1: 
    273273    sizeok = 0; 
    274274    sc2 = sc->push(this); 
    275275    sc2->stc = 0; 
     
    279279    sc2->protection = PROTpublic; 
    280280    sc2->explicitProtection = 0; 
    281281 
    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; 
    293294    } 
    294 #endif 
     295    else 
     296        throw deferexc; 
    295297    } 
    296  
    297298    /* The TypeInfo_Struct is expecting an opEquals and opCmp with 
    298299     * a parameter that is a pointer to the struct. But if there 
    299300     * isn't one, but is an opEquals or opCmp with a value, write 
     
    321322    tfeq = (TypeFunction *)tfeq->semantic(0, sc); 
    322323    } 
    323324 
    324     Identifier *id = Id::eq; 
    325     for (int i = 0; i < 2; i++) 
     325    id = Id::eq; 
     326    for (i = 0; i < 2; i++) 
    326327    { 
    327328    Dsymbol *s = search_function(this, id); 
    328329    FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL; 
     
    354355 
    355356 
    356357    sc2->pop(); 
    357  
    358     if (sizeok == 2) 
    359     {   // semantic() failed because of forward references. 
    360     // Unwind what we did, and defer it for later 
    361     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     } 
    372358 
    373359    // 0 sized struct's are set to 1 byte 
    374360    if (structsize == 0) 
     
    423409    semantic2(sc); 
    424410    semantic3(sc); 
    425411    } 
     412    deferState = -1; 
     413case -1: 
     414    break; 
     415default: 
     416    assert(0 && "deferState for structs must be between -1 and 1"); 
     417} // switch for deferring 
    426418} 
    427419 
    428420void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 
     
    457449    return "struct"; 
    458450} 
    459451 
     452Dsymbol *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 
     467bool StructDeclaration::isMemberReorderable(Dsymbol* s) 
     468{ 
     469    if ( 
     470    s->isVarDeclaration() || 
     471    s->isAttribDeclaration() 
     472    ) 
     473    return false; 
     474    return true; 
     475} 
     476 
    460477/********************************* UnionDeclaration ****************************/ 
    461478 
    462479UnionDeclaration::UnionDeclaration(Loc loc, Identifier *id) 
     
    482499    return "union"; 
    483500} 
    484501 
    485  
     502void UnionDeclaration::postMemberSemantic(Scope* sc) 
     503
     504    sc->offset = 0; 
     505
  • a/dmd/template.c

    old new  
    28772877    // LDC 
    28782878    this->tinst = NULL; 
    28792879    this->tmodule = NULL; 
     2880    this->deferState = 0; 
    28802881} 
    28812882 
    28822883/***************** 
     
    29082909    // LDC 
    29092910    this->tinst = NULL; 
    29102911    this->tmodule = NULL; 
     2912    this->deferState = 0; 
    29112913 
    29122914    assert((size_t)tempdecl->scope > 0x10000); 
    29132915} 
     
    29532955 
    29542956void TemplateInstance::semantic(Scope *sc) 
    29552957{ 
     2958    int memnum = 0; 
     2959    int dosemantic3 = 0; 
     2960    unsigned errorsave; 
     2961    int tempdecl_instance_idx; 
     2962 
     2963int continueAt = deferState; 
     2964if (deferState > 0) 
     2965    deferState = 0; 
     2966switch (continueAt) { 
     2967case 0: 
    29562968    if (global.errors) 
    29572969    { 
    29582970    if (!global.gag) 
     
    30163028    semanticTiargs(sc); 
    30173029 
    30183030    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    } 
    30213039    if (!tempdecl || global.errors) 
    30223040    {   inst = this; 
    30233041        //printf("error return %p, %d\n", tempdecl, global.errors); 
     
    30703088#if LOG 
    30713089    printf("\timplement template instance '%s'\n", toChars()); 
    30723090#endif 
    3073     unsigned errorsave = global.errors; 
     3091    errorsave = global.errors; 
    30743092    inst = this; 
    3075     int tempdecl_instance_idx = tempdecl->instances.dim; 
     3093    tempdecl_instance_idx = tempdecl->instances.dim; 
    30763094    tempdecl->instances.push(this); 
    30773095    parent = tempdecl->parent; 
    30783096    //printf("parent = '%s'\n", parent->kind()); 
     
    30883106    // Add 'this' to the enclosing scope's members[] so the semantic routines 
    30893107    // will get called on the instance members 
    30903108#if 1 
    3091     int dosemantic3 = 0; 
    30923109    {   Array *a; 
    30933110 
    30943111    Scope *scx = sc; 
     
    31343151    // Copy the syntax trees from the TemplateDeclaration 
    31353152    members = Dsymbol::arraySyntaxCopy(tempdecl->members); 
    31363153 
     3154case 1: 
     3155    semanticdone = 1; 
    31373156    // Create our own scope for the template parameters 
    3138     Scope *scope = tempdecl->scope; 
     3157    scope = tempdecl->scope; 
    31393158    if (!scope) 
    31403159    { 
    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()); 
    31433163    } 
    31443164 
    31453165#if LOG 
     
    31553175    // Add members of template instance to template instance symbol table 
    31563176//    parent = scope->scopesym; 
    31573177    symtab = new DsymbolTable(); 
    3158     int memnum = 0; 
    31593178    for (int i = 0; i < members->dim; i++) 
    31603179    { 
    31613180    Dsymbol *s = (Dsymbol *)members->data[i]; 
     
    31933212#if LOG 
    31943213    printf("\tdo semantic() on template instance members '%s'\n", toChars()); 
    31953214#endif 
    3196     Scope *sc2; 
    31973215    sc2 = scope->push(this); 
    31983216    //printf("isnested = %d, sc->parent = %s\n", isnested, sc->parent->toChars()); 
    31993217    sc2->parent = /*isnested ? sc->parent :*/ this; 
    32003218    sc2->tinst = this; 
    32013219 
    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 
     3220case 2: 
     3221    semanticdone = 1; 
     3222    try { 
     3223    callSemanticOnMembers(sc2); 
     3224    } catch (DeferException* deferexc) { 
     3225    deferState = 2; 
     3226    semanticdone = 0; 
     3227    throw deferexc; 
     3228    } 
    32313229 
    32323230    /* If any of the instantiation members didn't get semantic() run 
    32333231     * on them due to forward references, we cannot run semantic2() 
    32343232     * or semantic3() yet. 
    32353233     */ 
    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
    32383236 
    32393237    if (sd->parent == this) 
    32403238        goto Laftersemantic; 
     
    32763274#if LOG 
    32773275    printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); 
    32783276#endif 
     3277 
     3278    deferState = -1; 
     3279case -1: 
     3280    break; 
     3281default: 
     3282    assert(0 && "deferState for template instances must be between -1 and 2"); 
     3283} // switch for deferring 
    32793284} 
    32803285 
    32813286 
     
    35213526    dedtypes.zero(); 
    35223527    if (!td->scope) 
    35233528    { 
    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()); 
    35263530    } 
    35273531    m = td->matchWithInstance(this, &dedtypes, 0); 
    35283532    //printf("matchWithInstance = %d\n", m); 
     
    40124016    } 
    40134017} 
    40144018 
     4019void TemplateInstance::postMemberSemantic(Scope *sc) 
     4020{ 
     4021    sc->module->runDeferredSemantic(); 
     4022} 
     4023 
    40154024/* ======================== TemplateMixin ================================ */ 
    40164025 
    40174026TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual, 
     
    40244033    this->idents = idents; 
    40254034    this->tiargs = tiargs ? tiargs : new Objects(); 
    40264035    this->scope = NULL; 
     4036    this->deferState = 0; 
    40274037} 
    40284038 
    40294039Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s) 
     
    40534063 
    40544064void TemplateMixin::semantic(Scope *sc) 
    40554065{ 
     4066    unsigned errorsave; 
     4067 
     4068int continueAt = deferState; 
     4069if (deferState > 0) 
     4070    deferState = 0; 
     4071switch (continueAt) { 
     4072case 0: 
     4073 
    40564074#if LOG 
    40574075    printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this); 
    40584076    fflush(stdout); 
     
    40784096    util_progress(); 
    40794097#endif 
    40804098 
    4081     Scope *scx = NULL; 
     4099    scx = NULL; 
    40824100    if (scope) 
    40834101    {   sc = scope; 
    40844102    scx = scope;        // save so we don't make redundant copies 
     
    41534171         */ 
    41544172        semanticdone = 0; 
    41554173        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()); 
    41674181    } 
    41684182    } 
    41694183 
     
    42514265#if LOG 
    42524266    printf("\tcreate scope for template parameters '%s'\n", toChars()); 
    42534267#endif 
    4254     Scope *scy = sc; 
     4268    scy = sc; 
    42554269    scy = sc->push(this); 
    42564270    scy->parent = this; 
    42574271 
    42584272    argsym = new ScopeDsymbol(); 
    42594273    argsym->parent = scy->parent; 
    4260     Scope *scope = scy->push(argsym); 
    4261  
    4262     unsigned errorsave = global.errors; 
     4274    scope = scy->push(argsym); 
     4275 
     4276    errorsave = global.errors; 
    42634277 
    42644278    // Declare each template parameter as an alias for the argument type 
    42654279    declareParameters(scope); 
     
    42794293#if LOG 
    42804294    printf("\tdo semantic() on template instance members '%s'\n", toChars()); 
    42814295#endif 
    4282     Scope *sc2; 
    42834296    sc2 = scope->push(this); 
    42844297    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 
     4299case 1: 
     4300    try { 
     4301    callSemanticOnMembers(sc2); 
     4302    } catch (DeferException* deferexc) { 
     4303    deferState = 1; 
     4304    semanticdone = 0; 
     4305    throw deferexc; 
    42894306    } 
    42904307    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    } 
    42914318 
    42924319    /* The problem is when to parse the initializer for a variable. 
    42934320     * Perhaps VarDeclaration::semantic() should do it like it does 
     
    43194346#if LOG 
    43204347    printf("-TemplateMixin::semantic('%s', this=%p)\n", toChars(), this); 
    43214348#endif 
     4349 
     4350    deferState = -1; 
     4351case -1: 
     4352    break; 
     4353default: 
     4354    assert(0 && "deferState for template mixins must be between -1 and 1"); 
     4355} // switch for deferring 
    43224356} 
    43234357 
    43244358void TemplateMixin::semantic2(Scope *sc) 
  • a/dmd/template.h

    old new  
    328328    TemplateInstance *tinst; // enclosing template instance 
    329329    Module* tmodule; // module from outermost enclosing template instantiation 
    330330    void printInstantiationTrace(); 
     331 
     332    void postMemberSemantic(Scope* sc); 
     333    int deferState; 
     334    Scope *sc2; 
     335    Scope *scope; 
    331336}; 
    332337 
    333338struct TemplateMixin : TemplateInstance 
     
    353358    void toObjFile(int multiobj);           // compile to .obj file 
    354359 
    355360    TemplateMixin *isTemplateMixin() { return this; } 
     361 
     362    // LDC 
     363    int deferState; 
     364    Scope *sc2, *scy, *scx; 
    356365}; 
    357366 
    358367Expression *isExpression(Object *o); 
Copyright © 2008, LDC Development Team.