Skip to content

Commit

Permalink
fix Issue 13816 - The compiler crashes with recursive tuple expansion
Browse files Browse the repository at this point in the history
  • Loading branch information
9rnsr committed Jun 10, 2015
1 parent 525dcb6 commit d17412a
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 1 deletion.
29 changes: 29 additions & 0 deletions src/declaration.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,22 @@ Type *TupleDeclaration::getType()
return tupletype;
}

Dsymbol *TupleDeclaration::toAlias2()
{
//printf("TupleDeclaration::toAlias2() '%s' objects = %s\n", toChars(), objects->toChars());

for (size_t i = 0; i < objects->dim; i++)
{
RootObject *o = (*objects)[i];
if (Dsymbol *s = isDsymbol(o))
{
s = s->toAlias2();
(*objects)[i] = s;
}
}
return this;
}

bool TupleDeclaration::needThis()
{
//printf("TupleDeclaration::needThis(%s)\n", toChars());
Expand Down Expand Up @@ -607,6 +623,19 @@ Dsymbol *AliasDeclaration::toAlias()
return s;
}

Dsymbol *AliasDeclaration::toAlias2()
{
if (inuse)
{
error("recursive alias declaration");
return this;
}
inuse = 1;
Dsymbol *s = aliassym ? aliassym->toAlias2() : this;
inuse = 0;
return s;
}

/****************************** OverDeclaration **************************/

OverDeclaration::OverDeclaration(Dsymbol *s, bool hasOverloads)
Expand Down
2 changes: 2 additions & 0 deletions src/declaration.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ class TupleDeclaration : public Declaration
Dsymbol *syntaxCopy(Dsymbol *);
const char *kind();
Type *getType();
Dsymbol *toAlias2();
bool needThis();

TupleDeclaration *isTupleDeclaration() { return this; }
Expand All @@ -204,6 +205,7 @@ class AliasDeclaration : public Declaration
const char *kind();
Type *getType();
Dsymbol *toAlias();
Dsymbol *toAlias2();

AliasDeclaration *isAliasDeclaration() { return this; }
void accept(Visitor *v) { v->visit(this); }
Expand Down
9 changes: 8 additions & 1 deletion src/dsymbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,12 +271,19 @@ const char *Dsymbol::kind()
* If this symbol is really an alias for another,
* return that other.
*/

Dsymbol *Dsymbol::toAlias()
{
return this;
}

/*********************************
* Resolve recursive tuple expansion in eponymous template.
*/
Dsymbol *Dsymbol::toAlias2()
{
return toAlias();
}

Dsymbol *Dsymbol::toParent()
{
return parent ? parent->pastMixin() : NULL;
Expand Down
1 change: 1 addition & 0 deletions src/dsymbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ class Dsymbol : public RootObject
virtual const char *toPrettyChars(bool QualifyTypes = false);
virtual const char *kind();
virtual Dsymbol *toAlias(); // resolve real symbol
virtual Dsymbol *toAlias2();
virtual int apply(Dsymbol_apply_ft_t fp, void *param);
virtual void addMember(Scope *sc, ScopeDsymbol *sds);
virtual void setScope(Scope *sc);
Expand Down
13 changes: 13 additions & 0 deletions src/template.c
Original file line number Diff line number Diff line change
Expand Up @@ -6285,6 +6285,19 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
}
}

if (aliasdecl)
{
/* Bugzilla 13816: AliasDeclaration tries to resolve forward reference
* twice (See inuse check in AliasDeclaration::toAlias()). It's
* necessary to resolve mutual references of instantiated symbols, but
* it will left a true recursive alias in tuple declaration - an
* AliasDeclaration A refers TupleDeclaration B, and B contains A
* in its elements. To correctly make it an error, we strictly need to
* resolve the alias of eponymous member.
*/
aliasdecl = aliasdecl->toAlias2();
}

Laftersemantic:
sc2->pop();

Expand Down
23 changes: 23 additions & 0 deletions test/fail_compilation/ice13816.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice13816.d(15): Error: alias ice13816.ItemProperty!().ItemProperty recursive alias declaration
fail_compilation/ice13816.d(20): Error: template instance ice13816.ItemProperty!() error instantiating
---
*/

alias TypeTuple(T...) = T;

template ItemProperty()
{
static if (true)
{
alias ItemProperty = TypeTuple!(ItemProperty!());
}
}
void main()
{
alias items = ItemProperty!();

enum num = items.length;
}

0 comments on commit d17412a

Please sign in to comment.