Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 809

Show
Ignore:
Timestamp:
12/20/10 07:17:34 (14 years ago)
Author:
walter
Message:

fixed problem with recursive instantiations reported by Stephan Dilly

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/func.c

    r785 r809  
    15871587                        fbody = new SynchronizedStatement(loc, vsync, fbody); 
    15881588                        fbody = fbody->semantic(sc2); 
    15891589                    } 
    15901590                } 
    15911591                else 
    15921592                { 
    15931593                    error("synchronized function %s must be a member of a class", toChars()); 
    15941594                } 
    15951595            } 
    15961596#endif 
    15971597        } 
    15981598 
    15991599        sc2->callSuper = 0; 
    16001600        sc2->pop(); 
    16011601    } 
    16021602 
    16031603    if (global.gag && global.errors != nerrors) 
    16041604        semanticRun = PASSsemanticdone; // Ensure errors get reported again 
    16051605    else 
    16061606        semanticRun = PASSsemantic3done; 
     1607    //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars()); 
     1608    //fflush(stdout); 
    16071609} 
    16081610 
    16091611void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 
    16101612{ 
    16111613    //printf("FuncDeclaration::toCBuffer() '%s'\n", toChars()); 
    16121614 
    16131615    StorageClassDeclaration::stcToCBuffer(buf, storage_class); 
    16141616    type->toCBuffer(buf, ident, hgs); 
    16151617    bodyToCBuffer(buf, hgs); 
    16161618} 
    16171619 
    16181620int FuncDeclaration::equals(Object *o) 
    16191621{ 
    16201622    if (this == o) 
    16211623        return TRUE; 
    16221624 
    16231625    Dsymbol *s = isDsymbol(o); 
    16241626    if (s) 
    16251627    { 
    16261628        FuncDeclaration *fd = s->isFuncDeclaration(); 
  • trunk/src/mtype.c

    r786 r809  
    60506050                } 
    60516051                t = cd->type; 
    60526052                break; 
    60536053            } 
    60546054            sd = s->isStructDeclaration(); 
    60556055            if (sd) 
    60566056            { 
    60576057                if (exp->op == TOKsuper) 
    60586058                { 
    60596059                    error(loc, "struct %s has no 'super'", sd->toChars()); 
    60606060                    goto Lerr; 
    60616061                } 
    60626062                t = sd->type->pointerTo(); 
    60636063                break; 
    60646064            } 
    60656065        } 
    60666066    } 
    60676067    else 
    60686068#endif 
    60696069    { 
    6070         sc->intypeof++; 
    6071         exp = exp->semantic(sc); 
     6070        Scope *sc2 = sc->push(); 
     6071        sc2->intypeof++; 
     6072        exp = exp->semantic(sc2); 
    60726073#if DMDV2 
    60736074        if (exp->type && exp->type->ty == Tfunction && 
    60746075            ((TypeFunction *)exp->type)->isproperty) 
    6075             exp = resolveProperties(sc, exp); 
     6076            exp = resolveProperties(sc2, exp); 
    60766077#endif 
    6077         sc->intypeof--
     6078        sc2->pop()
    60786079        if (exp->op == TOKtype) 
    60796080        { 
    60806081            error(loc, "argument %s to typeof is not an expression", exp->toChars()); 
    60816082            goto Lerr; 
    60826083        } 
    60836084        t = exp->type; 
    60846085        if (!t) 
    60856086        { 
    60866087            error(loc, "expression (%s) has no type", exp->toChars()); 
    60876088            goto Lerr; 
    60886089        } 
    60896090        if (t->ty == Ttypeof) 
    60906091        {   error(loc, "forward reference to %s", toChars()); 
    60916092            goto Lerr; 
    60926093        } 
    60936094 
    60946095        /* typeof should reflect the true type, 
    60956096         * not what 'auto' would have gotten us. 
    60966097         */ 
    60976098        //t = t->toHeadMutable(); 
     
    71287129        } 
    71297130        return t->implicitConvTo(to); 
    71307131    } 
    71317132    return MATCHnomatch; 
    71327133} 
    71337134 
    71347135MATCH TypeStruct::implicitConvTo(Type *to) 
    71357136{   MATCH m; 
    71367137 
    71377138    //printf("TypeStruct::implicitConvTo(%s => %s)\n", toChars(), to->toChars()); 
    71387139    if (to->ty == Taarray) 
    71397140    { 
    71407141        /* If there is an error instantiating AssociativeArray!(), it shouldn't 
    71417142         * be reported -- it just means implicit conversion is impossible. 
    71427143         */ 
    71437144        ++global.gag; 
    71447145        int errs = global.errors; 
    71457146        to = ((TypeAArray*)to)->getImpl()->type; 
    71467147        --global.gag; 
    71477148        if (errs != global.errors) 
    7148         {   global.errors = errs; 
     7149        { 
     7150            global.errors = errs; 
    71497151            return MATCHnomatch; 
    71507152        } 
    71517153    } 
    71527154 
    71537155    if (ty == to->ty && sym == ((TypeStruct *)to)->sym) 
    71547156    {   m = MATCHexact;         // exact match 
    71557157        if (mod != to->mod) 
    71567158        { 
    71577159            if (MODimplicitConv(mod, to->mod)) 
    71587160                m = MATCHconst; 
    71597161            else 
    71607162            {   /* Check all the fields. If they can all be converted, 
    71617163                 * allow the conversion. 
    71627164                 */ 
    71637165                for (int i = 0; i < sym->fields.dim; i++) 
    71647166                {   Dsymbol *s = (Dsymbol *)sym->fields.data[i]; 
    71657167                    VarDeclaration *v = s->isVarDeclaration(); 
    71667168                    assert(v && v->storage_class & STCfield); 
    71677169 
    71687170                    // 'from' type 
  • trunk/src/template.c

    r801 r809  
    703703    if (!flag) 
    704704    { 
    705705        /* Any parameter left without a type gets the type of 
    706706         * its corresponding arg 
    707707         */ 
    708708        for (int i = 0; i < dedtypes_dim; i++) 
    709709        { 
    710710            if (!dedtypes->data[i]) 
    711711            {   assert(i < ti->tiargs->dim); 
    712712                dedtypes->data[i] = ti->tiargs->data[i]; 
    713713            } 
    714714        } 
    715715    } 
    716716 
    717717#if DMDV2 
    718718    if (m && constraint && !(flag & 1)) 
    719719    {   /* Check to see if constraint is satisfied. 
    720720         */ 
    721721        makeParamNamesVisibleInConstraint(paramscope); 
    722722        Expression *e = constraint->syntaxCopy(); 
    723         paramscope->flags |= SCOPEstaticif; 
    724         e = e->semantic(paramscope); 
     723        Scope *sc = paramscope->push(); 
     724        sc->flags |= SCOPEstaticif; 
     725        e = e->semantic(sc); 
     726        sc->pop(); 
    725727        e = e->optimize(WANTvalue | WANTinterpret); 
    726728        if (e->isBool(TRUE)) 
    727729            ; 
    728730        else if (e->isBool(FALSE)) 
    729731            goto Lnomatch; 
    730732        else 
    731733        { 
    732734            e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars()); 
    733735        } 
    734736    } 
    735737#endif 
    736738 
    737739#if LOGM 
    738740    // Print out the results 
    739741    printf("--------------------------\n"); 
    740742    printf("template %s\n", toChars()); 
    741743    printf("instance %s\n", ti->toChars()); 
    742744    if (m) 
    743745    { 
    744746        for (int i = 0; i < dedtypes_dim; i++) 
     
    12911293                        oded = (Object *)new Tuple(); 
    12921294                    } 
    12931295                    else 
    12941296                        goto Lnomatch; 
    12951297                } 
    12961298            } 
    12971299            declareParameter(paramscope, tparam, oded); 
    12981300            dedargs->data[i] = (void *)oded; 
    12991301        } 
    13001302    } 
    13011303 
    13021304#if DMDV2 
    13031305    if (constraint) 
    13041306    {   /* Check to see if constraint is satisfied. 
    13051307         */ 
    13061308        makeParamNamesVisibleInConstraint(paramscope); 
    13071309        Expression *e = constraint->syntaxCopy(); 
    13081310        paramscope->flags |= SCOPEstaticif; 
    13091311 
    13101312        /* Detect recursive attempts to instantiate this template declaration, 
     1313         * Bugzilla 4072 
    13111314         *  void foo(T)(T x) if (is(typeof(foo(x)))) { } 
    1312          *  static assert(!is(typeof(bug4072(7)))); 
     1315         *  static assert(!is(typeof(foo(7)))); 
    13131316         * Recursive attempts are regarded as a constraint failure. 
    13141317         */ 
     1318        int nmatches = 0; 
    13151319        for (Previous *p = previous; p; p = p->prev) 
    13161320        { 
    13171321            if (arrayObjectMatch(p->dedargs, dedargs, this, sc)) 
    1318                 goto Lnomatch; 
     1322            { 
     1323                //printf("recursive, no match %p %s\n", this, this->toChars()); 
     1324                nmatches++; 
     1325            } 
    13191326            /* BUG: should also check for ref param differences 
    13201327             */ 
    13211328        } 
     1329        /* Look for 2 matches at least, because sometimes semantic3() gets run causing what appears to 
     1330         * be recursion but isn't. 
     1331         * Template A's constraint instantiates B, B's semantic3() run includes something that has A in its constraint. 
     1332         * Perhaps a better solution is to always defer semantic3() rather than doing it eagerly. The risk 
     1333         * with that is what if semantic3() fails, but our constraint "succeeded"? 
     1334         */ 
     1335        if (nmatches >= 2) 
     1336            goto Lnomatch; 
     1337 
    13221338        Previous pr; 
    13231339        pr.prev = previous; 
    13241340        pr.dedargs = dedargs; 
    13251341        previous = &pr;                 // add this to threaded list 
    13261342 
    13271343        int nerrors = global.errors; 
    13281344 
    13291345        e = e->semantic(paramscope); 
    13301346 
    13311347        previous = pr.prev;             // unlink from threaded list 
    13321348 
    13331349        if (nerrors != global.errors)   // if any errors from evaluating the constraint, no match 
    13341350            goto Lnomatch; 
    13351351 
    13361352        e = e->optimize(WANTvalue | WANTinterpret); 
    13371353        if (e->isBool(TRUE)) 
    13381354            ; 
    13391355        else if (e->isBool(FALSE)) 
    13401356            goto Lnomatch; 
    13411357        else 
     
    38323848                    } 
    38333849                } 
    38343850            } 
    38353851        } 
    38363852 
    38373853        // It's a match 
    38383854        inst = ti; 
    38393855        parent = ti->parent; 
    38403856#if LOG 
    38413857        printf("\tit's a match with instance %p\n", inst); 
    38423858#endif 
    38433859        return; 
    38443860 
    38453861     L1: 
    38463862        ; 
    38473863    } 
    38483864 
    38493865    /* So, we need to implement 'this' instance. 
    38503866     */ 
    38513867#if LOG 
    3852     printf("\timplement template instance '%s'\n", toChars()); 
     3868    printf("\timplement template instance %s '%s'\n", tempdecl->parent->toChars(), toChars()); 
     3869    printf("\ttempdecl %s\n", tempdecl->toChars()); 
    38533870#endif 
    38543871    unsigned errorsave = global.errors; 
    38553872    inst = this; 
    38563873    int tempdecl_instance_idx = tempdecl->instances.dim; 
    38573874    tempdecl->instances.push(this); 
    38583875    parent = tempdecl->parent; 
    38593876    //printf("parent = '%s'\n", parent->kind()); 
    38603877 
    3861     ident = genIdent();         // need an identifier for name mangling purposes. 
     3878    ident = genIdent(tiargs);         // need an identifier for name mangling purposes. 
    38623879 
    38633880#if 1 
    38643881    if (isnested) 
    38653882        parent = isnested; 
    38663883#endif 
    38673884    //printf("parent = '%s'\n", parent->kind()); 
    38683885 
    38693886    // Add 'this' to the enclosing scope's members[] so the semantic routines 
    38703887    // will get called on the instance members 
    38713888#if 1 
    38723889    int dosemantic3 = 0; 
    38733890    {   Array *a; 
    38743891 
    38753892        Scope *scx = sc; 
    38763893#if 0 
    38773894        for (scx = sc; scx; scx = scx->enclosing) 
    38783895            if (scx->scopesym) 
    38793896                break; 
    38803897#endif 
    38813898 
     
    38843901            scx->scopesym->members && !scx->scopesym->isTemplateMixin() 
    38853902#if 0 // removed because it bloated compile times 
    38863903            /* The problem is if A imports B, and B imports A, and both A 
    38873904             * and B instantiate the same template, does the compilation of A 
    38883905             * or the compilation of B do the actual instantiation? 
    38893906             * 
    38903907             * see bugzilla 2500. 
    38913908             */ 
    38923909            && !scx->module->selfImports() 
    38933910#endif 
    38943911           ) 
    38953912        { 
    38963913            //printf("\t1: adding to %s %s\n", scx->scopesym->kind(), scx->scopesym->toChars()); 
    38973914            a = scx->scopesym->members; 
    38983915        } 
    38993916        else 
    39003917        {   Module *m = sc->module->importedFrom; 
    39013918            //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars()); 
    39023919            a = m->members; 
    39033920            if (m->semanticRun >= 3) 
     3921            { 
    39043922                dosemantic3 = 1; 
     3923            } 
    39053924        } 
    39063925        for (int i = 0; 1; i++) 
    39073926        { 
    39083927            if (i == a->dim) 
    39093928            { 
    39103929                a->push(this); 
    39113930                break; 
    39123931            } 
    39133932            if (this == (Dsymbol *)a->data[i])  // if already in Array 
    39143933                break; 
    39153934        } 
    39163935    } 
    39173936#endif 
    39183937 
    39193938    // Copy the syntax trees from the TemplateDeclaration 
    39203939    members = Dsymbol::arraySyntaxCopy(tempdecl->members); 
    39213940 
    39223941    // Create our own scope for the template parameters 
    39233942    Scope *scope = tempdecl->scope; 
    39243943    if (!tempdecl->semanticRun) 
     
    40864105            fatal(); 
    40874106        } 
    40884107#endif 
    40894108    } 
    40904109 
    40914110  Laftersemantic: 
    40924111    sc2->pop(); 
    40934112 
    40944113    scope->pop(); 
    40954114 
    40964115    // Give additional context info if error occurred during instantiation 
    40974116    if (global.errors != errorsave) 
    40984117    { 
    40994118        error(loc, "error instantiating"); 
    41004119        if (tinst) 
    41014120        {   tinst->printInstantiationTrace(); 
    41024121        } 
    41034122        errors = 1; 
    41044123        if (global.gag) 
    41054124        {   // Try to reset things so we can try again later to instantiate it 
     4125            //printf("remove %s\n", toChars()); 
    41064126            tempdecl->instances.remove(tempdecl_instance_idx); 
    41074127            if (!(sc->flags & SCOPEstaticif)) 
    41084128            {   // Bugzilla 4302 for discussion 
    41094129                semanticRun = 0; 
    41104130                inst = NULL; 
    41114131            } 
    41124132        } 
    41134133    } 
    41144134 
    41154135#if LOG 
    41164136    printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); 
    41174137#endif 
    41184138} 
    41194139 
    41204140 
    41214141void TemplateInstance::semanticTiargs(Scope *sc) 
    41224142{ 
    41234143    //printf("+TemplateInstance::semanticTiargs() %s\n", toChars()); 
    41244144    if (semantictiargsdone) 
    41254145        return; 
     
    45904610                    nested |= 1; 
    45914611                } 
    45924612                else 
    45934613                    error("cannot use local '%s' as parameter to non-global template %s", sa->toChars(), tempdecl->toChars()); 
    45944614            } 
    45954615        } 
    45964616        else if (va) 
    45974617        { 
    45984618            nested |= hasNestedArgs(&va->objects); 
    45994619        } 
    46004620    } 
    46014621    return nested; 
    46024622} 
    46034623 
    46044624/**************************************** 
    46054625 * This instance needs an identifier for name mangling purposes. 
    46064626 * Create one by taking the template declaration name and adding 
    46074627 * the type signature for it. 
    46084628 */ 
    46094629 
    4610 Identifier *TemplateInstance::genIdent(
     4630Identifier *TemplateInstance::genIdent(Objects *args
    46114631{   OutBuffer buf; 
    46124632 
    46134633    //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars()); 
    46144634    char *id = tempdecl->ident->toChars(); 
    46154635    buf.printf("__T%zu%s", strlen(id), id); 
    4616     Objects *args = tiargs; 
    46174636    for (int i = 0; i < args->dim; i++) 
    46184637    {   Object *o = (Object *)args->data[i]; 
    46194638        Type *ta = isType(o); 
    46204639        Expression *ea = isExpression(o); 
    46214640        Dsymbol *sa = isDsymbol(o); 
    46224641        Tuple *va = isTuple(o); 
    46234642        //printf("\to [%d] %p ta %p ea %p sa %p va %p\n", i, o, ta, ea, sa, va); 
    46244643        if (ta) 
    46254644        { 
    46264645            buf.writeByte('T'); 
    46274646            if (ta->deco) 
    46284647                buf.writestring(ta->deco); 
    46294648            else 
    46304649            { 
    46314650#ifdef DEBUG 
    46324651                printf("ta = %d, %s\n", ta->ty, ta->toChars()); 
    46334652#endif 
    46344653                assert(global.errors); 
    46354654            } 
    46364655        } 
     
    51815200                scope = scx ? scx : new Scope(*sc); 
    51825201                scope->setNoFree(); 
    51835202                scope->module->addDeferredSemantic(this); 
    51845203            } 
    51855204            return; 
    51865205        } 
    51875206    } 
    51885207 
    51895208    // Run semantic on each argument, place results in tiargs[] 
    51905209    semanticTiargs(sc); 
    51915210    if (errors) 
    51925211        return; 
    51935212 
    51945213    tempdecl = findBestMatch(sc); 
    51955214    if (!tempdecl) 
    51965215    {   inst = this; 
    51975216        return;         // error recovery 
    51985217    } 
    51995218 
    52005219    if (!ident) 
    5201         ident = genIdent(); 
     5220        ident = genIdent(tiargs); 
    52025221 
    52035222    inst = this; 
    52045223    parent = sc->parent; 
    52055224 
    52065225    /* Detect recursive mixin instantiations. 
    52075226     */ 
    52085227    for (Dsymbol *s = parent; s; s = s->parent) 
    52095228    { 
    52105229        //printf("\ts = '%s'\n", s->toChars()); 
    52115230        TemplateMixin *tm = s->isTemplateMixin(); 
    52125231        if (!tm || tempdecl != tm->tempdecl) 
    52135232            continue; 
    52145233 
    52155234        /* Different argument list lengths happen with variadic args 
    52165235         */ 
    52175236        if (tiargs->dim != tm->tiargs->dim) 
    52185237            continue; 
    52195238 
    52205239        for (int i = 0; i < tiargs->dim; i++) 
    52215240        {   Object *o = (Object *)tiargs->data[i]; 
  • trunk/src/template.h

    r495 r809  
    309309    void semantic3(Scope *sc); 
    310310    void inlineScan(); 
    311311    void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 
    312312    Dsymbol *toAlias();                 // resolve real symbol 
    313313    const char *kind(); 
    314314    int oneMember(Dsymbol **ps); 
    315315    int needsTypeInference(Scope *sc); 
    316316    char *toChars(); 
    317317    char *mangle(); 
    318318    void printInstantiationTrace(); 
    319319 
    320320    void toObjFile(int multiobj);                       // compile to .obj file 
    321321 
    322322    // Internal 
    323323    static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags); 
    324324    void semanticTiargs(Scope *sc); 
    325325    TemplateDeclaration *findTemplateDeclaration(Scope *sc); 
    326326    TemplateDeclaration *findBestMatch(Scope *sc); 
    327327    void declareParameters(Scope *sc); 
    328328    int hasNestedArgs(Objects *tiargs); 
    329     Identifier *genIdent(); 
     329    Identifier *genIdent(Objects *args); 
    330330 
    331331    TemplateInstance *isTemplateInstance() { return this; } 
    332332    AliasDeclaration *isAliasDeclaration(); 
    333333}; 
    334334 
    335335struct TemplateMixin : TemplateInstance 
    336336{ 
    337337    Array *idents; 
    338338    Type *tqual; 
    339339 
    340340    TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Array *idents, Objects *tiargs); 
    341341    Dsymbol *syntaxCopy(Dsymbol *s); 
    342342    void semantic(Scope *sc); 
    343343    void semantic2(Scope *sc); 
    344344    void semantic3(Scope *sc); 
    345345    void inlineScan(); 
    346346    const char *kind(); 
    347347    int oneMember(Dsymbol **ps); 
    348348    int hasPointers(); 
    349349    char *toChars();