Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REG2.069-devel] Issue 15167 - conflicting error with repeated alias declaration #5169

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
230 changes: 108 additions & 122 deletions src/declaration.d
Expand Up @@ -566,9 +566,11 @@ public:
return;
}
inuse = 1;

storage_class |= sc.stc & STCdeprecated;
protection = sc.protection;
userAttribDecl = sc.userAttribDecl;

// Given:
// alias foo.bar.abc def;
// it is not knowable from the syntax whether this is an alias
Expand All @@ -577,11 +579,10 @@ public:
// If it is a type, then type is set and getType() will return that
// type. If it is a symbol, then aliassym is set and type is NULL -
// toAlias() will return aliasssym.

uint errors = global.errors;
Type savedtype = type;
Dsymbol s;
Type t;
Expression e;
Type oldtype = type;

// Ungag errors when not instantiated DeclDefs scope alias
auto ungag = Ungag(global.gag);
//printf("%s parent = %s, gag = %d, instantiated = %d\n", toChars(), parent, global.gag, isInstantiated());
Expand All @@ -590,12 +591,13 @@ public:
//printf("%s type = %s\n", toPrettyChars(), type->toChars());
global.gag = 0;
}
/* This section is needed because resolve() will:

/* This section is needed because Type.resolve() will:
* const x = 3;
* alias x y;
* try to alias y to 3.
* alias y = x;
* try to convert identifier x to 3.
*/
s = type.toDsymbol(sc);
Dsymbol s = type.toDsymbol(sc);
if (errors != global.errors)
{
s = null;
Expand All @@ -607,127 +609,110 @@ public:
s = null;
type = Type.terror;
}
if (s && ((s.getType() && type.equals(s.getType())) || s.isEnumMember()))
goto L2;
// it's a symbolic alias
type = type.addSTC(storage_class);
if (storage_class & (STCref | STCnothrow | STCnogc | STCpure | STCdisable))
if (!s || !((s.getType() && type.equals(s.getType())) || s.isEnumMember()))
{
// For 'ref' to be attached to function types, and picked
// up by Type::resolve(), it has to go into sc.
sc = sc.push();
sc.stc |= storage_class & (STCref | STCnothrow | STCnogc | STCpure | STCshared | STCdisable);
type.resolve(loc, sc, &e, &t, &s);
sc = sc.pop();
Type t;
Expression e;
Scope* sc2 = sc;
if (storage_class & (STCref | STCnothrow | STCnogc | STCpure | STCdisable))
{
// For 'ref' to be attached to function types, and picked
// up by Type.resolve(), it has to go into sc.
sc2 = sc.push();
sc2.stc |= storage_class & (STCref | STCnothrow | STCnogc | STCpure | STCshared | STCdisable);
}
type = type.addSTC(storage_class);
type.resolve(loc, sc2, &e, &t, &s);
if (sc2 != sc)
sc2.pop();

if (e) // Try to convert Expression to Dsymbol
{
s = getDsymbol(e);
if (!s)
{
if (e.op != TOKerror)
error("cannot alias an expression %s", e.toChars());
t = Type.terror;
}
}
type = t;
}
else
type.resolve(loc, sc, &e, &t, &s);
if (s)
if (s == this)
{
goto L2;
assert(global.errors);
type = Type.terror;
s = null;
}
else if (e)
if (!s) // it's a type alias
{
// Try to convert Expression to Dsymbol
s = getDsymbol(e);
if (s)
goto L2;
if (e.op != TOKerror)
error("cannot alias an expression %s", e.toChars());
t = e.type;
//printf("alias %s resolved to type %s\n", toChars(), type.toChars());
type = type.semantic(loc, sc);
aliassym = null;
}
else if (t)
else // it's a symbolic alias
{
type = t.semantic(loc, sc);
//printf("\talias resolved to type %s\n", type->toChars());
//printf("alias %s resolved to %s %s\n", toChars(), s.kind(), s.toChars());
type = null;
aliassym = s;
}
if (overnext)
ScopeDsymbol.multiplyDefined(Loc(), overnext, this);
inuse = 0;
if (global.gag && errors != global.errors)
type = savedtype;

semanticRun = PASSsemanticdone;
return;
L2:
//printf("alias is a symbol %s %s\n", s->kind(), s->toChars());
type = null;
VarDeclaration v = s.isVarDeclaration();
if (0 && v && v.linkage == LINKdefault)
{
error("forward reference of %s", v.toChars());
s = null;
{
type = oldtype;
aliassym = null;
}
else
inuse = 0;
semanticRun = PASSsemanticdone;

if (Dsymbol sx = overnext)
{
Dsymbol savedovernext = overnext;
Dsymbol sa = s.toAlias();
if (FuncDeclaration fd = sa.isFuncDeclaration())
{
if (overnext)
{
auto fa = new FuncAliasDeclaration(ident, fd);
if (!fa.overloadInsert(overnext))
ScopeDsymbol.multiplyDefined(Loc(), overnext, fd);
overnext = null;
s = fa;
s.parent = sc.parent;
}
}
else if (TemplateDeclaration td = sa.isTemplateDeclaration())
overnext = null;

if (type)
{
if (overnext)
{
auto od = new OverDeclaration(ident, td);
if (!od.overloadInsert(overnext))
ScopeDsymbol.multiplyDefined(Loc(), overnext, td);
overnext = null;
s = od;
s.parent = sc.parent;
}
if (!overloadInsert(sx))
ScopeDsymbol.multiplyDefined(Loc(), sx, this);
return;
}
else if (OverDeclaration od = sa.isOverDeclaration())

Dsymbol sa = aliassym.toAlias();
if (sa == sx.toAlias()) // it's identical alias
return;

if (auto fd = sa.isFuncDeclaration())
{
if (overnext)
{
auto od2 = new OverDeclaration(ident, od);
if (!od2.overloadInsert(overnext))
ScopeDsymbol.multiplyDefined(Loc(), overnext, od);
overnext = null;
s = od2;
s.parent = sc.parent;
}
aliassym = new FuncAliasDeclaration(ident, fd);
aliassym.parent = sc.parent;
if (!aliassym.overloadInsert(sx))
ScopeDsymbol.multiplyDefined(Loc(), sx, sa);
return;
}
else if (OverloadSet os = sa.isOverloadSet())
if (auto td = sa.isTemplateDeclaration())
{
if (overnext)
{
os = new OverloadSet(ident, os);
os.push(overnext);
overnext = null;
s = os;
s.parent = sc.parent;
}
aliassym = new OverDeclaration(ident, td);
aliassym.parent = sc.parent;
if (!aliassym.overloadInsert(sx))
ScopeDsymbol.multiplyDefined(Loc(), sx, sa);
return;
}
if (overnext)
ScopeDsymbol.multiplyDefined(Loc(), overnext, this);
if (s == this)
if (auto od = sa.isOverDeclaration())
{
assert(global.errors);
s = null;
aliassym = new OverDeclaration(ident, od);
aliassym.parent = sc.parent;
if (!aliassym.overloadInsert(sx))
ScopeDsymbol.multiplyDefined(Loc(), sx, sa);
return;
}
if (global.gag && errors != global.errors)
if (auto os = sa.isOverloadSet())
{
type = savedtype;
overnext = savedovernext;
s = null;
aliassym = new OverloadSet(ident, os);
aliassym.parent = sc.parent;
(cast(OverloadSet)aliassym).push(sx);
return;
}
ScopeDsymbol.multiplyDefined(Loc(), sx, this);
return;
}
//printf("setting aliassym %s to %s %s\n", toChars(), s->kind(), s->toChars());
aliassym = s;
inuse = 0;

semanticRun = PASSsemanticdone;
}

override bool overloadInsert(Dsymbol s)
Expand All @@ -741,12 +726,15 @@ public:
if (semanticRun >= PASSsemanticdone)
{
if (type)
return false;
return type.equals(s.toAlias().getType());

/* When s is added in member scope by static if, mixin("code") or others,
* aliassym is determined already. See the case in: test/compilable/test61.d
*/
Dsymbol sa = aliassym.toAlias();
if (sa == s.toAlias()) // it's identical alias
return true;

if (auto fd = sa.isFuncDeclaration())
{
auto fa = new FuncAliasDeclaration(ident, fd);
Expand Down Expand Up @@ -788,7 +776,7 @@ public:
override Dsymbol toAlias()
{
//printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s', inuse = %d)\n",
// loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym->kind() : "", inuse);
// loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym.kind() : "", inuse);
assert(this != aliassym);
//static int count; if (++count == 10) *(char*)0=0;
if (inuse == 1 && type && _scope)
Expand Down Expand Up @@ -829,9 +817,12 @@ public:
type = Type.terror;
return aliassym;
}
if (aliassym || type.deco)
if (aliassym)
{
// semantic is already done.

// Even if type.deco !is null, "alias T = const int;` needs semantic
// call to take the storage class `const` as type qualifier.
}
else if (_import && _import._scope)
{
Expand All @@ -841,7 +832,9 @@ public:
_import.semantic(null);
}
else if (_scope)
{
semantic(_scope);
}
inuse = 1;
Dsymbol s = aliassym ? aliassym.toAlias() : this;
inuse = 0;
Expand Down Expand Up @@ -938,19 +931,12 @@ public:
override bool overloadInsert(Dsymbol s)
{
//printf("OverDeclaration::overloadInsert('%s') aliassym = %p, overnext = %p\n", s->toChars(), aliassym, overnext);
if (overnext is null)
{
if (s == this)
{
return true;
}
overnext = s;
return true;
}
else
{
if (overnext)
return overnext.overloadInsert(s);
}
if (s == this)
return true;
overnext = s;
return true;
}

override Dsymbol toAlias()
Expand Down
4 changes: 2 additions & 2 deletions src/expression.d
Expand Up @@ -5308,8 +5308,8 @@ public:
//printf("\tparent = '%s'\n", sds2.parent.toChars());
sds2.semantic(sc);

if (auto ad = sds2.isAggregateDeclaration())
return (new TypeExp(loc, ad.type)).semantic(sc);
if (auto t = sds2.getType()) // (Aggregate|Enum)Declaration
return (new TypeExp(loc, t)).semantic(sc);

sds = sds2;
type = Type.tvoid;
Expand Down
12 changes: 7 additions & 5 deletions test/fail_compilation/diag8510.d
Expand Up @@ -2,16 +2,18 @@
TEST_OUTPUT:
---
fail_compilation/diag8510.d(10): Error: alias diag8510.a conflicts with alias diag8510.a at fail_compilation/diag8510.d(9)
fail_compilation/diag8510.d(15): Error: alias diag8510.S.a conflicts with alias diag8510.S.a at fail_compilation/diag8510.d(14)
fail_compilation/diag8510.d(18): Error: alias diag8510.S.a conflicts with alias diag8510.S.a at fail_compilation/diag8510.d(17)
---
*/

alias int a;
alias int a;
alias long a;

int g;
struct S {
alias g a;
int h;

struct S
{
alias g a;
alias h a;
}

24 changes: 24 additions & 0 deletions test/fail_compilation/fail15167.d
@@ -0,0 +1,24 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail15167.d(12): Error: alias fail15167.Ulong15167 conflicts with alias fail15167.Ulong15167 at fail_compilation/fail15167.d(11)
fail_compilation/fail15167.d(16): Error: alias fail15167.Array15167 conflicts with alias fail15167.Array15167 at fail_compilation/fail15167.d(15)
fail_compilation/fail15167.d(20): Error: alias fail15167.StructType15167 conflicts with alias fail15167.StructType15167 at fail_compilation/fail15167.d(19)
fail_compilation/fail15167.d(24): Error: alias fail15167.ClassType15167 conflicts with alias fail15167.ClassType15167 at fail_compilation/fail15167.d(23)
---
*/

alias Ulong15167 = ulong;
alias Ulong15167 = const ulong; // error

alias UlongAlias15167 = ulong;
alias Array15167 = UlongAlias15167[]*;
alias Array15167 = UlongAlias15167[]; // error

struct S15167 {}
alias StructType15167 = S15167;
alias StructType15167 = S15167[]; // error

class C15167 {}
alias ClassType15167 = C15167[1];
alias ClassType15167 = C15167; // error