Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions compiler/src/dmd/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,50 @@ private Dsymbol getDsymbolWithoutExpCtx(RootObject oarg)
return getDsymbol(oarg);
}

private const(Dsymbol) recursiveCompilesKey(TraitsExp e, Scope* sc)
{
if (!e.args || e.args.length != 1)
return null;

const(Dsymbol) resolveKey(RootObject o)
{
if (auto ex = isExpression(o))
{
if (const ve = ex.isVarExp())
return ve.var;

if (auto ie = ex.isIdentifierExp())
{
Dsymbol scopesym;
return sc.search(ie.loc, ie.ident, scopesym);
}

if (auto me = ex.isMixinExp())
{
if (!me.exps || me.exps.length != 1)
return null;

return resolveKey((*me.exps)[0]);
}
}

if (auto tm = isType(o))
{
if (auto tmixin = tm.isTypeMixin())
{
if (!tmixin.exps || tmixin.exps.length != 1)
return null;

return resolveKey((*tmixin.exps)[0]);
}
}

return getDsymbolWithoutExpCtx(o);
}

return resolveKey((*e.args)[0]);
}

/**
* Fill an array of target size_t values that indicate possible pointer words in memory
* if interpreted as the type given as argument.
Expand Down Expand Up @@ -1877,6 +1921,24 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
/* Determine if all the objects - types, expressions, or symbols -
* compile without error
*/
__gshared const(Dsymbol)[] compilesStack;
bool popCompilesStack;
if (const key = recursiveCompilesKey(e, sc))
{
foreach (prev; compilesStack)
{
if (prev is key)
{
error(e.loc, "recursive `__traits(compiles)` expression");
return False();
}
}
compilesStack ~= key;
popCompilesStack = true;
}
scope (exit) if (popCompilesStack)
compilesStack = compilesStack[0 .. $ - 1];

if (!dim)
return False();

Expand Down
6 changes: 6 additions & 0 deletions compiler/test/compilable/ice19465.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
enum string s = "__traits(compiles, mixin(s))";

static if (__traits(compiles, mixin(s)))
{
enum b = 2;
}
Loading