Skip to content

Commit

Permalink
Merge pull request #3984 from 9rnsr/fix13437
Browse files Browse the repository at this point in the history
Issue 13437 - [e2ir] ICE in e2ir.c 4616
  • Loading branch information
WalterBright committed Sep 14, 2014
2 parents 7c497d8 + 1b36922 commit 350c46f
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 27 deletions.
27 changes: 12 additions & 15 deletions src/cast.c
Expand Up @@ -59,7 +59,7 @@ Expression *implicitCastTo(Expression *e, Scope *sc, Type *t)
{
if (match == MATCHconst &&
(e->type->constConv(t) ||
!e->isLvalue() && e->type->immutableOf()->equals(t->immutableOf())))
!e->isLvalue() && e->type->equivalent(t)))
{
/* Do not emit CastExp for const conversions and
* unique conversions on rvalue.
Expand Down Expand Up @@ -272,15 +272,15 @@ MATCH implicitConvTo(Expression *e, Type *t)
Type *t1b = e->e1->type->toBasetype();
Type *t2b = e->e2->type->toBasetype();
if (t1b->ty == Tpointer && t2b->isintegral() &&
t1b->immutableOf()->equals(tb->immutableOf()))
t1b->equivalent(tb))
{
// ptr + offset
// ptr - offset
MATCH m = e->e1->implicitConvTo(t);
return (m > MATCHconst) ? MATCHconst : m;
}
if (t2b->ty == Tpointer && t1b->isintegral() &&
t2b->immutableOf()->equals(tb->immutableOf()))
t2b->equivalent(tb))
{
// offset + ptr
MATCH m = e->e2->implicitConvTo(t);
Expand Down Expand Up @@ -521,7 +521,7 @@ MATCH implicitConvTo(Expression *e, Type *t)
* and mutable to immutable. It works because, after all, a null
* doesn't actually point to anything.
*/
if (t->immutableOf()->equals(e->type->immutableOf()))
if (t->equivalent(e->type))
{
result = MATCHconst;
return;
Expand Down Expand Up @@ -1249,6 +1249,7 @@ MATCH implicitConvTo(Expression *e, Type *t)

void visit(SliceExp *e)
{
//printf("SliceExp::implicitConvTo e = %s, type = %s\n", e->toChars(), e->type->toChars());
visit((Expression *)e);
if (result != MATCHnomatch)
return;
Expand All @@ -1269,8 +1270,7 @@ MATCH implicitConvTo(Expression *e, Type *t)
* same mod bits.
*/
Type *t1b = e->e1->type->toBasetype();
if (tb->ty == Tarray &&
typeb->immutableOf()->equals(tb->immutableOf()))
if (tb->ty == Tarray && typeb->equivalent(tb))
{
Type *tbn = tb->nextOf();
Type *tx = NULL;
Expand Down Expand Up @@ -2156,25 +2156,22 @@ Expression *castTo(Expression *e, Scope *sc, Type *t)

void visit(SliceExp *e)
{
//printf("SliceExp::castTo e = %s, type = %s, t = %s\n", e->toChars(), e->type->toChars(), t->toChars());
Type *typeb = e->type->toBasetype();
Type *tb = t->toBasetype();

if (typeb->ty == Tarray && tb->ty == Tsarray)
if (typeb->ty == Tarray && (tb->ty == Tarray || tb->ty == Tsarray) &&
typeb->nextOf()->equivalent(tb->nextOf()))
{
// T[] to const(T)[]
// T[] to const(T)[dim]

/* If a SliceExp has Tsarray, it will become lvalue.
* That's handled in SliceExp::isLvalue and toLvalue
*/
result = e->copy();
result->type = t;
}
else if (typeb->ty == Tarray && tb->ty == Tarray &&
typeb->nextOf()->constConv(tb->nextOf()) == MATCHconst)
{
// immutable(T)[] to const(T)[]
// T [] to const(T)[]
result = e->copy();
result->type = t;
}
else
{
visit((Expression *)e);
Expand Down
11 changes: 8 additions & 3 deletions src/e2ir.c
Expand Up @@ -4388,9 +4388,9 @@ elem *toElem(Expression *e, IRState *irs)

void visit(SliceExp *se)
{
//printf("SliceExp::toElem()\n");
//printf("SliceExp::toElem() se = %s %s\n", se->type->toChars(), se->toChars());
Type *tb = se->type->toBasetype();
assert(tb->ty == Tarray || tb->ty == Tsarray && se->lwr);
assert(tb->ty == Tarray || tb->ty == Tsarray);
Type *t1 = se->e1->type->toBasetype();
elem *e = toElem(se->e1, irs);
if (se->lwr)
Expand Down Expand Up @@ -4484,10 +4484,15 @@ elem *toElem(Expression *e, IRState *irs)
e = el_combine(elwr, e);
e = el_combine(einit, e);
}
else if (t1->ty == Tsarray)
else if (t1->ty == Tsarray && tb->ty == Tarray)
{
e = sarray_toDarray(se->loc, t1, NULL, e);
}
else
{
assert(t1->ty == tb->ty); // Tarray or Tsarray
assert(t1->nextOf()->equivalent(tb->nextOf()));
}
el_setLoc(e, se->loc);
result = e;
}
Expand Down
2 changes: 1 addition & 1 deletion src/expression.c
Expand Up @@ -11427,7 +11427,7 @@ Expression *AssignExp::semantic(Scope *sc)
Type *t2n = t2->nextOf();
Type *t1n = t1->nextOf();
int offset;
if (t2n->immutableOf()->equals(t1n->immutableOf()) ||
if (t2n->equivalent(t1n) ||
t1n->isBaseOf(t2n, &offset) && offset == 0)
{
/* Allow copy of distinct qualifier elements.
Expand Down
5 changes: 5 additions & 0 deletions src/mtype.c
Expand Up @@ -182,6 +182,11 @@ bool Type::equals(RootObject *o)
return false;
}

bool Type::equivalent(Type *t)
{
return immutableOf()->equals(t->immutableOf());
}

char Type::needThisPrefix()
{
return 'M'; // name mangling prefix for functions needing 'this'
Expand Down
1 change: 1 addition & 0 deletions src/mtype.h
Expand Up @@ -237,6 +237,7 @@ class Type : public RootObject
Type *copy();
virtual Type *syntaxCopy();
bool equals(RootObject *o);
bool equivalent(Type *t);
// kludge for template.isType()
int dyncast() { return DYNCAST_TYPE; }
int covariant(Type *t, StorageClass *pstc = NULL);
Expand Down
4 changes: 2 additions & 2 deletions src/optimize.c
Expand Up @@ -322,7 +322,7 @@ Expression *Expression_optimize(Expression *e, int result, bool keepLvalue)
Expression *ex = ((PtrExp *)e->e1)->e1;
if (e->type->equals(ex->type))
ret = ex;
else if (e->type->toBasetype()->immutableOf()->equals(ex->type->toBasetype()->immutableOf()))
else if (e->type->toBasetype()->equivalent(ex->type->toBasetype()))
{
ret = ex->copy();
ret->type = e->type;
Expand Down Expand Up @@ -379,7 +379,7 @@ Expression *Expression_optimize(Expression *e, int result, bool keepLvalue)
Expression *ex = ((AddrExp *)e->e1)->e1;
if (e->type->equals(ex->type))
ret = ex;
else if (e->type->toBasetype()->immutableOf()->equals(ex->type->toBasetype()->immutableOf()))
else if (e->type->toBasetype()->equivalent(ex->type->toBasetype()))
{
ret = ex->copy();
ret->type = e->type;
Expand Down
9 changes: 3 additions & 6 deletions src/statement.c
Expand Up @@ -1894,8 +1894,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
key = var;
if (arg->storageClass & STCref)
{
if (!var->type->immutableOf()->equals(arg->type->immutableOf()) ||
!MODimplicitConv(var->type->mod, arg->type->mod))
if (var->type->constConv(arg->type) <= MATCHnomatch)
{
error("key type mismatch, %s to ref %s",
var->type->toChars(), arg->type->toChars());
Expand Down Expand Up @@ -1928,8 +1927,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
var->storage_class |= STCctorinit;

Type *t = tab->nextOf();
if (!t->immutableOf()->equals(arg->type->immutableOf()) ||
!MODimplicitConv(t->mod, arg->type->mod))
if (t->constConv(arg->type) <= MATCHnomatch)
{
error("argument type mismatch, %s to ref %s",
t->toChars(), arg->type->toChars());
Expand Down Expand Up @@ -2743,8 +2741,7 @@ Statement *ForeachRangeStatement::semantic(Scope *sc)
}
if (arg->storageClass & STCref)
{
if (!key->type->immutableOf()->equals(arg->type->immutableOf()) ||
!MODimplicitConv(key->type->mod, arg->type->mod))
if (key->type->constConv(arg->type) <= MATCHnomatch)
{
error("argument type mismatch, %s to ref %s",
key->type->toChars(), arg->type->toChars());
Expand Down
13 changes: 13 additions & 0 deletions test/runnable/xtest46.d
Expand Up @@ -7104,6 +7104,18 @@ void test13154()
assert(floats2 == [2, 1, 0]);
}

/***************************************************/
// 13437

ubyte[4] foo13437() { return [1,2,3,4]; }

void test13437()
{
auto n = cast(ubyte[4])foo13437()[]; // OK <- ICE: e2ir.c 4616
static assert(is(typeof(n) == ubyte[4]));
assert(n == [1,2,3,4]);
}

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

int main()
Expand Down Expand Up @@ -7399,6 +7411,7 @@ int main()
test12153();
test12937();
test13154();
test13437();

printf("Success\n");
return 0;
Expand Down

0 comments on commit 350c46f

Please sign in to comment.