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

Ticket #125: forwardref-new.diff

File forwardref-new.diff, 51.5 kB (added by ChristianK, 13 years ago)

patch

  • 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) 
     
    296359    if (stc & (STCauto | STCscope | STCstatic | STCextern)) 
    297360        sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern); 
    298361    sc->stc |= stc; 
    299     for (unsigned i = 0; i < decl->dim; i++) 
    300     { 
    301         Dsymbol *s = (Dsymbol *)decl->data[i]; 
    302  
    303         s->semantic(sc); 
    304     } 
     362    callSemanticOnMembers(sc, decl); 
    305363    sc->stc = stc_save; 
    306364    } 
    307365    else 
     
    370428    {   enum LINK linkage_save = sc->linkage; 
    371429 
    372430    sc->linkage = linkage; 
    373     for (unsigned i = 0; i < decl->dim; i++) 
    374     { 
    375         Dsymbol *s = (Dsymbol *)decl->data[i]; 
    376  
    377         s->semantic(sc); 
    378     } 
     431    callSemanticOnMembers(sc, decl); 
    379432    sc->linkage = linkage_save; 
    380433    } 
    381434    else 
     
    460513 
    461514    sc->protection = protection; 
    462515    sc->explicitProtection = 1; 
    463     for (unsigned i = 0; i < decl->dim; i++) 
    464     { 
    465         Dsymbol *s = (Dsymbol *)decl->data[i]; 
    466  
    467         s->semantic(sc); 
    468     } 
     516    callSemanticOnMembers(sc, decl); 
    469517    sc->protection = protection_save; 
    470518    sc->explicitProtection = explicitProtection_save; 
    471519    } 
     
    519567 
    520568    //printf("\tAlignDeclaration::semantic '%s'\n",toChars()); 
    521569    if (decl) 
    522     {   unsigned salign_save = sc->structalign; 
    523  
    524     for (unsigned i = 0; i < decl->dim; i++) 
    525     { 
    526         Dsymbol *s = (Dsymbol *)decl->data[i]; 
    527  
    528         if (s->isStructDeclaration() && salign == 1) 
    529         { 
    530             sc->structalign = salign; 
    531             s->semantic(sc); 
    532             sc->structalign = salign_save; 
    533         } 
    534         else 
    535         { 
    536             s->semantic(sc); 
    537         } 
    538     } 
    539     sc->structalign = salign_save; 
     570    {    
     571    callSemanticOnMembers(sc, decl); 
    540572    } 
    541573    else 
    542574    assert(0 && "what kind of align use triggers this?"); 
    543575} 
    544576 
     577void AlignDeclaration::runSemantic(Dsymbol* s, Scope* sc) 
     578{ 
     579    unsigned salign_save = sc->structalign; 
     580 
     581    if (s->isStructDeclaration() && salign == 1) 
     582    { 
     583    sc->structalign = salign; 
     584    s->semantic(sc); 
     585    sc->structalign = salign_save; 
     586    } 
     587    else 
     588    { 
     589    s->semantic(sc); 
     590    } 
     591} 
    545592 
    546593void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 
    547594{ 
     
    556603{ 
    557604    this->loc = loc; 
    558605    this->isunion = isunion; 
    559     this->scope = NULL; 
    560606    this->sem = 0; 
     607 
     608    sc_offset = -1; 
    561609} 
    562610 
    563611Dsymbol *AnonDeclaration::syntaxCopy(Dsymbol *s) 
     
    569617    return ad; 
    570618} 
    571619 
     620// copied from StructDeclaration::isMemberReorderable 
     621bool AnonDeclaration::isMemberReorderable(Dsymbol* s) 
     622{ 
     623    if ( 
     624    s->isVarDeclaration() || 
     625    s->isAttribDeclaration() 
     626    ) 
     627    return false; 
     628    return true; 
     629} 
     630 
     631void AnonDeclaration::postMemberSemantic(Scope* sc) 
     632{ 
     633    if (isunion) 
     634    sc->offset = 0; 
     635} 
     636 
    572637void AnonDeclaration::semantic(Scope *sc) 
    573638{ 
    574639    //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this); 
    575  
    576     Scope *scx = NULL; 
    577     if (scope) 
    578     {   sc = scope; 
    579     scx = scope; 
    580     scope = NULL; 
    581     } 
    582640 
    583641    assert(sc->parent); 
    584642 
     
    593651 
    594652    if (decl) 
    595653    { 
    596     AnonymousAggregateDeclaration aad; 
    597654    int adisunion; 
    598655 
    599656    if (sc->anonAgg) 
     
    612669    sc->stc &= ~(STCauto | STCscope | STCstatic); 
    613670    sc->inunion = isunion; 
    614671    sc->offset = 0; 
     672    if (sc_offset >= 0) 
     673        sc->offset = sc_offset; 
     674  
    615675    sc->flags = 0; 
    616676    aad.structalign = sc->structalign; 
    617677    aad.parent = ad; 
    618     for (unsigned i = 0; i < decl->dim; i++) 
    619     { 
    620         Dsymbol *s = (Dsymbol *)decl->data[i]; 
    621  
    622         s->semantic(sc); 
    623         if (isunion) 
    624         sc->offset = 0; 
    625         if (aad.sizeok == 2) 
    626         { 
    627         break; 
    628         } 
     678     
     679    try { 
     680        callSemanticOnMembers(sc, decl); 
     681    } catch (DeferException* deferexc) { 
     682        sc_offset = sc->offset; 
     683        sc->pop(); 
     684        throw deferexc; 
    629685    } 
     686     
    630687    sc = sc->pop(); 
    631688 
    632     // If failed due to forward references, unwind and try again later 
    633     if (aad.sizeok == 2) 
    634     { 
    635         ad->sizeok = 2; 
    636         //printf("\tsetting ad->sizeok %p to 2\n", ad); 
    637         if (!sc->anonAgg) 
    638         { 
    639         scope = scx ? scx : new Scope(*sc); 
    640         scope->setNoFree(); 
    641         scope->module->addDeferredSemantic(this); 
    642         } 
    643         //printf("\tforward reference %p\n", this); 
    644         return; 
    645     } 
    646689    if (sem == 0) 
    647690    {   Module::dprogress++; 
    648691        sem = 1; 
     
    13321375 
    13331376void StaticIfDeclaration::semantic(Scope *sc) 
    13341377{ 
    1335     Array *d = include(sc, sd); 
     1378    if (!included_decls) 
     1379    included_decls = include(sc, sd); 
    13361380 
    13371381    //printf("\tStaticIfDeclaration::semantic '%s', d = %p\n",toChars(), d); 
    1338     if (d
     1382    if (included_decls
    13391383    { 
    13401384    if (!addisdone) 
    13411385    {   AttribDeclaration::addMember(sc, sd, 1); 
    13421386        addisdone = 1; 
    13431387    } 
    13441388 
    1345     for (unsigned i = 0; i < d->dim; i++) 
    1346     { 
    1347         Dsymbol *s = (Dsymbol *)d->data[i]; 
    1348  
    1349         s->semantic(sc); 
    1350     } 
     1389    callSemanticOnMembers(sc, included_decls); 
    13511390    } 
    13521391} 
    13531392 
  • 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); 
     
    543560    sc->protection = PROTpublic; 
    544561    sc->explicitProtection = 0; 
    545562    sc->structalign = 8; 
    546     structalign = sc->structalign; 
    547     if (baseClass) 
    548     {   sc->offset = baseClass->structsize; 
    549     alignsize = baseClass->alignsize; 
    550 //  if (isnested) 
    551 //      sc->offset += PTRSIZE;  // room for uplevel context pointer 
    552     } 
    553     else 
    554     {   sc->offset = 2*PTRSIZE;     // allow room for vptr[] and monitor 
    555     alignsize = PTRSIZE; 
    556     } 
    557     structsize = sc->offset; 
    558     Scope scsave = *sc; 
    559     int members_dim = members->dim; 
    560     sizeok = 0; 
    561     for (i = 0; i < members_dim; i++) 
    562     { 
    563     Dsymbol *s = (Dsymbol *)members->data[i]; 
    564     s->semantic(sc); 
    565     } 
    566563 
    567     if (sizeok == 2) 
    568     {   // semantic() failed because of forward references. 
    569     // Unwind what we did, and defer it for later 
    570     fields.setDim(0); 
    571     structsize = 0; 
    572     alignsize = 0; 
    573     structalign = 0; 
     564    if (sc_offset >= 0) 
     565    sc->offset = sc_offset; 
    574566 
     567    scsave = *sc; 
     568 
     569    try { 
     570    callSemanticOnMembers(sc); 
     571    } catch (DeferException* deferexc) { 
     572    sc_offset = sc->offset; 
     573    deferState = 3; 
    575574    sc = sc->pop(); 
    576  
    577     scope = scx ? scx : new Scope(*sc); 
    578     scope->setNoFree(); 
    579     scope->module->addDeferredSemantic(this); 
    580  
    581     //printf("\tsemantic('%s') failed due to forward references\n", toChars()); 
    582     return; 
     575    throw deferexc; 
    583576    } 
    584577 
    585578    //printf("\tsemantic('%s') successful\n", toChars()); 
     
    670663    } 
    671664#endif 
    672665    //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type); 
     666 
     667    deferState = -1; 
     668case -1: 
     669    break; 
     670default: 
     671    assert(0 && "deferState for classes must be between -1 and 3"); 
     672} // switch for deferred calling 
    673673} 
    674674 
    675675void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 
     
    766766    Dsymbol *s; 
    767767 
    768768    //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars()); 
    769     if (scope) 
    770     semantic(scope); 
     769    s = ScopeDsymbol::search(loc, ident, flags); 
    771770 
    772     if (!members || !symtab || scope) 
    773     {   error("is forward referenced when looking for '%s'", ident->toChars()); 
    774     //*(char*)0=0; 
    775     return NULL; 
     771    if (!s && (!members || !symtab || deferState > 0)) 
     772    { 
     773    throw new DeferException(loc, "%s is forward referenced when looking for '%s'", toChars(), ident->toChars()); 
    776774    } 
    777775 
    778     s = ScopeDsymbol::search(loc, ident, flags); 
    779776    if (!s) 
    780777    { 
    781778    // Search bases classes in depth-first, left to right order 
     
    987984 
    988985void InterfaceDeclaration::semantic(Scope *sc) 
    989986{   int i; 
     987    Scope *scx = NULL; 
    990988 
     989int continueAt = deferState; 
     990if (deferState > 0) 
     991    deferState = 0; 
     992switch (continueAt) { 
     993case 0: 
    991994    //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); 
    992995    if (inuse) 
    993996    return; 
    994     if (!scope) 
    995     type = type->semantic(loc, sc); 
    996    handle = handle->semantic(loc, sc); 
    997     } 
     997 
     998    type = type->semantic(loc, sc); 
     999    handle = handle->semantic(loc, sc); 
     1000 
    9981001    if (!members)           // if forward reference 
    9991002    {   //printf("\tinterface '%s' is forward referenced\n", toChars()); 
    10001003    return; 
    10011004    } 
    10021005    if (symtab)         // if already done 
    1003     {  if (!scope) 
    1004         return; 
     1006    { 
     1007    return; 
    10051008    } 
    10061009    else 
    10071010    symtab = new DsymbolTable(); 
    1008  
    1009     Scope *scx = NULL; 
    1010     if (scope) 
    1011     {   sc = scope; 
    1012     scx = scope;        // save so we don't make redundant copies 
    1013     scope = NULL; 
    1014     } 
    10151011 
    10161012    if (sc->stc & STCdeprecated) 
    10171013    { 
     
    10391035        i++; 
    10401036    } 
    10411037 
     1038case 1: 
    10421039    // Check for errors, handle forward references 
    10431040    for (i = 0; i < baseclasses.dim; ) 
    10441041    {   TypeClass *tc; 
     
    10751072        baseclasses.remove(i); 
    10761073        continue; 
    10771074        } 
    1078         if (!b->base->symtab || b->base->scope || b->base->inuse) 
     1075        if (!b->base->symtab || b->base->deferState > 0 || b->base->inuse) 
    10791076        { 
    10801077        //error("forward reference of base class %s", baseClass->toChars()); 
    10811078        // Forward reference of base, try again later 
    10821079        //printf("\ttry later, forward reference of base %s\n", b->base->toChars()); 
    1083         scope = scx ? scx : new Scope(*sc); 
    1084         scope->setNoFree(); 
    1085         scope->module->addDeferredSemantic(this); 
     1080        deferState = 1; 
     1081        sc->module->addDeferredSemantic(this, sc); 
    10861082        return; 
     1083        //throw new DeferException(loc, "forward reference of interface %s", baseClass->toChars()); 
    10871084        } 
    10881085    } 
    10891086    i++; 
     
    11331130    s->addMember(sc, this, 1); 
    11341131    } 
    11351132 
     1133case 2: 
    11361134    sc = sc->push(this); 
    11371135    sc->parent = this; 
    11381136    if (isCOMinterface()) 
     
    11401138    sc->structalign = 8; 
    11411139    structalign = sc->structalign; 
    11421140    sc->offset = 2*PTRSIZE; 
     1141    if (sc_offset >= 0) 
     1142    sc->offset = sc_offset; 
     1143 
    11431144    inuse++; 
    1144     for (i = 0; i < members->dim; i++) 
    1145     { 
    1146     Dsymbol *s = (Dsymbol *)members->data[i]; 
    1147     s->semantic(sc); 
     1145 
     1146    try { 
     1147    callSemanticOnMembers(sc); 
     1148    } catch (DeferException* deferexc) { 
     1149    sc_offset = sc->offset; 
     1150    deferState = 2; 
     1151    sc = sc->pop(); 
     1152    inuse--; 
     1153    throw deferexc; 
    11481154    } 
     1155 
    11491156    inuse--; 
    11501157    //members->print(); 
    11511158    sc->pop(); 
    11521159    //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); 
     1160 
     1161    deferState = -1; 
     1162case -1: 
     1163    break; 
     1164default: 
     1165    assert(0 && "deferState for interfaces must be between -1 and 2"); 
     1166} // switch for deferStatus 
    11531167} 
    11541168 
    11551169 
  • 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  
    324324        break; 
    325325 
    326326        case -2:    // can't determine because of fwd refs 
    327         cd->sizeok = 2; // can't finish due to forward reference 
    328         return; 
     327        throw new DeferException(loc, "cannot determine vtbl index of %s because of forward references", toChars()); 
    329328 
    330329        default: 
    331330        {   FuncDeclaration *fdv = (FuncDeclaration *)cd->vtbl.data[vi]; 
     
    398397            break; 
    399398 
    400399        case -2: 
    401             cd->sizeok = 2; // can't finish due to forward reference 
    402             return; 
     400            throw new DeferException(loc, "cannot determine vtbl index of %s because of forward references", toChars()); 
    403401 
    404402        default: 
    405403        {   FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi]; 
     
    494492            } 
    495493            if (cov == 3) 
    496494            { 
    497             cd->sizeok = 2; // can't finish due to forward reference 
    498             return; 
     495            throw new DeferException(loc, "cannot finish due to forward reference"); 
    499496            } 
    500497        } 
    501498        } 
  • a/dmd/import.c

    old new  
    122122{ 
    123123    //printf("Import::semantic('%s')\n", toChars()); 
    124124 
    125     load(sc); 
     125    DeferException* defer = NULL; 
     126    try { 
     127    load(sc); 
     128    } catch (DeferException* exc) { 
     129    defer = exc; 
     130    } 
    126131 
    127132    if (mod) 
    128133    { 
     
    148153    } 
    149154 
    150155    // Modules need a list of each imported module 
    151     sc->module->aimports.push(mod); 
     156    bool in_aimports = false; 
     157    for (int i = 0; i < sc->module->aimports.dim; ++i) 
     158        if (sc->module->aimports.data[i] == mod) 
     159        in_aimports = true; 
     160    if (!in_aimports) 
     161        sc->module->aimports.push(mod); 
    152162 
    153163    if (mod->needmoduleinfo) 
    154164        sc->module->needmoduleinfo = 1; 
     
    166176    } 
    167177    sc = sc->pop(); 
    168178    } 
     179 
     180    if (defer) 
     181    throw defer; 
    169182    //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg); 
    170183} 
    171184 
  • a/dmd/mars.c

    old new  
    11371137    m = (Module *)modules.data[i]; 
    11381138    if (global.params.verbose) 
    11391139        printf("semantic  %s\n", m->toChars()); 
    1140     m->semantic(); 
     1140    try { 
     1141        m->semantic(); 
     1142    } catch (DeferException* deferexc) { 
     1143        error("Couldn't resolve error though deferring:\n%s", deferexc->errormessage); 
     1144    } 
    11411145    } 
    11421146    if (global.errors) 
    11431147    fatal(); 
  • a/dmd/module.c

    old new  
    4646DsymbolTable *Module::modules; 
    4747Array Module::amodules; 
    4848 
    49 Array Module::deferred;   // deferred Dsymbol's needing semantic() run on them 
     49std::deque<DeferredDsymbol> Module::deferred; // deferred Dsymbol's needing semantic() run on them 
    5050unsigned Module::dprogress; 
    5151 
    5252void Module::init() 
     
    126126    llvmForceLogging = false; 
    127127    this->doDocComment = doDocComment; 
    128128    this->doHdrGen = doHdrGen; 
     129    sc = NULL; 
    129130} 
    130131 
    131132File* Module::buildFilePath(char* forcename, char* path, char* ext) 
     
    616617void Module::semantic(Scope* unused_sc) 
    617618{   int i; 
    618619 
    619     if (semanticstarted) 
     620    // if already done or circular, bail out 
     621    if (semanticdone || semanticstarted == 1) 
    620622    return; 
    621623 
    622     //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); 
    623     semanticstarted = 1; 
     624    if (semanticstarted == 0) 
     625    { 
     626    //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); 
     627    semanticstarted = 1; 
    624628 
    625     // Note that modules get their own scope, from scratch. 
    626     // This is so regardless of where in the syntax a module 
    627     // gets imported, it is unaffected by context. 
    628     Scope *sc = Scope::createGlobal(this);    // create root scope 
     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   sc = Scope::createGlobal(this);    // create root scope 
    629633 
    630     //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage); 
     634   //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage); 
    631635 
    632     // Add import of "object" if this module isn't "object" 
    633     if (ident != Id::object) 
    634    
    635     Import *im = new Import(0, NULL, Id::object, NULL, 0); 
    636     members->shift(im); 
    637    
     636   // Add import of "object" if this module isn't "object" 
     637   if (ident != Id::object) 
     638   
     639        Import *im = new Import(0, NULL, Id::object, NULL, 0); 
     640        members->shift(im); 
     641   
    638642 
    639     // Add all symbols into module's symbol table 
    640     symtab = new DsymbolTable(); 
    641     for (i = 0; i < members->dim; i++) 
    642     { Dsymbol *s; 
     643   // Add all symbols into module's symbol table 
     644   symtab = new DsymbolTable(); 
     645   for (i = 0; i < members->dim; i++) 
     646   {  Dsymbol *s; 
    643647 
    644     s = (Dsymbol *)members->data[i]; 
    645     s->addMember(NULL, sc->scopesym, 1); 
     648        s = (Dsymbol *)members->data[i]; 
     649        s->addMember(NULL, sc->scopesym, 1); 
     650    } 
    646651    } 
    647652 
    648653    // Pass 1 semantic routines: do public side of the definition 
    649     for (i = 0; i < members->dim; i++) 
    650     {   Dsymbol *s; 
    651  
    652     s = (Dsymbol *)members->data[i]; 
    653     //printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars()); 
    654     s->semantic(sc); 
    655     runDeferredSemantic(); 
     654    try { 
     655        callSemanticOnMembers(sc); 
     656    } catch (DeferException* deferexc) { 
     657        semanticstarted = -1; 
     658        throw deferexc; 
    656659    } 
    657660 
    658661    sc = sc->pop(); 
    659662    sc->pop(); 
    660     semanticdone = semanticstarted; 
     663    semanticstarted = 1; 
     664    semanticdone = 1; 
    661665    //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); 
    662666} 
    663667 
    664668void Module::semantic2(Scope* unused_sc) 
    665669{   int i; 
    666670 
    667     if (deferred.dim
     671    if (!deferred.empty()
    668672    { 
    669     for (int i = 0; i < deferred.dim; i++) 
     673    for (int i = 0; i < deferred.size(); i++) 
    670674    { 
    671         Dsymbol *sd = (Dsymbol *)deferred.data[i]
     675        Dsymbol *sd = deferred[i].sym
    672676 
    673677        sd->error("unable to resolve forward reference in definition"); 
    674678    } 
     
    810814    s = ScopeDsymbol::search(loc, ident, flags); 
    811815    insearch = 0; 
    812816 
     817    if (!s && semanticstarted == -1) 
     818        error("Forward reference!"); 
     819 
    813820    searchCacheIdent = ident; 
    814821    searchCacheSymbol = s; 
    815822    searchCacheFlags = flags; 
     
    821828 * Can't run semantic on s now, try again later. 
    822829 */ 
    823830 
    824 void Module::addDeferredSemantic(Dsymbol *s
     831void Module::addDeferredSemantic(Dsymbol *sym, Scope *scope
    825832{ 
    826833    // Don't add it if it is already there 
    827     for (int i = 0; i < deferred.dim; i++) 
     834    for (int i = 0; i < deferred.size(); i++) 
    828835    { 
    829     Dsymbol *sd = (Dsymbol *)deferred.data[i]
     836    Dsymbol *sd = (Dsymbol *)deferred[i].sym
    830837 
    831     if (sd == s
     838    if (sd == sym
    832839        return; 
    833840    } 
    834841 
     842    // copy scope 
     843    Scope* scx = new Scope(*scope); 
     844    scx->setNoFree(); 
     845 
    835846    //printf("Module::addDeferredSemantic('%s')\n", s->toChars()); 
    836     deferred.push(s); 
     847    deferred.push_back(DeferredDsymbol(sym, scx)); 
    837848} 
    838849 
    839850 
     
    843854 
    844855void Module::runDeferredSemantic() 
    845856{ 
    846     size_t len
     857    //if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim)
    847858 
    848859    static int nested; 
    849860    if (nested) 
    850861    return; 
    851     //if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); 
    852862    nested++; 
    853863 
    854     do 
    855     { 
    856     dprogress = 0; 
    857     len = deferred.dim; 
    858     if (!len) 
    859         break; 
     864    int failed = 0; 
    860865 
    861     Dsymbol **todo; 
    862     Dsymbol *tmp; 
    863     if (len == 1) 
    864     { 
    865         todo = &tmp; 
     866    // last defer exception that was caught. stored for the error message inside 
     867    DeferException* lastdefer; 
     868 
     869    // if we deferred an order dependent member, save it here 
     870    // we will then skip all order dependent members until this is reached again 
     871    Dsymbol *deferredOrderDependent = NULL; 
     872 
     873    while (!deferred.empty() && failed != deferred.size()) 
     874    {   Dsymbol *s; 
     875    Scope *sc; 
     876    s = deferred[0].sym; 
     877    sc = deferred[0].scope; 
     878    deferred.pop_front(); 
     879 
     880    // if we deferred something order dependent, skip other 
     881    // order dependent ones for one iteration 
     882    if (deferredOrderDependent == s) 
     883        deferredOrderDependent = NULL; 
     884    if (deferredOrderDependent && !isMemberReorderable(s)) { 
     885        ++failed; 
     886        deferred.push_back(DeferredDsymbol(s, sc)); 
     887        continue; 
    866888    } 
    867     else 
    868     { 
    869         todo = (Dsymbol **)alloca(len * sizeof(Dsymbol *)); 
    870         assert(todo); 
     889 
     890    try { 
     891        s->semantic(sc); 
     892        if (!deferred.empty() && deferred.rbegin()->sym == s) 
     893        ++failed; 
     894        else 
     895        failed = 0; 
     896    } catch (DeferException* deferexc) { 
     897        lastdefer = deferexc; 
     898        ++failed; 
     899        deferred.push_back(DeferredDsymbol(s, sc)); 
     900        if (!isMemberReorderable(s)) 
     901        deferredOrderDependent = s; 
     902        continue; 
    871903    } 
    872     memcpy(todo, deferred.data, len * sizeof(Dsymbol *)); 
    873     deferred.setDim(0); 
     904    } 
    874905 
    875     for (int i = 0; i < len; i++) 
    876     { 
    877         Dsymbol *s = todo[i]; 
    878  
    879         s->semantic(NULL); 
    880         //printf("deferred: %s, parent = %s\n", s->toChars(), s->parent->toChars()); 
    881     } 
    882     //printf("\tdeferred.dim = %d, len = %d, dprogress = %d\n", deferred.dim, len, dprogress); 
    883     } while (deferred.dim < len || dprogress);  // while making progress 
    884906    nested--; 
    885907    //printf("-Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); 
    886908} 
  • 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 
    145159    // Back end 
     
    178192 
    179193    // array ops emitted in this module already 
    180194    StringTable arrayfuncs; 
     195 
     196    // LDC 
     197    virtual void postMemberSemantic(Scope* sc) { runDeferredSemantic(); } 
     198    Scope* sc; 
    181199}; 
    182200 
    183201 
  • a/dmd/mtype.c

    old new  
    39233923#ifdef DEBUG 
    39243924    printf("2: "); 
    39253925#endif 
    3926     error(sym->loc, "enum %s is forward referenced", sym->toChars()); 
     3926    //error(sym->loc, "enum %s is forward referenced", sym->toChars()); 
     3927    throw new DeferException(sym->loc, "enum %s is forward referenced", sym->toChars()); 
    39273928    return tint32; 
    39283929    } 
    39293930    return sym->memtype->toBasetype(); 
     
    45954596Type *TypeClass::semantic(Loc loc, Scope *sc) 
    45964597{ 
    45974598    //printf("TypeClass::semantic(%s)\n", sym->toChars()); 
    4598     if (sym->scope) 
    4599     sym->semantic(sym->scope); 
    46004599    return merge(); 
    46014600} 
    46024601 
  • a/dmd/root.c

    old new  
    142142    exit(EXIT_FAILURE); 
    143143} 
    144144#endif 
     145 
     146DeferException::DeferException(Loc& loc, const char* format, ...) 
     147{ 
     148    errormessage = (char *)mem.malloc(200); 
     149    va_list ap; 
     150 
     151    va_start(ap, format); 
     152    size_t n = snprintf(errormessage, 200, "%s: ", loc.toChars()); 
     153    vsnprintf(errormessage+n, 200-n, format, ap); 
     154    va_end( ap ); 
     155 
     156    //warning("Avoided a forward reference error:\n  %s\n  This might not be safe. If you run into issues, this may be the cause!", errormessage); 
     157} 
    145158 
    146159void error_mem() 
    147160{ 
  • 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  
    27762776    this->isnested = NULL; 
    27772777    this->errors = 0; 
    27782778    this->tinst = NULL; 
     2779    this->deferState = 0; 
    27792780} 
    27802781 
    27812782 
     
    28002801    this->isnested = NULL; 
    28012802    this->errors = 0; 
    28022803    this->tinst = NULL; 
     2804    this->deferState = 0; 
    28032805 
    28042806    assert((size_t)tempdecl->scope > 0x10000); 
    28052807} 
     
    28462848 
    28472849void TemplateInstance::semantic(Scope *sc) 
    28482850{ 
     2851    int memnum = 0; 
     2852    int dosemantic3 = 0; 
     2853    unsigned errorsave; 
     2854    int tempdecl_instance_idx; 
     2855 
     2856int continueAt = deferState; 
     2857if (deferState > 0) 
     2858    deferState = 0; 
     2859switch (continueAt) { 
     2860case 0: 
    28492861    if (global.errors) 
    28502862    { 
    28512863    if (!global.gag) 
     
    29002912    semanticTiargs(sc); 
    29012913 
    29022914    tempdecl = findTemplateDeclaration(sc); 
    2903     if (tempdecl) 
    2904         tempdecl = findBestMatch(sc); 
     2915    if (tempdecl) { 
     2916        try { 
     2917        tempdecl = findBestMatch(sc); 
     2918        } catch(DeferException* deferexc) { 
     2919        semanticdone = 0; 
     2920        throw deferexc; 
     2921        } 
     2922    } 
    29052923    if (!tempdecl || global.errors) 
    29062924    {   inst = this; 
    29072925        //printf("error return %p, %d\n", tempdecl, global.errors); 
     
    29542972#if LOG 
    29552973    printf("\timplement template instance '%s'\n", toChars()); 
    29562974#endif 
    2957     unsigned errorsave = global.errors; 
     2975    errorsave = global.errors; 
    29582976    inst = this; 
    2959     int tempdecl_instance_idx = tempdecl->instances.dim; 
     2977    tempdecl_instance_idx = tempdecl->instances.dim; 
    29602978    tempdecl->instances.push(this); 
    29612979    parent = tempdecl->parent; 
    29622980    //printf("parent = '%s'\n", parent->kind()); 
     
    29722990    // Add 'this' to the enclosing scope's members[] so the semantic routines 
    29732991    // will get called on the instance members 
    29742992#if 1 
    2975     int dosemantic3 = 0; 
    29762993    {   Array *a; 
    29772994    int i; 
    29782995 
     
    30043021    // Copy the syntax trees from the TemplateDeclaration 
    30053022    members = Dsymbol::arraySyntaxCopy(tempdecl->members); 
    30063023 
     3024case 1: 
     3025    semanticdone = 1; 
    30073026    // Create our own scope for the template parameters 
    3008     Scope *scope = tempdecl->scope; 
     3027    scope = tempdecl->scope; 
    30093028    if (!scope) 
    30103029    { 
    3011     error("forward reference to template declaration %s\n", tempdecl->toChars()); 
    3012     return; 
     3030    semanticdone = 0; 
     3031    deferState = 1; 
     3032    throw new DeferException(loc, "forward reference to template declaration %s\n", tempdecl->toChars()); 
    30133033    } 
    30143034 
    30153035#if LOG 
     
    30253045    // Add members of template instance to template instance symbol table 
    30263046//    parent = scope->scopesym; 
    30273047    symtab = new DsymbolTable(); 
    3028     int memnum = 0; 
    30293048    for (int i = 0; i < members->dim; i++) 
    30303049    { 
    30313050    Dsymbol *s = (Dsymbol *)members->data[i]; 
     
    30633082#if LOG 
    30643083    printf("\tdo semantic() on template instance members '%s'\n", toChars()); 
    30653084#endif 
    3066     Scope *sc2; 
    30673085    sc2 = scope->push(this); 
    30683086    //printf("isnested = %d, sc->parent = %s\n", isnested, sc->parent->toChars()); 
    30693087    sc2->parent = /*isnested ? sc->parent :*/ this; 
    30703088    sc2->tinst = this; 
    30713089 
    3072 #if !IN_LLVM     
    3073 #if _WIN32 
    3074   __try 
    3075   { 
    3076 #endif 
    3077 #endif 
    3078     for (int i = 0; i < members->dim; i++) 
    3079     { 
    3080     Dsymbol *s = (Dsymbol *)members->data[i]; 
    3081     //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars()); 
    3082     //printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars()); 
    3083 //  if (isnested) 
    3084 //      s->parent = sc->parent; 
    3085     //printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); 
    3086     s->semantic(sc2); 
    3087     //printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); 
    3088     sc2->module->runDeferredSemantic(); 
    3089     } 
    3090 #if !IN_LLVM     
    3091 #if _WIN32 
    3092   } 
    3093   __except (__ehfilter(GetExceptionInformation())) 
    3094   { 
    3095     global.gag = 0;         // ensure error message gets printed 
    3096     error("recursive expansion"); 
    3097     fatal(); 
    3098   } 
    3099 #endif 
    3100 #endif 
     3090case 2: 
     3091    semanticdone = 1; 
     3092    try { 
     3093    callSemanticOnMembers(sc2); 
     3094    } catch (DeferException* deferexc) { 
     3095    deferState = 2; 
     3096    semanticdone = 0; 
     3097    throw deferexc; 
     3098    } 
    31013099 
    31023100    /* If any of the instantiation members didn't get semantic() run 
    31033101     * on them due to forward references, we cannot run semantic2() 
    31043102     * or semantic3() yet. 
    31053103     */ 
    3106     for (size_t i = 0; i < Module::deferred.dim; i++) 
    3107     {   Dsymbol *sd = (Dsymbol *)Module::deferred.data[i]
     3104    for (size_t i = 0; i < Module::deferred.size(); i++) 
     3105    {   Dsymbol *sd = (Dsymbol *)Module::deferred[i].sym
    31083106 
    31093107    if (sd->parent == this) 
    31103108        goto Laftersemantic; 
     
    31463144#if LOG 
    31473145    printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); 
    31483146#endif 
     3147 
     3148    deferState = -1; 
     3149case -1: 
     3150    break; 
     3151default: 
     3152    assert(0 && "deferState for template instances must be between -1 and 2"); 
     3153} // switch for deferring 
    31493154} 
    31503155 
    31513156 
     
    33913396    dedtypes.zero(); 
    33923397    if (!td->scope) 
    33933398    { 
    3394         error("forward reference to template declaration %s", td->toChars()); 
    3395         return NULL; 
     3399        throw new DeferException(loc, "forward reference to template declaration %s", td->toChars()); 
    33963400    } 
    33973401    m = td->matchWithInstance(this, &dedtypes, 0); 
    33983402    //printf("m = %d\n", m); 
     
    38843888    } 
    38853889} 
    38863890 
     3891void TemplateInstance::postMemberSemantic(Scope *sc) 
     3892{ 
     3893    sc->module->runDeferredSemantic(); 
     3894} 
     3895 
    38873896/* ======================== TemplateMixin ================================ */ 
    38883897 
    38893898TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual, 
     
    38963905    this->idents = idents; 
    38973906    this->tiargs = tiargs ? tiargs : new Objects(); 
    38983907    this->scope = NULL; 
     3908    this->deferState = 0; 
    38993909} 
    39003910 
    39013911Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s) 
     
    39253935 
    39263936void TemplateMixin::semantic(Scope *sc) 
    39273937{ 
     3938    unsigned errorsave; 
     3939 
     3940int continueAt = deferState; 
     3941if (deferState > 0) 
     3942    deferState = 0; 
     3943switch (continueAt) { 
     3944case 0: 
     3945 
    39283946#if LOG 
    39293947    printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this); 
    39303948    fflush(stdout); 
     
    39503968    util_progress(); 
    39513969#endif 
    39523970 
    3953     Scope *scx = NULL; 
     3971    scx = NULL; 
    39543972    if (scope) 
    39553973    {   sc = scope; 
    39563974    scx = scope;        // save so we don't make redundant copies 
     
    40254043         */ 
    40264044        semanticdone = 0; 
    40274045        AggregateDeclaration *ad = toParent()->isAggregateDeclaration(); 
    4028         if (ad) 
    4029         ad->sizeok = 2; 
    4030         else 
    4031         { 
    4032         // Forward reference 
    4033         //printf("forward reference - deferring\n"); 
    4034         scope = scx ? scx : new Scope(*sc); 
    4035         scope->setNoFree(); 
    4036         scope->module->addDeferredSemantic(this); 
    4037         } 
    4038         return; 
     4046 
     4047        // Forward reference 
     4048        //printf("forward reference - deferring\n"); 
     4049        //scope = scx ? scx : new Scope(*sc); 
     4050        //scope->setNoFree(); 
     4051        //scope->module->addDeferredSemantic(this); 
     4052        throw new DeferException(loc, "%s at %s is forward referenced", td->toChars(), td->loc.toChars()); 
    40394053    } 
    40404054    } 
    40414055 
     
    41234137#if LOG 
    41244138    printf("\tcreate scope for template parameters '%s'\n", toChars()); 
    41254139#endif 
    4126     Scope *scy = sc; 
     4140    scy = sc; 
    41274141    scy = sc->push(this); 
    41284142    scy->parent = this; 
    41294143 
    41304144    argsym = new ScopeDsymbol(); 
    41314145    argsym->parent = scy->parent; 
    4132     Scope *scope = scy->push(argsym); 
    4133  
    4134     unsigned errorsave = global.errors; 
     4146    scope = scy->push(argsym); 
     4147 
     4148    errorsave = global.errors; 
    41354149 
    41364150    // Declare each template parameter as an alias for the argument type 
    41374151    declareParameters(scope); 
     
    41514165#if LOG 
    41524166    printf("\tdo semantic() on template instance members '%s'\n", toChars()); 
    41534167#endif 
    4154     Scope *sc2; 
    41554168    sc2 = scope->push(this); 
    41564169    sc2->offset = sc->offset; 
    4157     for (int i = 0; i < members->dim; i++) 
    4158     { 
    4159     Dsymbol *s = (Dsymbol *)members->data[i]; 
    4160     s->semantic(sc2); 
     4170 
     4171case 1: 
     4172    try { 
     4173    callSemanticOnMembers(sc2); 
     4174    } catch (DeferException* deferexc) { 
     4175    deferState = 1; 
     4176    semanticdone = 0; 
     4177    throw deferexc; 
    41614178    } 
    41624179    sc->offset = sc2->offset; 
     4180 
     4181    /* If any of the instantiation members didn't get semantic() run 
     4182     * on them due to forward references, error! 
     4183     */ 
     4184    for (size_t i = 0; i < Module::deferred.size(); i++) 
     4185    {   Dsymbol *sd = (Dsymbol *)Module::deferred[i].sym; 
     4186 
     4187    if (sd->parent == this) 
     4188        error("semantic failed due to forward references in %s", sd->toPrettyChars()); 
     4189    } 
    41634190 
    41644191    /* The problem is when to parse the initializer for a variable. 
    41654192     * Perhaps VarDeclaration::semantic() should do it like it does 
     
    41914218#if LOG 
    41924219    printf("-TemplateMixin::semantic('%s', this=%p)\n", toChars(), this); 
    41934220#endif 
     4221 
     4222    deferState = -1; 
     4223case -1: 
     4224    break; 
     4225default: 
     4226    assert(0 && "deferState for template mixins must be between -1 and 1"); 
     4227} // switch for deferring 
    41944228} 
    41954229 
    41964230void TemplateMixin::semantic2(Scope *sc) 
  • a/dmd/template.h

    old new  
    316316    AliasDeclaration *isAliasDeclaration(); 
    317317 
    318318    // LDC 
     319    void postMemberSemantic(Scope* sc); 
    319320    TemplateInstance *tinst; // enclosing template instance 
    320321    void printInstantiationTrace(); 
     322    int deferState; 
     323    Scope *sc2; 
     324    Scope *scope; 
    321325}; 
    322326 
    323327struct TemplateMixin : TemplateInstance 
     
    343347    void toObjFile(int multiobj);           // compile to .obj file 
    344348 
    345349    TemplateMixin *isTemplateMixin() { return this; } 
     350 
     351    // LDC 
     352    int deferState; 
     353    Scope *sc2, *scy, *scx; 
    346354}; 
    347355 
    348356Expression *isExpression(Object *o); 
Copyright © 2008, LDC Development Team.