Skip to content

Commit

Permalink
Merge pull request #4715 from 9rnsr/fix14642
Browse files Browse the repository at this point in the history
[REG2.066] Issue 14642 - ICE in ctfeInterpret
  • Loading branch information
WalterBright committed Jun 3, 2015
2 parents 55d7491 + e555b56 commit a74d774
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 40 deletions.
7 changes: 5 additions & 2 deletions src/declaration.c
Original file line number Diff line number Diff line change
Expand Up @@ -1679,10 +1679,14 @@ void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset,
ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced
return;
}

// List in ad->fields. Even if the type is error, it's necessary to avoid
// pointless error diagnostic "more initializers than fields" on struct literal.
ad->fields.push(this);

if (t->ty == Terror)
return;


unsigned memsize = (unsigned)t->size(loc); // size of member
unsigned memalignsize = Target::fieldalign(t); // size of member for alignment purposes

Expand All @@ -1692,7 +1696,6 @@ void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset,
//printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);

//printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad->toChars(), offset, memsize);
ad->fields.push(this);
}

const char *VarDeclaration::kind()
Expand Down
1 change: 1 addition & 0 deletions src/interpret.c
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,7 @@ Expression *ctfeInterpret(Expression *e)
{
if (e->op == TOKerror)
return e;
assert(e->type); // Bugzilla 14642
//assert(e->type->ty != Terror); // FIXME
if (e->type->ty == Terror)
return new ErrorExp();
Expand Down
29 changes: 24 additions & 5 deletions src/mtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -6614,13 +6614,32 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,

if (VarDeclaration *v = s->isVarDeclaration())
{
if (v && v->inuse && (!v->type || !v->type->deco)) // Bugzilla 9494
/* This is mostly same with DsymbolExp::semantic(), but we cannot use it
* because some variables used in type context need to prevent lowering
* to a literal or contextful expression. For example:
*
* enum a = 1; alias b = a;
* template X(alias e){ alias v = e; } alias x = X!(1);
* struct S { int v; alias w = v; }
* // TypeIdentifier 'a', 'e', and 'v' should be TOKvar,
* // because getDsymbol() need to work in AliasDeclaration::semantic().
*/
if (!v->type || !v->type->deco)
{
error(loc, "circular reference to '%s'", v->toPrettyChars());
*pe = new ErrorExp();
return;
if (v->inuse) // Bugzilla 9494
{
error(loc, "circular reference to '%s'", v->toPrettyChars());
*pe = new ErrorExp();
return;
}
if (v->sem < SemanticDone && v->scope)
v->semantic(NULL);
}
*pe = new VarExp(loc, v);
assert(v->type); // Bugzilla 14642
if (v->type->ty == Terror)
*pt = Type::terror;
else
*pe = new VarExp(loc, v);
return;
}
#if 0
Expand Down
59 changes: 26 additions & 33 deletions src/template.c
Original file line number Diff line number Diff line change
Expand Up @@ -6631,47 +6631,40 @@ bool TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
{
Lexpr:
//printf("+[%d] ea = %s %s\n", j, Token::toChars(ea->op), ea->toChars());
if (!(flags & 1)) sc = sc->startCTFE();
ea = ea->semantic(sc);
if (!(flags & 1)) sc = sc->endCTFE();
if (flags & 1) // only used by __traits, must not interpret the args
if (flags & 1) // only used by __traits
{
VarDeclaration *v;
if (ea->op == TOKvar && (v = ((VarExp *)ea)->var->isVarDeclaration()) != NULL &&
!(v->storage_class & STCtemplateparameter))
{
if (v->sem < SemanticDone && v->scope)
v->semantic(NULL);
// skip optimization for variable symbols
}
else
ea = ea->semantic(sc);

// must not interpret the args, excepting template parameters
if (ea->op != TOKvar ||
(((VarExp *)ea)->var->storage_class & STCtemplateparameter))
{
ea = ea->optimize(WANTvalue);
}
}
else if (ea->op == TOKvar)
else
{
VarDeclaration *v = ((VarExp *)ea)->var->isVarDeclaration();
if (v && !(v->storage_class & STCtemplateparameter))
sc = sc->startCTFE();
ea = ea->semantic(sc);
sc = sc->endCTFE();

if (ea->op == TOKvar)
{
if (v->sem < SemanticDone && v->scope)
v->semantic(NULL);
/* This test is to skip substituting a const var with
* its initializer. The problem is the initializer won't
* match with an 'alias' parameter. Instead, do the
* const substitution in TemplateValueParameter::matchArg().
*/
}
else if (definitelyValueParameter(ea))
{
if (ea->checkValue()) // check void expression
ea = new ErrorExp();
unsigned int olderrs = global.errors;
ea = ea->ctfeInterpret();
if (global.errors != olderrs)
ea = new ErrorExp();
}

/* This test is to skip substituting a const var with
* its initializer. The problem is the initializer won't
* match with an 'alias' parameter. Instead, do the
* const substitution in TemplateValueParameter::matchArg().
*/
}
else if (definitelyValueParameter(ea))
{
if (ea->checkValue()) // check void expression
ea = new ErrorExp();
unsigned int olderrs = global.errors;
ea = ea->ctfeInterpret();
if (global.errors != olderrs)
ea = new ErrorExp();
}
//printf("-[%d] ea = %s %s\n", j, Token::toChars(ea->op), ea->toChars());
if (ea->op == TOKtuple)
Expand Down
52 changes: 52 additions & 0 deletions test/fail_compilation/ice14642.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice14642.d(47): Error: undefined identifier 'errorValue'
fail_compilation/ice14642.d(23): Error: template instance ice14642.X.NA!() error instantiating
---
*/

alias TypeTuple(T...) = T;

struct X
{
static struct NA()
{
X x;

void check()
{
x.func();
}
}

alias na = NA!();

auto func()
{
Y* p;
p.func();
}
}

struct Y
{
mixin Mix;
}

template Mix()
{
void func()
{
auto z = Z(null);
}
}

struct Type(size_t v) {}

enum errVal = errorValue;

struct Z
{
Type!errVal v;
}

0 comments on commit a74d774

Please sign in to comment.