Skip to content

Commit

Permalink
Fix Issue 21122 - __traits(getAttributes) wrong scope on enums
Browse files Browse the repository at this point in the history
  • Loading branch information
BorisCarvajal authored and dlang-bot committed Aug 7, 2020
1 parent 2f8760e commit 7d40b94
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/dmd/attrib.d
Original file line number Diff line number Diff line change
Expand Up @@ -1369,7 +1369,7 @@ extern (C++) final class UserAttributeDeclaration : AttribDeclaration
arrayExpressionSemantic(atts, sc);
}
auto exps = new Expressions();
if (userAttribDecl)
if (userAttribDecl && userAttribDecl !is this)
exps.push(new TupleExp(Loc.initial, userAttribDecl.getAttributes()));
if (atts && atts.dim)
exps.push(new TupleExp(Loc.initial, atts));
Expand Down
4 changes: 4 additions & 0 deletions src/dmd/dsymbolsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -2495,6 +2495,10 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
em.userAttribDecl = em.ed.userAttribDecl;
}

// Eval UDA in this same scope. Issues 19344, 20835, 21122
if (em.userAttribDecl)
em.userAttribDecl.setScope(sc);

// The first enum member is special
bool first = (em == (*em.ed.members)[0]);

Expand Down
14 changes: 9 additions & 5 deletions src/dmd/parse.d
Original file line number Diff line number Diff line change
Expand Up @@ -3222,20 +3222,24 @@ final class Parser(AST) : Lexer
error("if type, there must be an initializer");
}

AST.UserAttributeDeclaration uad;
if (udas)
uad = new AST.UserAttributeDeclaration(udas, null);

AST.DeprecatedDeclaration dd;
if (deprecationMessage)
{
dd = new AST.DeprecatedDeclaration(deprecationMessage, null);
stc |= STC.deprecated_;
}

auto em = new AST.EnumMember(loc, ident, value, type, stc, uad, dd);
auto em = new AST.EnumMember(loc, ident, value, type, stc, null, dd);
e.members.push(em);

if (udas)
{
auto s = new AST.Dsymbols();
s.push(em);
auto uad = new AST.UserAttributeDeclaration(udas, s);
em.userAttribDecl = uad;
}

if (token.value == TOK.rightCurly)
{
}
Expand Down
9 changes: 1 addition & 8 deletions src/dmd/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -1184,7 +1184,6 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
auto po = isParameter(o);
auto s = getDsymbolWithoutExpCtx(o);
UserAttributeDeclaration udad = null;
Scope* sc2 = sc;
if (po)
{
udad = po.userAttribDecl;
Expand All @@ -1197,12 +1196,6 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
}
//printf("getAttributes %s, attrs = %p, scope = %p\n", s.toChars(), s.userAttribDecl, s.scope);
udad = s.userAttribDecl;

// Use the symbol scope when possible
if (s._scope)
sc2 = s._scope;
else if (auto m = s.getModule()) // needed for some top level symbols
sc2 = m._scope;
}
else
{
Expand All @@ -1221,7 +1214,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)

auto exps = udad ? udad.getAttributes() : new Expressions();
auto tup = new TupleExp(e.loc, exps);
return tup.expressionSemantic(sc2);
return tup.expressionSemantic(sc);
}
if (e.ident == Id.getFunctionAttributes)
{
Expand Down
12 changes: 12 additions & 0 deletions test/compilable/test20835.d
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,15 @@ enum Enum {

static assert(getUDAs!(Enum.first, Struct)[0] == Struct(42));
static assert(__traits(getAttributes, Enum.first)[0] == Struct(42));

// https://issues.dlang.org/show_bug.cgi?id=21122

void test21122()
{
enum A;
enum E { @A a }

static assert(is(getAllUDAs!(E.a)[0] == A));
}

alias getAllUDAs(A...) = __traits(getAttributes, A);

0 comments on commit 7d40b94

Please sign in to comment.