Skip to content

Commit

Permalink
fix Issue 12574 - [ICE](statement.c, line 713) with reduce with wrong…
Browse files Browse the repository at this point in the history
… tuple arity

Make `TemplateInstance::semanticTiargs` reentrant against semantic errors.
  • Loading branch information
9rnsr committed Apr 15, 2014
1 parent d4f778f commit 5327b68
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 11 deletions.
28 changes: 22 additions & 6 deletions src/template.c
Expand Up @@ -6362,9 +6362,13 @@ bool TemplateInstance::semanticTiargs(Scope *sc)
//printf("+TemplateInstance::semanticTiargs() %s\n", toChars());
if (semantictiargsdone)
return true;
semantictiargsdone = 1;
semanticTiargs(loc, sc, tiargs, 0);
return arrayObjectIsError(tiargs) == 0;
if (semanticTiargs(loc, sc, tiargs, 0))
{
// cache the result iff semantic analysis succeeded entirely
semantictiargsdone = 1;
return true;
}
return false;
}

/**********************************
Expand Down Expand Up @@ -6429,12 +6433,13 @@ bool definitelyValueParameter(Expression *e)
* 2: don't devolve Parameter to Type
*/

void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags)
bool TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags)
{
// Run semantic on each argument, place results in tiargs[]
//printf("+TemplateInstance::semanticTiargs()\n");
if (!tiargs)
return;
return true;
bool err = false;
for (size_t j = 0; j < tiargs->dim; j++)
{
RootObject *o = (*tiargs)[j];
Expand Down Expand Up @@ -6478,6 +6483,11 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
j--;
continue;
}
if (ta->ty == Terror)
{
err = true;
continue;
}
(*tiargs)[j] = ta->merge2();
}
else if (ea)
Expand Down Expand Up @@ -6534,6 +6544,11 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
j--;
continue;
}
if (ea->op == TOKerror)
{
err = true;
continue;
}
(*tiargs)[j] = ea;

if (ea->op == TOKtype)
Expand Down Expand Up @@ -6642,6 +6657,7 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
printf("\ttiargs[%d] = ta %p, ea %p, sa %p, va %p\n", j, ta, ea, sa, va);
}
#endif
return !err;
}

bool TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs)
Expand Down Expand Up @@ -7229,7 +7245,7 @@ Identifier *TemplateInstance::genIdent(Objects *args)

Identifier *TemplateInstance::getIdent()
{
if (!ident && inst)
if (!ident && inst && !errors)
ident = genIdent(tiargs); // need an identifier for name mangling purposes.
return ident;
}
Expand Down
2 changes: 1 addition & 1 deletion src/template.h
Expand Up @@ -349,7 +349,7 @@ class TemplateInstance : public ScopeDsymbol
// Internal
bool findTemplateDeclaration(Scope *sc, WithScopeSymbol **pwithsym);
bool updateTemplateDeclaration(Scope *sc, Dsymbol *s);
static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags);
static bool semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags);
bool semanticTiargs(Scope *sc);
bool findBestMatch(Scope *sc, Expressions *fargs);
bool needsTypeInference(Scope *sc, int flag = 0);
Expand Down
14 changes: 10 additions & 4 deletions src/traits.c
Expand Up @@ -208,7 +208,8 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
if (e->ident != Id::compiles && e->ident != Id::isSame &&
e->ident != Id::identifier && e->ident != Id::getProtection)
{
TemplateInstance::semanticTiargs(e->loc, sc, e->args, 1);
if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 1))
return new ErrorExp();
}
size_t dim = e->args ? e->args->dim : 0;
Declaration *d;
Expand Down Expand Up @@ -343,7 +344,8 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
* a symbol should not be folded to a constant.
* Bit 1 means don't convert Parameter to Type if Parameter has an identifier
*/
TemplateInstance::semanticTiargs(e->loc, sc, e->args, 2);
if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 2))
return new ErrorExp();

if (dim != 1)
goto Ldimerror;
Expand Down Expand Up @@ -375,9 +377,12 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)

Scope *sc2 = sc->push();
sc2->flags = sc->flags | SCOPEnoaccesscheck;
TemplateInstance::semanticTiargs(e->loc, sc2, e->args, 1);
bool ok = TemplateInstance::semanticTiargs(e->loc, sc2, e->args, 1);
sc2->pop();

if (!ok)
return new ErrorExp();

RootObject *o = (*e->args)[0];
Dsymbol *s = getDsymbol(o);
if (!s)
Expand Down Expand Up @@ -769,7 +774,8 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
*/
if (dim != 2)
goto Ldimerror;
TemplateInstance::semanticTiargs(e->loc, sc, e->args, 0);
if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 0))
return new ErrorExp();
RootObject *o1 = (*e->args)[0];
RootObject *o2 = (*e->args)[1];
Dsymbol *s1 = getDsymbol(o1);
Expand Down
55 changes: 55 additions & 0 deletions test/fail_compilation/ice12574.d
@@ -0,0 +1,55 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice12574.d(41): Error: tuple index 2 exceeds length 2
fail_compilation/ice12574.d(41): Error: tuple index 2 exceeds 2
fail_compilation/ice12574.d(54): Error: template instance ice12574.reduce!("a", "a").reduce!(Tuple!(int, int, int)) error instantiating
---
*/

struct Tuple(T...)
{
alias Types = T;
T field;
alias field this;
}
Tuple!A tuple(A...)(A args) { return typeof(return)(args); }

template binaryFun(alias fun)
{
static if (is(typeof(fun) : string))
{
auto binaryFun(ElementType1, ElementType2)(auto ref ElementType1 __a, auto ref ElementType2 __b)
{
mixin("alias "~"a"~" = __a ;");
mixin("alias "~"b"~" = __b ;");
return mixin(fun);
}
}
else
{
alias binaryFun = fun;
}
}

template reduce(fun...)
{
auto reduce(Seed)(Seed result)
{
foreach (i, Unused; Seed.Types)
{
result[i] = binaryFun!(fun[i])(1, 1); // here
}
return result;
}
}

int foo(int value)
{
return value;
}

void main()
{
reduce!("a", "a")(tuple(1, 1, 1));
}

0 comments on commit 5327b68

Please sign in to comment.