Skip to content

Commit

Permalink
Move issue 7815 case to fail_compilation, because it was invalid
Browse files Browse the repository at this point in the history
It was wrongly accepted by the bug in `StaticIfCondition::include()`.

Bug explanation copied from fail_compilation/fail7815.d:
----
When the Move struct member is analyzed:
1. mixin Helpers!() is instantiated.
2. In Helpers!(), static if and its condition is(Flags!Move)) evaluated.
3. In Flags!Move, string mixin evaluates and CTFE lambda.
4. __traits(derivedMembers, Move) tries to see the member of Move.
   4a. mixin Helpers!() member is analyzed.
   4b. `static if (is(Flags!Move))` in Helpers!() is evaluated
   4c. The Flags!Move instantiation is already in progress, so it cannot be resolved.
   4d. `static if` fails because Flags!Move cannot be determined as a type.
5. __traits(derivedMembers, Move) returns a 1-length tuple("a").
6. The lambda in Flags!Move returns a string "struct Flags {...}", then
   Flags!Move is instantiated to a new struct Flags.
7. Finally Move struct does not have flags member, then the `enum a7815`
   definition will fail in its initializer.
  • Loading branch information
9rnsr committed May 13, 2015
1 parent 779349b commit d0c854a
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 35 deletions.
5 changes: 5 additions & 0 deletions src/cond.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,11 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *sds)
sc->pop();
--nest;

// Prevent repeated condition evaluation.
// See: fail_compilation/fail7815.d
if (inc != 0)
return (inc == 1);

if (!e->type->isBoolean())
{
if (e->type->toBasetype() != Type::terror)
Expand Down
65 changes: 65 additions & 0 deletions test/fail_compilation/fail7815.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// REQUIRED_ARGS: -o-
/*
TEST_OUTPUT:
---
X: tuple("x")
fail_compilation/fail7815.d(47): Error: no property 'flags' for type 'Move'
---
*/

mixin template Helpers()
{
static if (is(Flags!Move))
{
Flags!Move flags;
}
else
{
pragma(msg, "X: ", __traits(derivedMembers, Flags!Move));
}
}

template Flags(T)
{
mixin({
int defs = 1;
foreach (name; __traits(derivedMembers, Move))
{
defs++;
}
if (defs)
{
return "struct Flags { bool x; }";
}
else
{
return "";
}
}());
}

struct Move
{
int a;
mixin Helpers!();
}

enum a7815 = Move.init.flags;

/+
This is an invalid case.
When the Move struct member is analyzed:
1. mixin Helpers!() is instantiated.
2. In Helpers!(), static if and its condition is(Flags!Move)) evaluated.
3. In Flags!Move, string mixin evaluates and CTFE lambda.
4. __traits(derivedMembers, Move) tries to see the member of Move.
4a. mixin Helpers!() member is analyzed.
4b. `static if (is(Flags!Move))` in Helpers!() is evaluated
4c. The Flags!Move instantiation is already in progress, so it cannot be resolved.
4d. `static if` fails because Flags!Move cannot be determined as a type.
5. __traits(derivedMembers, Move) returns a 1-length tuple("a").
6. The lambda in Flags!Move returns a string "struct Flags {...}", then
Flags!Move is instantiated to a new struct Flags.
7. Finally Move struct does not have flags member, then the `enum a7815`
definition will fail in its initializer.
+/
35 changes: 0 additions & 35 deletions test/runnable/xtest46.d
Original file line number Diff line number Diff line change
Expand Up @@ -5899,41 +5899,6 @@ void test7735()
a7735([]);
}

/***************************************************/
// 7815

mixin template Helpers() {

static if (is(Flags!Move)) {
Flags!Move flags;
} else {
// DMD will happily instantiate the allegedly
// non-existent Flags!This here. (!)
pragma(msg, __traits(derivedMembers, Flags!Move));
}
}

template Flags(T) {
mixin({
int defs = 1;
foreach (name; __traits(derivedMembers, Move)) {
defs++;
}
if (defs) {
return "struct Flags { bool a; }";
} else {
return "";
}
}());
}

struct Move {
int a;
mixin Helpers!();
}

enum a7815 = Move.init.flags;

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

struct A7823 {
Expand Down

0 comments on commit d0c854a

Please sign in to comment.