diff --git a/compiler/src/dmd/traits.d b/compiler/src/dmd/traits.d index 21ec3ab0e1..fbb77b0ffd 100644 --- a/compiler/src/dmd/traits.d +++ b/compiler/src/dmd/traits.d @@ -947,15 +947,24 @@ Expression semanticTraits(TraitsExp e, Scope* sc) */ Dsymbol sym = getDsymbol(o); + + if (sym && e.ident == Id.hasMember) + { + if (auto sm = sym.search(e.loc, id)) + return True(); + + // https://issues.dlang.org/show_bug.cgi?id=23951 + if (auto decl = sym.isDeclaration()) + { + ex = typeDotIdExp(e.loc, decl.type, id); + goto doSemantic; + } + } + if (auto t = isType(o)) ex = typeDotIdExp(e.loc, t, id); else if (sym) { - if (e.ident == Id.hasMember) - { - if (auto sm = sym.search(e.loc, id)) - return True(); - } ex = new DsymbolExp(e.loc, sym); ex = new DotIdExp(e.loc, ex, id); } @@ -966,7 +975,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc) e.error("invalid first argument"); return ErrorExp.get(); } - + doSemantic: // ignore symbol visibility and disable access checks for these traits Scope* scx = sc.push(); scx.flags |= SCOPE.ignoresymbolvisibility | SCOPE.noaccesscheck; diff --git a/compiler/test/compilable/test23951.d b/compiler/test/compilable/test23951.d new file mode 100644 index 0000000000..e09a3d7b5d --- /dev/null +++ b/compiler/test/compilable/test23951.d @@ -0,0 +1,10 @@ +// https://issues.dlang.org/show_bug.cgi?id=23951 + +struct S { int x; } +struct T { S a; alias a this; } +struct U { T t; } +static assert(__traits(hasMember, T, "x")); +static assert(__traits(hasMember, T.init, "x")); +static assert(__traits(hasMember, U.init.t, "x")); +static assert(__traits(hasMember, U.t, "a")); +static assert(__traits(hasMember, U.t, "x")); diff --git a/compiler/test/fail_compilation/test23279.d b/compiler/test/fail_compilation/test23279.d new file mode 100644 index 0000000000..43f2d44a07 --- /dev/null +++ b/compiler/test/fail_compilation/test23279.d @@ -0,0 +1,14 @@ +// https://issues.dlang.org/show_bug.cgi?id=23279 + +/* +TEST_OUTPUT: +--- +fail_compilation/test23279.d(13): Error: undefined identifier `Sth` +--- +*/ + +class Tester +{ + enum a = __traits(hasMember, Tester, "setIt"); + void setIt(Sth sth){} +}