Skip to content

Commit

Permalink
Merge pull request #2212 from WalterBright/refactor_error_check2
Browse files Browse the repository at this point in the history
2nd try at pull #2205
  • Loading branch information
yebblies committed Jun 19, 2013
2 parents f4a2748 + e04d591 commit 584bf17
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 31 deletions.
104 changes: 74 additions & 30 deletions src/template.c
Expand Up @@ -44,7 +44,8 @@ long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
#define IDX_NOTFOUND (0x12345678) // index is not found

size_t templateParameterLookup(Type *tparam, TemplateParameters *parameters);
int arrayObjectMatch(Objects *oa1, Objects *oa2, TemplateDeclaration *tempdecl, Scope *sc);
int arrayObjectMatch(Objects *oa1, Objects *oa2);
int arrayCheckRecursiveExpansion(Objects *oa1, TemplateDeclaration *tempdecl, Scope *sc);

/********************************************
* These functions substitute for dynamic_cast. dynamic_cast does not work
Expand Down Expand Up @@ -207,7 +208,7 @@ Expression *getValue(Dsymbol *&s)
* Else, return 0.
*/

int match(RootObject *o1, RootObject *o2, TemplateDeclaration *tempdecl, Scope *sc)
int match(RootObject *o1, RootObject *o2)
{
Type *t1 = isType(o1);
Type *t2 = isType(o2);
Expand All @@ -231,25 +232,6 @@ int match(RootObject *o1, RootObject *o2, TemplateDeclaration *tempdecl, Scope *

if (t1)
{
/* if t1 is an instance of ti, then give error
* about recursive expansions.
*/
Dsymbol *s = t1->toDsymbol(sc);
if (s && s->parent)
{ TemplateInstance *ti1 = s->parent->isTemplateInstance();
if (ti1 && ti1->tempdecl == tempdecl)
{
for (Scope *sc1 = sc; sc1; sc1 = sc1->enclosing)
{
if (sc1->scopesym == ti1)
{
tempdecl->error("recursive template expansion for template argument %s", t1->toChars());
return 1; // fake a match
}
}
}
}

//printf("t1 = %s\n", t1->toChars());
//printf("t2 = %s\n", t2->toChars());
if (!t2 || !t1->equals(t2))
Expand Down Expand Up @@ -290,7 +272,7 @@ int match(RootObject *o1, RootObject *o2, TemplateDeclaration *tempdecl, Scope *
{
if (!u2)
goto Lnomatch;
if (!arrayObjectMatch(&u1->objects, &u2->objects, tempdecl, sc))
if (!arrayObjectMatch(&u1->objects, &u2->objects))
goto Lnomatch;
}
//printf("match\n");
Expand All @@ -305,7 +287,7 @@ int match(RootObject *o1, RootObject *o2, TemplateDeclaration *tempdecl, Scope *
/************************************
* Match an array of them.
*/
int arrayObjectMatch(Objects *oa1, Objects *oa2, TemplateDeclaration *tempdecl, Scope *sc)
int arrayObjectMatch(Objects *oa1, Objects *oa2)
{
if (oa1 == oa2)
return 1;
Expand All @@ -314,14 +296,68 @@ int arrayObjectMatch(Objects *oa1, Objects *oa2, TemplateDeclaration *tempdecl,
for (size_t j = 0; j < oa1->dim; j++)
{ RootObject *o1 = (*oa1)[j];
RootObject *o2 = (*oa2)[j];
if (!match(o1, o2, tempdecl, sc))
if (!match(o1, o2))
{
return 0;
}
}
return 1;
}


/******************************
* Check template argument o1 to see if it is a recursive expansion of tempdecl in scope sc.
* If so, issue error and return 1.
*/

int checkRecursiveExpansion(RootObject *o1, TemplateDeclaration *tempdecl, Scope *sc)
{
if (Type *t1 = isType(o1))
{
/* if t1 is an instance of ti, then give error
* about recursive expansions.
*/
Dsymbol *s = t1->toDsymbol(sc);
if (s && s->parent)
{
TemplateInstance *ti1 = s->parent->isTemplateInstance();
if (ti1 && ti1->tempdecl == tempdecl)
{
for (Scope *sc1 = sc; sc1; sc1 = sc1->enclosing)
{
if (sc1->scopesym == ti1)
{
tempdecl->error("recursive template expansion for template argument %s", t1->toChars());
return 1;
}
}
}
}
}
else if (Tuple *u1 = isTuple(o1))
{
return arrayCheckRecursiveExpansion(&u1->objects, tempdecl, sc);
}
return 0; // no error
}


/************************************
* Match an array of them.
*/
int arrayCheckRecursiveExpansion(Objects *oa1, TemplateDeclaration *tempdecl, Scope *sc)
{
for (size_t j = 0; j < oa1->dim; j++)
{
RootObject *o1 = (*oa1)[j];
if (checkRecursiveExpansion(o1, tempdecl, sc))
return 1;
}
return 0;
}



/****************************************
* This makes a 'pretty' version of the template arguments.
* It's analogous to genIdent() which makes a mangled version.
Expand Down Expand Up @@ -1867,7 +1903,10 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Scope *sc, Objec
int nmatches = 0;
for (Previous *p = previous; p; p = p->prev)
{
if (arrayObjectMatch(p->dedargs, dedargs, this, sc))
if (arrayCheckRecursiveExpansion(p->dedargs, this, sc))
goto Lnomatch;

if (arrayObjectMatch(p->dedargs, dedargs))
{
//printf("recursive, no match p->sc=%p %p %s\n", p->sc, this, this->toChars());
/* It must be a subscope of p->sc, other scope chains are not recursive
Expand Down Expand Up @@ -1971,7 +2010,8 @@ RootObject *TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *
if (va && td)
{ Tuple tup;
tup.objects = *td->objects;
if (match(va, &tup, this, sc))
checkRecursiveExpansion(va, this, sc);
if (match(va, &tup))
{
return o;
}
Expand Down Expand Up @@ -2609,7 +2649,7 @@ PROT TemplateDeclaration::prot()
* If so, return that existing instance.
*/

TemplateInstance *TemplateDeclaration::findExistingInstance(TemplateInstance *tithis, Scope *sc, Expressions *fargs)
TemplateInstance *TemplateDeclaration::findExistingInstance(TemplateInstance *tithis, Expressions *fargs)
{
for (size_t i = 0; i < instances.dim; i++)
{
Expand All @@ -2627,7 +2667,7 @@ TemplateInstance *TemplateDeclaration::findExistingInstance(TemplateInstance *ti
}
//printf("parent = %s, ti->parent = %s\n", parent->toPrettyChars(), ti->parent->toPrettyChars());

if (!arrayObjectMatch(&tithis->tdtypes, &ti->tdtypes, this, sc))
if (!arrayObjectMatch(&tithis->tdtypes, &ti->tdtypes))
continue;

/* Template functions may have different instantiations based on
Expand Down Expand Up @@ -3393,7 +3433,9 @@ MATCH TypeInstance::deduceType(Scope *sc,
Tuple *v = (Tuple *)(*dedtypes)[j];
if (v)
{
if (!match(v, vt, tempinst->tempdecl, sc))
if (checkRecursiveExpansion(v, tempinst->tempdecl, sc))
goto Lnomatch;
if (!match(v, vt))
goto Lnomatch;
}
else
Expand Down Expand Up @@ -5086,11 +5128,13 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)

hasNestedArgs(tiargs);

arrayCheckRecursiveExpansion(&tdtypes, tempdecl, sc);

/* See if there is an existing TemplateInstantiation that already
* implements the typeargs. If so, just refer to that one instead.
*/
{
TemplateInstance *ti = tempdecl->findExistingInstance(this, sc, fargs);
TemplateInstance *ti = tempdecl->findExistingInstance(this, fargs);
if (ti)
{
// It's a match
Expand Down
2 changes: 1 addition & 1 deletion src/template.h
Expand Up @@ -100,7 +100,7 @@ class TemplateDeclaration : public ScopeDsymbol
FuncDeclaration *deduceFunctionTemplate(Loc loc, Scope *sc, Objects *tiargs, Type *tthis, Expressions *fargs, int flags = 0);
RootObject *declareParameter(Scope *sc, TemplateParameter *tp, RootObject *o);
FuncDeclaration *doHeaderInstantiation(Scope *sc, Objects *tdargs, Type *tthis, Expressions *fargs);
TemplateInstance *findExistingInstance(TemplateInstance *tithis, Scope *sc, Expressions *fargs);
TemplateInstance *findExistingInstance(TemplateInstance *tithis, Expressions *fargs);
size_t addInstance(TemplateInstance *ti);
void removeInstance(size_t handle);

Expand Down

0 comments on commit 584bf17

Please sign in to comment.