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

Ticket #125: forwardref-new2.diff

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

update to forward ref patch to apply cleanly against [878]

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

    old new  
    616616    symtab = NULL; 
    617617    imports = NULL; 
    618618    prots = NULL; 
     619    member_semantic_started = false; 
    619620} 
    620621 
    621622ScopeDsymbol::ScopeDsymbol(Identifier *id) 
     
    625626    symtab = NULL; 
    626627    imports = NULL; 
    627628    prots = NULL; 
     629    member_semantic_started = false; 
    628630} 
    629631 
    630632Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s) 
     
    737739        } 
    738740        } 
    739741    } 
    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    } 
    743752    } 
    744753} 
    745754 
     
    805814const char *ScopeDsymbol::kind() 
    806815{ 
    807816    return "ScopeDsymbol"; 
     817} 
     818 
     819// shares code with AttribDeclaration::callSemanticOnMembers 
     820void 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    } 
    808882} 
    809883 
    810884 
     
    9741048    return NULL; 
    9751049} 
    9761050 
    977  
    9781051/****************************** DsymbolTable ******************************/ 
    9791052 
    9801053DsymbolTable::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" 
     
    251252    void emitMemberComments(Scope *sc); 
    252253 
    253254    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; } 
    254262}; 
    255263 
    256264// With statement scope 
  • a/dmd/func.c

    old new  
    326326        break; 
    327327 
    328328        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()); 
    331330 
    332331        default: 
    333332        {   FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi]; 
     
    400399            break; 
    401400 
    402401        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()); 
    405403 
    406404        default: 
    407405        {   FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi]; 
     
    496494            } 
    497495            if (cov == 3) 
    498496            { 
    499             cd->sizeok = 2; // can't finish due to forward reference 
    500             return; 
     497            throw new DeferException(loc, "cannot finish due to forward reference"); 
    501498            } 
    502499        } 
    503500        } 
  • 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  
    11511151    m = (Module *)modules.data[i]; 
    11521152    if (global.params.verbose) 
    11531153        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    } 
    11551159    } 
    11561160    if (global.errors) 
    11571161    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  
    39573957#ifdef DEBUG 
    39583958    printf("2: "); 
    39593959#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()); 
    39613962    return tint32; 
    39623963    } 
    39633964    return sym->memtype->toBasetype(); 
     
    46444645Type *TypeClass::semantic(Loc loc, Scope *sc) 
    46454646{ 
    46464647    //printf("TypeClass::semantic(%s)\n", sym->toChars()); 
    4647     if (sym->scope) 
    4648     sym->semantic(sym->scope); 
    46494648    return merge(); 
    46504649} 
    46514650 
  • 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  
    28742874    this->isnested = NULL; 
    28752875    this->errors = 0; 
    28762876    this->tinst = NULL; 
     2877    this->deferState = 0; 
    28772878} 
    28782879 
    28792880/***************** 
     
    29022903    this->isnested = NULL; 
    29032904    this->errors = 0; 
    29042905    this->tinst = NULL; 
     2906    this->deferState = 0; 
    29052907 
    29062908    assert((size_t)tempdecl->scope > 0x10000); 
    29072909} 
     
    29472949 
    29482950void TemplateInstance::semantic(Scope *sc) 
    29492951{ 
     2952    int memnum = 0; 
     2953    int dosemantic3 = 0; 
     2954    unsigned errorsave; 
     2955    int tempdecl_instance_idx; 
     2956 
     2957int continueAt = deferState; 
     2958if (deferState > 0) 
     2959    deferState = 0; 
     2960switch (continueAt) { 
     2961case 0: 
    29502962    if (global.errors) 
    29512963    { 
    29522964    if (!global.gag) 
     
    30033015    semanticTiargs(sc); 
    30043016 
    30053017    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    } 
    30083026    if (!tempdecl || global.errors) 
    30093027    {   inst = this; 
    30103028        //printf("error return %p, %d\n", tempdecl, global.errors); 
     
    30573075#if LOG 
    30583076    printf("\timplement template instance '%s'\n", toChars()); 
    30593077#endif 
    3060     unsigned errorsave = global.errors; 
     3078    errorsave = global.errors; 
    30613079    inst = this; 
    3062     int tempdecl_instance_idx = tempdecl->instances.dim; 
     3080    tempdecl_instance_idx = tempdecl->instances.dim; 
    30633081    tempdecl->instances.push(this); 
    30643082    parent = tempdecl->parent; 
    30653083    //printf("parent = '%s'\n", parent->kind()); 
     
    30753093    // Add 'this' to the enclosing scope's members[] so the semantic routines 
    30763094    // will get called on the instance members 
    30773095#if 1 
    3078     int dosemantic3 = 0; 
    30793096    {   Array *a; 
    30803097 
    30813098    Scope *scx = sc; 
     
    31213138    // Copy the syntax trees from the TemplateDeclaration 
    31223139    members = Dsymbol::arraySyntaxCopy(tempdecl->members); 
    31233140 
     3141case 1: 
     3142    semanticdone = 1; 
    31243143    // Create our own scope for the template parameters 
    3125     Scope *scope = tempdecl->scope; 
     3144    scope = tempdecl->scope; 
    31263145    if (!scope) 
    31273146    { 
    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()); 
    31303150    } 
    31313151 
    31323152#if LOG 
     
    31423162    // Add members of template instance to template instance symbol table 
    31433163//    parent = scope->scopesym; 
    31443164    symtab = new DsymbolTable(); 
    3145     int memnum = 0; 
    31463165    for (int i = 0; i < members->dim; i++) 
    31473166    { 
    31483167    Dsymbol *s = (Dsymbol *)members->data[i]; 
     
    31803199#if LOG 
    31813200    printf("\tdo semantic() on template instance members '%s'\n", toChars()); 
    31823201#endif 
    3183     Scope *sc2; 
    31843202    sc2 = scope->push(this); 
    31853203    //printf("isnested = %d, sc->parent = %s\n", isnested, sc->parent->toChars()); 
    31863204    sc2->parent = /*isnested ? sc->parent :*/ this; 
    31873205    sc2->tinst = this; 
    31883206 
    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 
     3207case 2: 
     3208    semanticdone = 1; 
     3209    try { 
     3210    callSemanticOnMembers(sc2); 
     3211    } catch (DeferException* deferexc) { 
     3212    deferState = 2; 
     3213    semanticdone = 0; 
     3214    throw deferexc; 
     3215    } 
    32183216 
    32193217    /* If any of the instantiation members didn't get semantic() run 
    32203218     * on them due to forward references, we cannot run semantic2() 
    32213219     * or semantic3() yet. 
    32223220     */ 
    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
    32253223 
    32263224    if (sd->parent == this) 
    32273225        goto Laftersemantic; 
     
    32633261#if LOG 
    32643262    printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); 
    32653263#endif 
     3264 
     3265    deferState = -1; 
     3266case -1: 
     3267    break; 
     3268default: 
     3269    assert(0 && "deferState for template instances must be between -1 and 2"); 
     3270} // switch for deferring 
    32663271} 
    32673272 
    32683273 
     
    35083513    dedtypes.zero(); 
    35093514    if (!td->scope) 
    35103515    { 
    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()); 
    35133517    } 
    35143518    m = td->matchWithInstance(this, &dedtypes, 0); 
    35153519    //printf("matchWithInstance = %d\n", m); 
     
    39994003    } 
    40004004} 
    40014005 
     4006void TemplateInstance::postMemberSemantic(Scope *sc) 
     4007{ 
     4008    sc->module->runDeferredSemantic(); 
     4009} 
     4010 
    40024011/* ======================== TemplateMixin ================================ */ 
    40034012 
    40044013TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual, 
     
    40114020    this->idents = idents; 
    40124021    this->tiargs = tiargs ? tiargs : new Objects(); 
    40134022    this->scope = NULL; 
     4023    this->deferState = 0; 
    40144024} 
    40154025 
    40164026Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s) 
     
    40404050 
    40414051void TemplateMixin::semantic(Scope *sc) 
    40424052{ 
     4053    unsigned errorsave; 
     4054 
     4055int continueAt = deferState; 
     4056if (deferState > 0) 
     4057    deferState = 0; 
     4058switch (continueAt) { 
     4059case 0: 
     4060 
    40434061#if LOG 
    40444062    printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this); 
    40454063    fflush(stdout); 
     
    40654083    util_progress(); 
    40664084#endif 
    40674085 
    4068     Scope *scx = NULL; 
     4086    scx = NULL; 
    40694087    if (scope) 
    40704088    {   sc = scope; 
    40714089    scx = scope;        // save so we don't make redundant copies 
     
    41404158         */ 
    41414159        semanticdone = 0; 
    41424160        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()); 
    41544168    } 
    41554169    } 
    41564170 
     
    42384252#if LOG 
    42394253    printf("\tcreate scope for template parameters '%s'\n", toChars()); 
    42404254#endif 
    4241     Scope *scy = sc; 
     4255    scy = sc; 
    42424256    scy = sc->push(this); 
    42434257    scy->parent = this; 
    42444258 
    42454259    argsym = new ScopeDsymbol(); 
    42464260    argsym->parent = scy->parent; 
    4247     Scope *scope = scy->push(argsym); 
    4248  
    4249     unsigned errorsave = global.errors; 
     4261    scope = scy->push(argsym); 
     4262 
     4263    errorsave = global.errors; 
    42504264 
    42514265    // Declare each template parameter as an alias for the argument type 
    42524266    declareParameters(scope); 
     
    42664280#if LOG 
    42674281    printf("\tdo semantic() on template instance members '%s'\n", toChars()); 
    42684282#endif 
    4269     Scope *sc2; 
    42704283    sc2 = scope->push(this); 
    42714284    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 
     4286case 1: 
     4287    try { 
     4288    callSemanticOnMembers(sc2); 
     4289    } catch (DeferException* deferexc) { 
     4290    deferState = 1; 
     4291    semanticdone = 0; 
     4292    throw deferexc; 
    42764293    } 
    42774294    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    } 
    42784305 
    42794306    /* The problem is when to parse the initializer for a variable. 
    42804307     * Perhaps VarDeclaration::semantic() should do it like it does 
     
    43064333#if LOG 
    43074334    printf("-TemplateMixin::semantic('%s', this=%p)\n", toChars(), this); 
    43084335#endif 
     4336 
     4337    deferState = -1; 
     4338case -1: 
     4339    break; 
     4340default: 
     4341    assert(0 && "deferState for template mixins must be between -1 and 1"); 
     4342} // switch for deferring 
    43094343} 
    43104344 
    43114345void TemplateMixin::semantic2(Scope *sc) 
  • a/dmd/template.h

    old new  
    325325    AliasDeclaration *isAliasDeclaration(); 
    326326 
    327327    // LDC 
     328    void postMemberSemantic(Scope* sc); 
    328329    TemplateInstance *tinst; // enclosing template instance 
    329330    void printInstantiationTrace(); 
     331    int deferState; 
     332    Scope *sc2; 
     333    Scope *scope; 
    330334}; 
    331335 
    332336struct TemplateMixin : TemplateInstance 
     
    352356    void toObjFile(int multiobj);           // compile to .obj file 
    353357 
    354358    TemplateMixin *isTemplateMixin() { return this; } 
     359 
     360    // LDC 
     361    int deferState; 
     362    Scope *sc2, *scy, *scx; 
    355363}; 
    356364 
    357365Expression *isExpression(Object *o); 
Copyright © 2008, LDC Development Team.