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

Ticket #125: forwardref.diff

File forwardref.diff, 51.4 kB (added by ChristianK, 15 years ago)

patch

  • a/dmd/aggregate.h

    old new  
    6363                // 1: size is correct 
    6464                // 2: cannot determine size; fwd referenced 
    6565    int isdeprecated;       // !=0 if deprecated 
    66     Scope *scope;       // !=NULL means context to use 
    6766 
    6867    // Special member functions 
    6968    InvariantDeclaration *inv;      // invariant 
     
    105104    Symbol *toInitializer(); 
    106105 
    107106    AggregateDeclaration *isAggregateDeclaration() { return this; } 
     107 
     108    // LDC 
     109    int sc_offset;      // saved next offset in aggregate 
    108110}; 
    109111 
    110112struct AnonymousAggregateDeclaration : AggregateDeclaration 
     
    132134    Dsymbol *syntaxCopy(Dsymbol *s); 
    133135    void semantic(Scope *sc); 
    134136    void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 
     137 
     138    //LDC, override to allow searching in partially semantic'ed structs 
     139    Dsymbol *search(Loc, Identifier *ident, int flags); 
     140 
     141    //LDC, for deferring 
     142    int deferState; 
     143    virtual bool isMemberReorderable(Dsymbol* s); 
     144 
    135145    char *mangle(); 
    136146    const char *kind(); 
    137147    Expression *cloneMembers(); 
     
    153163    const char *kind(); 
    154164 
    155165    UnionDeclaration *isUnionDeclaration() { return this; } 
     166 
     167    // LDC, overload to reset offset to zero after each member 
     168    virtual void postMemberSemantic(Scope* sc); 
    156169}; 
    157170 
    158171struct BaseClass 
     
    215228    VarDeclaration *vthis;      // 'this' parameter if this class is nested 
    216229 
    217230    int inuse;              // to prevent recursive attempts 
     231 
     232    //LDC, for deferring 
     233    int deferState; 
    218234 
    219235    ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses); 
    220236    Dsymbol *syntaxCopy(Dsymbol *s); 
  • a/dmd/attrib.c

    old new  
    4444    : Dsymbol() 
    4545{ 
    4646    this->decl = decl; 
     47    member_semantic_started = false; 
     48    included_decls = NULL; 
    4749} 
    4850 
    4951Array *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd) 
     
    6668    return m; 
    6769} 
    6870 
     71// shares code with ScopeDsymbol::callSemanticOnMembers 
     72void AttribDeclaration::callSemanticOnMembers(Scope* sc, Array* members) 
     73{ 
     74    if (!members) 
     75    return; 
     76 
     77    // first add everything to remaining_semantic 
     78    if (!member_semantic_started) { 
     79    for (int i = 0; i < members->dim; i++) 
     80        remaining_semantic.push_back( (Dsymbol*)members->data[i] ); 
     81    member_semantic_started = true; 
     82    } 
     83 
     84    int failed = 0; 
     85 
     86    // last defer exception that was caught. stored for the error message inside 
     87    DeferException* lastdefer; 
     88 
     89    // if we deferred an order dependent member, save it here 
     90    // we will then skip all order dependent members until this is reached again 
     91    Dsymbol *deferredOrderDependent = NULL; 
     92 
     93    while (!remaining_semantic.empty() && failed != remaining_semantic.size()) 
     94    {   Dsymbol *s; 
     95    s = remaining_semantic[0]; 
     96    remaining_semantic.pop_front(); 
     97 
     98    // if we deferred something order dependent, skip other 
     99    // order dependent ones for one iteration 
     100    if (deferredOrderDependent == s) 
     101        deferredOrderDependent = NULL; 
     102    if (deferredOrderDependent && !isMemberReorderable(s)) { 
     103        ++failed; 
     104        remaining_semantic.push_back(s); 
     105        continue; 
     106    } 
     107 
     108    try { 
     109        runSemantic(s, sc); 
     110    } catch (DeferException* deferexc) { 
     111        lastdefer = deferexc; 
     112        ++failed; 
     113        remaining_semantic.push_back(s); 
     114        if (!isMemberReorderable(s)) 
     115        deferredOrderDependent = s; 
     116        continue; 
     117    } 
     118 
     119    failed = 0; 
     120    postMemberSemantic(sc); 
     121    } 
     122 
     123    if (!remaining_semantic.empty()) 
     124    { 
     125    assert(lastdefer); 
     126 
     127    // reorder members into a valid state if necessary 
     128    if (deferredOrderDependent) 
     129        while (remaining_semantic[0] != deferredOrderDependent) { 
     130        Dsymbol* s = remaining_semantic[0]; 
     131        remaining_semantic.pop_front(); 
     132        remaining_semantic.push_back(s); 
     133        } 
     134 
     135    throw lastdefer; 
     136    } 
     137} 
     138 
    69139void AttribDeclaration::semantic(Scope *sc) 
    70140{ 
    71     Array *d = include(sc, NULL); 
     141    if (!included_decls) 
     142    included_decls = include(sc, NULL); 
    72143 
    73144    //printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d); 
    74     if (d) 
    75     { 
    76     for (unsigned i = 0; i < d->dim; i++) 
    77     { 
    78         Dsymbol *s = (Dsymbol *)d->data[i]; 
    79  
    80         s->semantic(sc); 
    81     } 
    82     } 
     145    callSemanticOnMembers(sc, included_decls); 
    83146} 
    84147 
    85148void AttribDeclaration::semantic2(Scope *sc) 
     
    297360    if (stc & (STCauto | STCscope | STCstatic | STCextern)) 
    298361        sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern); 
    299362    sc->stc |= stc; 
    300     for (unsigned i = 0; i < decl->dim; i++) 
    301     { 
    302         Dsymbol *s = (Dsymbol *)decl->data[i]; 
    303  
    304         s->semantic(sc); 
    305     } 
     363    callSemanticOnMembers(sc, decl); 
    306364    sc->stc = stc_save; 
    307365    } 
    308366    else 
     
    371429    {   enum LINK linkage_save = sc->linkage; 
    372430 
    373431    sc->linkage = linkage; 
    374     for (unsigned i = 0; i < decl->dim; i++) 
    375     { 
    376         Dsymbol *s = (Dsymbol *)decl->data[i]; 
    377  
    378         s->semantic(sc); 
    379     } 
     432    callSemanticOnMembers(sc, decl); 
    380433    sc->linkage = linkage_save; 
    381434    } 
    382435    else 
     
    461514 
    462515    sc->protection = protection; 
    463516    sc->explicitProtection = 1; 
    464     for (unsigned i = 0; i < decl->dim; i++) 
    465     { 
    466         Dsymbol *s = (Dsymbol *)decl->data[i]; 
    467  
    468         s->semantic(sc); 
    469     } 
     517    callSemanticOnMembers(sc, decl); 
    470518    sc->protection = protection_save; 
    471519    sc->explicitProtection = explicitProtection_save; 
    472520    } 
     
    520568 
    521569    //printf("\tAlignDeclaration::semantic '%s'\n",toChars()); 
    522570    if (decl) 
    523     {   unsigned salign_save = sc->structalign; 
    524  
    525     for (unsigned i = 0; i < decl->dim; i++) 
    526     { 
    527         Dsymbol *s = (Dsymbol *)decl->data[i]; 
    528  
    529         if (s->isStructDeclaration() && salign == 1) 
    530         { 
    531             sc->structalign = salign; 
    532             s->semantic(sc); 
    533             sc->structalign = salign_save; 
    534         } 
    535         else 
    536         { 
    537             s->semantic(sc); 
    538         } 
    539     } 
    540     sc->structalign = salign_save; 
     571    {    
     572    callSemanticOnMembers(sc, decl); 
    541573    } 
    542574    else 
    543575    assert(0 && "what kind of align use triggers this?"); 
    544576} 
    545577 
     578void AlignDeclaration::runSemantic(Dsymbol* s, Scope* sc) 
     579{ 
     580    unsigned salign_save = sc->structalign; 
     581 
     582    if (s->isStructDeclaration() && salign == 1) 
     583    { 
     584    sc->structalign = salign; 
     585    s->semantic(sc); 
     586    sc->structalign = salign_save; 
     587    } 
     588    else 
     589    { 
     590    s->semantic(sc); 
     591    } 
     592} 
    546593 
    547594void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 
    548595{ 
     
    557604{ 
    558605    this->loc = loc; 
    559606    this->isunion = isunion; 
    560     this->scope = NULL; 
    561607    this->sem = 0; 
     608 
     609    sc_offset = -1; 
    562610} 
    563611 
    564612Dsymbol *AnonDeclaration::syntaxCopy(Dsymbol *s) 
     
    570618    return ad; 
    571619} 
    572620 
     621// copied from StructDeclaration::isMemberReorderable 
     622bool AnonDeclaration::isMemberReorderable(Dsymbol* s) 
     623{ 
     624    if ( 
     625    s->isVarDeclaration() || 
     626    s->isAttribDeclaration() 
     627    ) 
     628    return false; 
     629    return true; 
     630} 
     631 
     632void AnonDeclaration::postMemberSemantic(Scope* sc) 
     633{ 
     634    if (isunion) 
     635    sc->offset = 0; 
     636} 
     637 
    573638void AnonDeclaration::semantic(Scope *sc) 
    574639{ 
    575640    //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this); 
    576  
    577     Scope *scx = NULL; 
    578     if (scope) 
    579     {   sc = scope; 
    580     scx = scope; 
    581     scope = NULL; 
    582     } 
    583641 
    584642    assert(sc->parent); 
    585643 
     
    594652 
    595653    if (decl) 
    596654    { 
    597     AnonymousAggregateDeclaration aad; 
    598655    int adisunion; 
    599656 
    600657    if (sc->anonAgg) 
     
    613670    sc->stc &= ~(STCauto | STCscope | STCstatic); 
    614671    sc->inunion = isunion; 
    615672    sc->offset = 0; 
     673    if (sc_offset >= 0) 
     674        sc->offset = sc_offset; 
     675 
    616676    sc->flags = 0; 
    617677    aad.structalign = sc->structalign; 
    618678    aad.parent = ad; 
    619679 
    620     for (unsigned i = 0; i < decl->dim; i++) 
    621     { 
    622         Dsymbol *s = (Dsymbol *)decl->data[i]; 
     680    try { 
     681        callSemanticOnMembers(sc, decl); 
     682    } catch (DeferException* deferexc) { 
     683        sc_offset = sc->offset; 
     684        sc->pop(); 
     685        throw deferexc; 
     686    } 
    623687 
    624         s->semantic(sc); 
    625         if (isunion) 
    626         sc->offset = 0; 
    627         if (aad.sizeok == 2) 
    628         { 
    629         break; 
    630         } 
    631     } 
    632688    sc = sc->pop(); 
    633689 
    634     // If failed due to forward references, unwind and try again later 
    635     if (aad.sizeok == 2) 
    636     { 
    637         ad->sizeok = 2; 
    638         //printf("\tsetting ad->sizeok %p to 2\n", ad); 
    639         if (!sc->anonAgg) 
    640         { 
    641         scope = scx ? scx : new Scope(*sc); 
    642         scope->setNoFree(); 
    643         scope->module->addDeferredSemantic(this); 
    644         } 
    645         //printf("\tforward reference %p\n", this); 
    646         return; 
    647     } 
    648690    if (sem == 0) 
    649691    {   Module::dprogress++; 
    650692        sem = 1; 
     
    13311373 
    13321374void StaticIfDeclaration::semantic(Scope *sc) 
    13331375{ 
    1334     Array *d = include(sc, sd); 
     1376    if (!included_decls) 
     1377    included_decls = include(sc, sd); 
    13351378 
    13361379    //printf("\tStaticIfDeclaration::semantic '%s', d = %p\n",toChars(), d); 
    1337     if (d
     1380    if (included_decls
    13381381    { 
    13391382    if (!addisdone) 
    13401383    {   AttribDeclaration::addMember(sc, sd, 1); 
    13411384        addisdone = 1; 
    13421385    } 
    13431386 
    1344     for (unsigned i = 0; i < d->dim; i++) 
    1345     { 
    1346         Dsymbol *s = (Dsymbol *)d->data[i]; 
    1347  
    1348         s->semantic(sc); 
    1349     } 
     1387    callSemanticOnMembers(sc, included_decls); 
    13501388    } 
    13511389} 
    13521390 
  • 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    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); 
     
    107119    void semantic(Scope *sc); 
    108120    void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 
    109121    const char *kind(); 
     122 
     123    void postMemberSemantic(Scope* sc); 
     124    bool isMemberReorderable(Dsymbol* sym); 
     125    int sc_offset;      // saved next offset in aggregate 
     126    AnonymousAggregateDeclaration aad; 
    110127}; 
    111128 
    112129struct 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 = 8;      // allow room for vptr[] and monitor 
     546    alignsize = 4; 
     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 = 8;     // allow room for vptr[] and monitor 
    555     alignsize = 4; 
    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 = 8; 
     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    deferState = -1; 
     1161case -1: 
     1162    break; 
     1163default: 
     1164    assert(0 && "deferState for interfaces must be between -1 and 2"); 
     1165} // switch for deferStatus 
    11531166} 
    11541167 
    11551168 
  • a/dmd/declaration.c

    old new  
    686686    int inferred = 0; 
    687687    if (!type) 
    688688    {   inuse++; 
    689     type = init->inferType(sc); 
     689    try { 
     690        type = init->inferType(sc); 
     691    } catch (DeferException* deferexc) { 
     692        inuse--; 
     693        throw deferexc; 
     694    } 
    690695    inuse--; 
    691696    inferred = 1; 
    692697 
     
    10071012        Expression *e; 
    10081013        Initializer *i2 = init; 
    10091014        inuse++; 
    1010         if (ei) 
    1011         { 
    1012             e = ei->exp->syntaxCopy(); 
    1013             e = e->semantic(sc); 
    1014             e = e->implicitCastTo(sc, type); 
    1015         } 
    1016         else if (si || ai) 
    1017         {   i2 = init->syntaxCopy(); 
    1018             i2 = i2->semantic(sc, type); 
     1015        try { 
     1016            if (ei) 
     1017            { 
     1018            e = ei->exp->syntaxCopy(); 
     1019            e = e->semantic(sc); 
     1020            e = e->implicitCastTo(sc, type); 
     1021            } 
     1022            else if (si || ai) 
     1023            {   i2 = init->syntaxCopy(); 
     1024            i2 = i2->semantic(sc, type); 
     1025            } 
     1026        } catch (DeferException* deferexc) { 
     1027            inuse--; 
     1028            global.gag--; 
     1029            throw deferexc; 
    10191030        } 
    10201031        inuse--; 
    10211032        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  
    11331133    m = (Module *)modules.data[i]; 
    11341134    if (global.params.verbose) 
    11351135        printf("semantic  %s\n", m->toChars()); 
    1136     m->semantic(); 
     1136    try { 
     1137        m->semantic(); 
     1138    } catch (DeferException* deferexc) { 
     1139        error("Couldn't resolve error though deferring:\n%s", deferexc->errormessage); 
     1140    } 
    11371141    } 
    11381142    if (global.errors) 
    11391143    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  
    39133913#ifdef DEBUG 
    39143914    printf("2: "); 
    39153915#endif 
    3916     error(sym->loc, "enum %s is forward referenced", sym->toChars()); 
     3916    //error(sym->loc, "enum %s is forward referenced", sym->toChars()); 
     3917    throw new DeferException(sym->loc, "enum %s is forward referenced", sym->toChars()); 
    39173918    return tint32; 
    39183919    } 
    39193920    return sym->memtype->toBasetype(); 
     
    45854586Type *TypeClass::semantic(Loc loc, Scope *sc) 
    45864587{ 
    45874588    //printf("TypeClass::semantic(%s)\n", sym->toChars()); 
    4588     if (sym->scope) 
    4589     sym->semantic(sym->scope); 
    45904589    return merge(); 
    45914590} 
    45924591 
  • 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.