Skip to content

Commit

Permalink
fix Issue 10056 - Strange Error with templates and string.format
Browse files Browse the repository at this point in the history
If IFTI error is gagged (`(flags&1) != 0` in deduceTemplateFunction), function body semantic should be delayed, as same as `FuncDeclaration::overloadResolve` do.

For the lazily function semantic, hasIdentity(Assign|Equals) should not allocate arguments `Expressions` on stack.
  • Loading branch information
9rnsr committed May 11, 2013
1 parent 869c537 commit 9577d07
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 12 deletions.
32 changes: 21 additions & 11 deletions src/clone.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ FuncDeclaration *AggregateDeclaration::hasIdentityOpAssign(Scope *sc)
Expression *er = new NullExp(loc, type); // dummy rvalue
Expression *el = new IdentifierExp(loc, Id::p); // dummy lvalue
el->type = type;
Expressions ar; ar.push(er);
Expressions al; al.push(el);
Expressions *a = new Expressions();
a->setDim(1);
FuncDeclaration *f = NULL;

unsigned errors = global.startGagging(); // Do not report errors, even if the
Expand All @@ -78,8 +78,13 @@ FuncDeclaration *AggregateDeclaration::hasIdentityOpAssign(Scope *sc)
sc = sc->push();
sc->speculative = true;

f = resolveFuncCall(loc, sc, assign, NULL, type, &ar, 1);
if (!f) f = resolveFuncCall(loc, sc, assign, NULL, type, &al, 1);
for (size_t i = 0; i < 2; i++)
{
(*a)[0] = (i == 0 ? er : el);
f = resolveFuncCall(loc, sc, assign, NULL, type, a, 1);
if (f)
break;
}

sc = sc->pop();
global.speculativeGag = oldspec;
Expand Down Expand Up @@ -359,6 +364,10 @@ FuncDeclaration *AggregateDeclaration::hasIdentityOpEquals(Scope *sc)
{
/* check identity opEquals exists
*/
Expression *er = new NullExp(loc, NULL); // dummy rvalue
Expression *el = new IdentifierExp(loc, Id::p); // dummy lvalue
Expressions *a = new Expressions();
a->setDim(1);
for (size_t i = 0; ; i++)
{
Type *tthis;
Expand All @@ -368,11 +377,6 @@ FuncDeclaration *AggregateDeclaration::hasIdentityOpEquals(Scope *sc)
if (i == 3) tthis = type->sharedOf();
if (i == 4) tthis = type->sharedConstOf();
if (i == 5) break;
Expression *er = new NullExp(loc, tthis); // dummy rvalue
Expression *el = new IdentifierExp(loc, Id::p); // dummy lvalue
el->type = tthis;
Expressions ar; ar.push(er);
Expressions al; al.push(el);
FuncDeclaration *f = NULL;

unsigned errors = global.startGagging(); // Do not report errors, even if the
Expand All @@ -381,8 +385,14 @@ FuncDeclaration *AggregateDeclaration::hasIdentityOpEquals(Scope *sc)
sc = sc->push();
sc->speculative = true;

f = resolveFuncCall(loc, sc, eq, NULL, tthis, &ar, 1);
if (!f) f = resolveFuncCall(loc, sc, eq, NULL, tthis, &al, 1);
for (size_t j = 0; j < 2; j++)
{
(*a)[0] = (j == 0 ? er : el);
(*a)[0]->type = tthis;
f = resolveFuncCall(loc, sc, eq, NULL, tthis, a, 1);
if (f)
break;
}

sc = sc->pop();
global.speculativeGag = oldspec;
Expand Down
3 changes: 2 additions & 1 deletion src/template.c
Original file line number Diff line number Diff line change
Expand Up @@ -2341,7 +2341,8 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Loc loc, Scope *sc,
}
}

fd_best->functionSemantic();
if (!(flags & 1))
fd_best->functionSemantic();

return fd_best;

Expand Down
66 changes: 66 additions & 0 deletions test/compilable/test10056.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
void main()
{
alias Zoo = Foo10056!(false, false, 1);
}

struct Foo10056(bool S, bool L, size_t N)
{
string bar()
{
Appender10056!(string) w;
char[] buf; put10056(w, buf);
return "";
}

public bool opEquals(T)(T other) //const
//If you add const, also fails to compile with 2.062.
{
alias Foo10056!(typeof(this), T, "CMP") P;
return false;
}
}

template Foo10056(T, U, string OP)
{
static if (T.ISEMPTY && U.ISEMPTY)
enum bool S = false;
else
enum bool S = false;

alias Foo10056 = Foo10056!(false, false, 0);
}

/**********************************************/

void put10056(R, E)(ref R r, E e)
{
static if (is(typeof(r.put(e))))
{
r.put(e);
}
else
{
static assert(false, "Cannot put a "~E.stringof~" into a "~R.stringof);
}
}

struct Appender10056(A : T[], T)
{
private template canPutItem(U)
{
enum bool canPutItem = is(U : T);
}
private template canPutRange(R)
{
enum bool canPutRange = is(typeof(Appender10056.init.put(R.init[0])));
}

void put(U)(U item) if (canPutItem!U)
{
char[T.sizeof == 1 ? 4 : 2] encoded;
put(encoded[]);
}
void put(R)(R items) if (canPutRange!R)
{
}
}

0 comments on commit 9577d07

Please sign in to comment.