enum Foo : ulong //remove the :ulong and the internal error is gone
{
baa = 0B_001,
}
void bitfieldToStrings(T)(T _val)
{
string[] res;
foreach(mem; __traits(allMembers, T))
{
if( (_val & 1) == 1 )
{
res ~= "foo";
}
}
}
void main(string[] argv)
{
Foo bar;
bitfieldToStrings(bar);
}
Just happens when compiled with : dmd main.d -O
Tested with dmd 2.051 and 2.052
Comment #1 by clugdbug — 2011-03-01T07:38:38Z
Reduced test case:
void foo5672() {}
void bug5672(long v)
{
if( (v & 1) == 1 )
{
foo5672();
}
}
Prehistoric bug. Same ICE on DMD 0.140.
Comment #2 by clugdbug — 2011-03-01T17:06:17Z
Completely reduced test case:
----
bool bug5672(long v)
{
return (v & 1) == 1;
}
----
It's happening because in cgelem.c, elcmp(), around line 3350,
bool = (long & 1) == 1;
gets optimized into
bool = long & 1;
Setting the new size of the long expression isn't done correctly.
Comment #3 by clugdbug — 2011-03-02T00:13:01Z
Actually I think the problem is in ellngsht. The (long&1)==1 optimisation does
cast(bool)cast(short)cast(int)((e & 1)==1) and assumes that it'll get optimised to (cast(bool)e) & 1. But it doesn't.
The optimiser does a very poor job in a case like this:
bool foo(long v)
{
return v&1;
}
It generates this:
mov EAX,4[ESP]
mov EDX,8[ESP]
and EAX,1
xor EDX,EDX
or EDX,EAX
jne L17
xor EAX,EAX
jmp short L1C
L17: mov EAX,1
L1C: ret 8
That's terrible code! It should just do:
mov EAX, 4[ESP]
and EAX, 1
ret 8