Permalink
Browse files

Merge pull request #1028 from 9rnsr/fix_aliasthis

Issue 7437,7980,8053 - Partial fix for stack overflow with recursive alias this
  • Loading branch information...
2 parents 2cab1b0 + 4759e8a commit ef9a73ca6719172c51b1abf0b94d238d1df87674 @WalterBright WalterBright committed Mar 7, 2013
Showing with 418 additions and 96 deletions.
  1. +38 −0 src/cast.c
  2. +53 −32 src/expression.c
  3. +4 −0 src/expression.h
  4. +50 −10 src/mtype.c
  5. +13 −0 src/mtype.h
  6. +102 −54 src/opover.c
  7. +158 −0 test/runnable/aliasthis.d
View
@@ -2137,6 +2137,14 @@ int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression
assert(t1);
Type *t = t1;
+ /* The start type of alias this type recursion.
+ * In following case, we should save A, and stop recursion
+ * if it appears again.
+ * X -> Y -> [A] -> B -> A -> B -> ...
+ */
+ Type *att1 = NULL;
+ Type *att2 = NULL;
+
//if (t1) printf("\tt1 = %s\n", t1->toChars());
//if (t2) printf("\tt2 = %s\n", t2->toChars());
#ifdef DEBUG
@@ -2440,12 +2448,22 @@ int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression
}
else if (t1->ty == Tstruct && ((TypeStruct *)t1)->sym->aliasthis)
{
+ if (att1 && e1->type == att1)
+ goto Lincompatible;
+ if (!att1 && e1->type->checkAliasThisRec())
+ att1 = e1->type;
+ //printf("att tmerge(c || c) e1 = %s\n", e1->type->toChars());
e1 = resolveAliasThis(sc, e1);
t1 = e1->type;
continue;
}
else if (t2->ty == Tstruct && ((TypeStruct *)t2)->sym->aliasthis)
{
+ if (att2 && e2->type == att2)
+ goto Lincompatible;
+ if (!att2 && e2->type->checkAliasThisRec())
+ att2 = e2->type;
+ //printf("att tmerge(c || c) e2 = %s\n", e2->type->toChars());
e2 = resolveAliasThis(sc, e2);
t2 = e2->type;
continue;
@@ -2481,11 +2499,21 @@ int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression
Expression *e2b = NULL;
if (ts2->sym->aliasthis)
{
+ if (att2 && e2->type == att2)
+ goto Lincompatible;
+ if (!att2 && e2->type->checkAliasThisRec())
+ att2 = e2->type;
+ //printf("att tmerge(s && s) e2 = %s\n", e2->type->toChars());
e2b = resolveAliasThis(sc, e2);
i1 = e2b->implicitConvTo(t1);
}
if (ts1->sym->aliasthis)
{
+ if (att1 && e1->type == att1)
+ goto Lincompatible;
+ if (!att1 && e1->type->checkAliasThisRec())
+ att1 = e1->type;
+ //printf("att tmerge(s && s) e1 = %s\n", e1->type->toChars());
e1b = resolveAliasThis(sc, e1);
i2 = e1b->implicitConvTo(t2);
}
@@ -2513,13 +2541,23 @@ int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression
{
if (t1->ty == Tstruct && ((TypeStruct *)t1)->sym->aliasthis)
{
+ if (att1 && e1->type == att1)
+ goto Lincompatible;
+ if (!att1 && e1->type->checkAliasThisRec())
+ att1 = e1->type;
+ //printf("att tmerge(s || s) e1 = %s\n", e1->type->toChars());
e1 = resolveAliasThis(sc, e1);
t1 = e1->type;
t = t1;
goto Lagain;
}
if (t2->ty == Tstruct && ((TypeStruct *)t2)->sym->aliasthis)
{
+ if (att2 && e2->type == att2)
+ goto Lincompatible;
+ if (!att2 && e2->type->checkAliasThisRec())
+ att2 = e2->type;
+ //printf("att tmerge(s || s) e2 = %s\n", e2->type->toChars());
e2 = resolveAliasThis(sc, e2);
t2 = e2->type;
t = t2;
View
@@ -1980,8 +1980,12 @@ Expression *Expression::checkToBoolean(Scope *sc)
assert(type);
#endif
- // Structs can be converted to bool using opCast(bool)()
+ Expression *e = this;
+ Type *t = type;
Type *tb = type->toBasetype();
+ Type *att = NULL;
+Lagain:
+ // Structs can be converted to bool using opCast(bool)()
if (tb->ty == Tstruct)
{ AggregateDeclaration *ad = ((TypeStruct *)tb)->sym;
/* Don't really need to check for opCast first, but by doing so we
@@ -1990,26 +1994,29 @@ Expression *Expression::checkToBoolean(Scope *sc)
Dsymbol *fd = search_function(ad, Id::cast);
if (fd)
{
- Expression *e = new CastExp(loc, this, Type::tbool);
+ e = new CastExp(loc, e, Type::tbool);
e = e->semantic(sc);
return e;
}
// Forward to aliasthis.
- if (ad->aliasthis)
+ if (ad->aliasthis && tb != att)
{
- Expression *e = resolveAliasThis(sc, this);
- e = e->checkToBoolean(sc);
- return e;
+ if (!att && tb->checkAliasThisRec())
+ att = tb;
+ e = resolveAliasThis(sc, e);
+ t = e->type;
+ tb = e->type->toBasetype();
+ goto Lagain;
}
}
- if (!type->checkBoolean())
- { if (type->toBasetype() != Type::terror)
- error("expression %s of type %s does not have a boolean value", toChars(), type->toChars());
+ if (!t->checkBoolean())
+ { if (tb != Type::terror)
+ error("expression %s of type %s does not have a boolean value", toChars(), t->toChars());
return new ErrorExp();
}
- return this;
+ return e;
}
/****************************
@@ -6126,6 +6133,7 @@ UnaExp::UnaExp(Loc loc, enum TOK op, int size, Expression *e1)
: Expression(loc, op, size)
{
this->e1 = e1;
+ this->att1 = NULL;
}
Expression *UnaExp::syntaxCopy()
@@ -6166,6 +6174,9 @@ BinExp::BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2)
{
this->e1 = e1;
this->e2 = e2;
+
+ this->att1 = NULL;
+ this->att2 = NULL;
}
Expression *BinExp::syntaxCopy()
@@ -7992,8 +8003,10 @@ Expression *CallExp::semantic(Scope *sc)
if (e1->op != TOKtype)
{
- if (ad->aliasthis)
+ if (ad->aliasthis && e1->type != att1)
{
+ if (!att1 && e1->type->checkAliasThisRec())
+ att1 = e1->type;
e1 = resolveAliasThis(sc, e1);
goto Lagain;
}
@@ -9421,8 +9434,10 @@ Expression *SliceExp::semantic(Scope *sc)
e = e->semantic(sc);
return e;
}
- if (ad->aliasthis)
+ if (ad->aliasthis && e1->type != att1)
{
+ if (!att1 && e1->type->checkAliasThisRec())
+ att1 = e1->type;
e1 = resolveAliasThis(sc, e1);
goto Lagain;
}
@@ -10249,6 +10264,7 @@ Expression *AssignExp::semantic(Scope *sc)
ae->e1 = ae->e1->semantic(sc);
ae->e1 = resolveProperties(sc, ae->e1);
+ Expression *e1 = ae->e1;
Type *t1 = ae->e1->type->toBasetype();
if (t1->ty == Tstruct)
{
@@ -10267,26 +10283,28 @@ Expression *AssignExp::semantic(Scope *sc)
Expressions *a = (Expressions *)ae->arguments->copy();
a->insert(0, e2);
- Expression *e = new DotIdExp(loc, ae->e1, Id::indexass);
+ Expression *e = new DotIdExp(loc, e1, Id::indexass);
e = new CallExp(loc, e, a);
e = e->semantic(sc);
return e;
}
}
// No opIndexAssign found yet, but there might be an alias this to try.
- if (ad && ad->aliasthis)
- { Expression *e = resolveAliasThis(sc, ae->e1);
- Type *t = e->type->toBasetype();
-
- if (t->ty == Tstruct)
+ if (ad && ad->aliasthis && t1 != att1)
+ {
+ if (!att1 && t1->checkAliasThisRec())
+ att1 = t1;
+ e1 = resolveAliasThis(sc, e1);
+ t1 = e1->type->toBasetype();
+ if (t1->ty == Tstruct)
{
- ad = ((TypeStruct *)t)->sym;
+ ad = ((TypeStruct *)t1)->sym;
goto L1;
}
- else if (t->ty == Tclass)
+ else if (t1->ty == Tclass)
{
- ad = ((TypeClass *)t)->sym;
+ ad = ((TypeClass *)t1)->sym;
goto L1;
}
}
@@ -10296,14 +10314,15 @@ Expression *AssignExp::semantic(Scope *sc)
* converted to a.opSlice() already.
*/
if (e1->op == TOKslice)
- { Type *t1;
+ {
SliceExp *ae = (SliceExp *)e1;
AggregateDeclaration *ad = NULL;
Identifier *id = Id::index;
ae->e1 = ae->e1->semantic(sc);
ae->e1 = resolveProperties(sc, ae->e1);
- t1 = ae->e1->type->toBasetype();
+ Expression *e1 = ae->e1;
+ Type *t1 = ae->e1->type->toBasetype();
if (t1->ty == Tstruct)
{
ad = ((TypeStruct *)t1)->sym;
@@ -10324,26 +10343,28 @@ Expression *AssignExp::semantic(Scope *sc)
{ a->push(ae->lwr);
a->push(ae->upr);
}
- Expression *e = new DotIdExp(loc, ae->e1, Id::sliceass);
+ Expression *e = new DotIdExp(loc, e1, Id::sliceass);
e = new CallExp(loc, e, a);
e = e->semantic(sc);
return e;
}
}
// No opSliceAssign found yet, but there might be an alias this to try.
- if (ad && ad->aliasthis)
- { Expression *e = resolveAliasThis(sc, ae->e1);
- Type *t = e->type->toBasetype();
-
- if (t->ty == Tstruct)
+ if (ad && ad->aliasthis && t1 != att1)
+ {
+ if (!att1 && t1->checkAliasThisRec())
+ att1 = t1;
+ e1 = resolveAliasThis(sc, e1);
+ t1 = e1->type->toBasetype();
+ if (t1->ty == Tstruct)
{
- ad = ((TypeStruct *)t)->sym;
+ ad = ((TypeStruct *)t1)->sym;
goto L2;
}
- else if (t->ty == Tclass)
+ else if (t1->ty == Tclass)
{
- ad = ((TypeClass *)t)->sym;
+ ad = ((TypeClass *)t1)->sym;
goto L2;
}
}
View
@@ -767,6 +767,7 @@ struct IsExp : Expression
struct UnaExp : Expression
{
Expression *e1;
+ Type *att1; // Save alias this type to detect recursion
UnaExp(Loc loc, enum TOK op, int size, Expression *e1);
Expression *syntaxCopy();
@@ -790,6 +791,9 @@ struct BinExp : Expression
Expression *e1;
Expression *e2;
+ Type *att1; // Save alias this type to detect recursion
+ Type *att2; // Save alias this type to detect recursion
+
BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Oops, something went wrong.

0 comments on commit ef9a73c

Please sign in to comment.