Skip to content

Commit

Permalink
Fix Issue 15094 - __traits(getMember) fails when the source is a stru…
Browse files Browse the repository at this point in the history
…ct/class field
  • Loading branch information
JinShil committed Nov 20, 2017
1 parent f6c2fbf commit 89c9003
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 18 deletions.
6 changes: 3 additions & 3 deletions src/ddmd/dtemplate.d
Expand Up @@ -6559,7 +6559,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
{
//printf("type %s\n", ta.toChars());
// It might really be an Expression or an Alias
ta.resolve(loc, sc, &ea, &ta, &sa);
ta.resolve(loc, sc, &ea, &ta, &sa, (flags & 1) != 0);
if (ea)
goto Lexpr;
if (sa)
Expand Down Expand Up @@ -6691,7 +6691,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
//goto Ldsym;
}
}
if (ea.op == TOKdotvar)
if (ea.op == TOKdotvar && !(flags & 1))
{
// translate expression to dsymbol.
sa = (cast(DotVarExp)ea).var;
Expand All @@ -6702,7 +6702,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
sa = (cast(TemplateExp)ea).td;
goto Ldsym;
}
if (ea.op == TOKdottd)
if (ea.op == TOKdottd && !(flags & 1))
{
// translate expression to dsymbol.
sa = (cast(DotTemplateExp)ea).td;
Expand Down
55 changes: 40 additions & 15 deletions src/ddmd/traits.d
Expand Up @@ -40,6 +40,7 @@ import ddmd.semantic;
import ddmd.tokens;
import ddmd.typesem;
import ddmd.visitor;
import ddmd.root.rootobject;

enum LOGSEMANTIC = false;

Expand All @@ -58,6 +59,31 @@ struct PushAttributes
}
}

/**************************************
* Convert `Expression` or `Type` to corresponding `Dsymbol`,
* additionally strip off expression contexts.
*
* Some symbol related `__traits` ignore arguments expression contexts.
* For example:
* struct S { void f() {} }
* S s;
* pragma(msg, __traits(isNested, s.f));
* // s.f is DotVarExp, but __traits(isNested) needs a FuncDeclaration.
*
* This is used for that common `__traits` behavior.
*/
private Dsymbol getDsymbolWithoutExpCtx(RootObject oarg)
{
if (auto e = isExpression(oarg))
{
if (e.op == TOKdotvar)
return (cast(DotVarExp)e).var;
if (e.op == TOKdottd)
return (cast(DotTemplateExp)e).td;
}
return getDsymbol(oarg);
}

extern (C++) __gshared StringTable traitsStringTable;

shared static this()
Expand Down Expand Up @@ -422,7 +448,7 @@ extern (C++) Expression semanticTraits(TraitsExp e, Scope* sc)

static if (is(T : Dsymbol))
{
auto s = getDsymbol(o);
auto s = getDsymbolWithoutExpCtx(o);
if (!s)
return False();
}
Expand Down Expand Up @@ -530,7 +556,7 @@ extern (C++) Expression semanticTraits(TraitsExp e, Scope* sc)
return dimError(1);

auto o = (*e.args)[0];
auto s = getDsymbol(o);
auto s = getDsymbolWithoutExpCtx(o);
if (!s)
{
}
Expand Down Expand Up @@ -630,7 +656,7 @@ extern (C++) Expression semanticTraits(TraitsExp e, Scope* sc)
}
else
{
Dsymbol s = getDsymbol(o);
Dsymbol s = getDsymbolWithoutExpCtx(o);
if (!s || !s.ident)
{
e.error("argument `%s` has no identifier", o.toChars());
Expand All @@ -655,7 +681,7 @@ extern (C++) Expression semanticTraits(TraitsExp e, Scope* sc)
return new ErrorExp();

auto o = (*e.args)[0];
auto s = getDsymbol(o);
auto s = getDsymbolWithoutExpCtx(o);
if (!s)
{
if (!isError(o))
Expand All @@ -676,7 +702,7 @@ extern (C++) Expression semanticTraits(TraitsExp e, Scope* sc)
return dimError(1);

auto o = (*e.args)[0];
auto s = getDsymbol(o);
auto s = getDsymbolWithoutExpCtx(o);
if (s)
{
if (auto fd = s.isFuncDeclaration()) // https://issues.dlang.org/show_bug.cgi?id=8943
Expand Down Expand Up @@ -747,6 +773,11 @@ extern (C++) Expression semanticTraits(TraitsExp e, Scope* sc)
Dsymbol sym = getDsymbol(o);
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);
}
Expand All @@ -767,12 +798,6 @@ extern (C++) Expression semanticTraits(TraitsExp e, Scope* sc)

if (e.ident == Id.hasMember)
{
if (sym)
{
if (auto sm = sym.search(e.loc, id))
return True();
}

/* Take any errors as meaning it wasn't found
*/
ex = ex.trySemantic(scx);
Expand Down Expand Up @@ -895,7 +920,7 @@ extern (C++) Expression semanticTraits(TraitsExp e, Scope* sc)
return dimError(1);

auto o = (*e.args)[0];
auto s = getDsymbol(o);
auto s = getDsymbolWithoutExpCtx(o);
if (!s)
{
version (none)
Expand Down Expand Up @@ -928,7 +953,7 @@ extern (C++) Expression semanticTraits(TraitsExp e, Scope* sc)
return dimError(1);

auto o = (*e.args)[0];
auto s = getDsymbol(o);
auto s = getDsymbolWithoutExpCtx(o);
auto t = isType(o);
TypeFunction tf = null;
if (s)
Expand Down Expand Up @@ -1414,7 +1439,7 @@ extern (C++) Expression semanticTraits(TraitsExp e, Scope* sc)
return dimError(1);

auto o = (*e.args)[0];
auto s = getDsymbol(o);
auto s = getDsymbolWithoutExpCtx(o);
if (!s)
{
e.error("argument `%s` to __traits(getUnitTests) must be a module or aggregate",
Expand Down Expand Up @@ -1475,7 +1500,7 @@ extern (C++) Expression semanticTraits(TraitsExp e, Scope* sc)
return dimError(1);

auto o = (*e.args)[0];
auto s = getDsymbol(o);
auto s = getDsymbolWithoutExpCtx(o);

auto fd = s ? s.isFuncDeclaration() : null;
if (!fd)
Expand Down
14 changes: 14 additions & 0 deletions test/runnable/traits.d
Expand Up @@ -1525,6 +1525,19 @@ void async(ARGS...)(ARGS)

alias test17495 = async!(int, int);

/********************************************************/
// 15094

void test15094()
{
static struct Foo { int i; }
static struct Bar { Foo foo; }

Bar bar;
auto n = __traits(getMember, bar.foo, "i");
assert(n == bar.foo.i);
}

/********************************************************/

int main()
Expand Down Expand Up @@ -1566,6 +1579,7 @@ int main()
test_getFunctionAttributes();
test_isOverrideFunction();
test12237();
test15094();

writeln("Success");
return 0;
Expand Down

0 comments on commit 89c9003

Please sign in to comment.