Showing with 88 additions and 17 deletions.
  1. +41 −15 src/declaration.c
  2. +2 −1 src/declaration.h
  3. +8 −1 src/dsymbol.c
  4. +1 −0 src/dsymbol.h
  5. +13 −0 src/template.c
  6. +23 −0 test/fail_compilation/ice13816.d
56 changes: 41 additions & 15 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 All @@ -280,7 +296,6 @@ bool TupleDeclaration::needThis()
return false;
}


/********************************* AliasDeclaration ****************************/

AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Type *type)
Expand All @@ -293,7 +308,6 @@ AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Type *type)
this->aliassym = NULL;
this->import = NULL;
this->overnext = NULL;
this->inSemantic = 0;
assert(type);
}

Expand All @@ -307,7 +321,6 @@ AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Dsymbol *s)
this->aliassym = s;
this->import = NULL;
this->overnext = NULL;
this->inSemantic = 0;
assert(s);
}

Expand All @@ -331,7 +344,7 @@ void AliasDeclaration::semantic(Scope *sc)
aliassym->semantic(sc);
return;
}
this->inSemantic = 1;
inuse = 1;

storage_class |= sc->stc & STCdeprecated;
protection = sc->protection;
Expand Down Expand Up @@ -411,7 +424,7 @@ void AliasDeclaration::semantic(Scope *sc)
}
if (overnext)
ScopeDsymbol::multiplyDefined(Loc(), overnext, this);
this->inSemantic = 0;
inuse = 0;

if (global.gag && errors != global.errors)
type = savedtype;
Expand Down Expand Up @@ -492,7 +505,7 @@ void AliasDeclaration::semantic(Scope *sc)
}
//printf("setting aliassym %s to %s %s\n", toChars(), s->kind(), s->toChars());
aliassym = s;
this->inSemantic = 0;
inuse = 0;
}

bool AliasDeclaration::overloadInsert(Dsymbol *s)
Expand Down Expand Up @@ -548,13 +561,13 @@ Type *AliasDeclaration::getType()

Dsymbol *AliasDeclaration::toAlias()
{
//printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s', inSemantic = %d)\n",
// loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym->kind() : "", inSemantic);
//printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s', inuse = %d)\n",
// loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym->kind() : "", inuse);
assert(this != aliassym);
//static int count; if (++count == 10) *(char*)0=0;
if (inSemantic == 1 && type && scope)
if (inuse == 1 && type && scope)
{
inSemantic = 2;
inuse = 2;
unsigned olderrors = global.errors;
Dsymbol *s = type->toDsymbol(scope);
//printf("[%s] type = %s, s = %p, this = %p\n", loc.toChars(), type->toChars(), s, this);
Expand All @@ -566,7 +579,7 @@ Dsymbol *AliasDeclaration::toAlias()
if (global.errors != olderrors)
goto Lerr;
aliassym = s;
inSemantic = 0;
inuse = 0;
}
else
{
Expand All @@ -576,10 +589,10 @@ Dsymbol *AliasDeclaration::toAlias()
if (global.errors != olderrors)
goto Lerr;
//printf("t = %s\n", t->toChars());
inSemantic = 0;
inuse = 0;
}
}
if (inSemantic)
if (inuse)
{
error("recursive alias declaration");

Expand All @@ -604,9 +617,22 @@ Dsymbol *AliasDeclaration::toAlias()
}
else if (scope)
semantic(scope);
inSemantic = 1;
inuse = 1;
Dsymbol *s = aliassym ? aliassym->toAlias() : this;
inSemantic = 0;
inuse = 0;
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;
}

Expand Down
3 changes: 2 additions & 1 deletion 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 @@ -195,7 +196,6 @@ class AliasDeclaration : public Declaration
Dsymbol *aliassym;
Dsymbol *overnext; // next in overload list
Dsymbol *import; // !=NULL if unresolved internal alias for selective import
int inSemantic;

AliasDeclaration(Loc loc, Identifier *ident, Type *type);
AliasDeclaration(Loc loc, Identifier *ident, Dsymbol *s);
Expand All @@ -205,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;
}