Spurious compiler warning ?

knommad spam_D at asylum.id.au
Fri Nov 4 01:16:40 PDT 2011



kenji hara wrote:

> 2011/11/3 knommad <spam_D at asylum.id.au>:
>> Hi,
>>
>> I'm a relative newcomer to D, and am enjoying the experience.
>>
>> I have a small testcase here that causes what seems to be a spurious
>> warning from the compiler (resulting code still works, however).
>>
>> Am I missing something??
>>
>> import std.stdio;
>> import std.traits;
>>
>> enum TestEnum
>> {
>> ONE = 1,
>> TWO = 2,
>> THREE = 3,
>> FOUR = 4
>> }
>>
>> void main()
>> {
>> // Generates warning - works as expected though
>> foreach( TestEnum member; EnumMembers!TestEnum )
>> {
>> if ( member == TestEnum.TWO )
>> continue;
>> writeln( "A: ", member );
>> }
>>
>> // No warning generated
>> foreach( TestEnum member; EnumMembers!TestEnum )
>> {
>> if ( member == TestEnum.TWO )
>> continue;
>> else
>> writeln( "B: ", member );
>> }
>>
>> // No warning generated
>> auto list = EnumMembers!TestEnum;
>> foreach( TestEnum member; list )
>> {
>> if ( member == TestEnum.TWO )
>> continue;
>> writeln( "C: ", member );
>> }
>>
>> }
>>
>> compiled with: dmd -wi -oftest test.d
>>
>> (dmd version 2.056)
>>
>> output is as expected:
>> A: ONE
>> A: THREE
>> A: FOUR
>> B: ONE
>> B: THREE
>> B: FOUR
>> C: ONE
>> C: THREE
>> C: FOUR
>>
>>
>> regards,
>> ted
>>
>> --
>> Money can't buy happiness. But it can buy marshmallows, which are kinda
>> the same thing.
>>
>>
> 
> EnumMember returns tuple, it is compile-time sequence.
> And foreach with tuple unrolls its body. Then, Loop A is unrolled like
> follows.
> 
> __foreachEntry0: {
>   if ( TestEnum.ONE == TestEnum.TWO )
>     goto __foreachEntry1;
>   writeln( "A: ", TestEnum.ONE );
> }
> __foreachEntry1: {
>   if ( TestEnum.TWO == TestEnum.TWO )
>     goto __foreachEntry2;
>   writeln( "A: ", TestEnum.TWO );  // LineX
> }
> __foreachEntry2: {
>   if ( TestEnum.THREE == TestEnum.TWO )
>     goto __foreachEntry3;
>   writeln( "A: ", TestEnum.THREE );
> }
> __foreachEntry3: {
>   if ( TestEnum.FOUR == TestEnum.TWO )
>     goto __foreachEntry4;
>   writeln( "A: ", TestEnum.FOUR );
> }
> __foreachEntry4:
>   ;
> 
> And, when member == TestEnum.TWO, the LineX is not reachable.
> 
> With loop B, unrolling is similar, but dmd does not warn the
> unreachable else block.
> Because dmd treats it as that is stated by programmers as "may become
> unreachable branch".
> (This is reasonable assumption, sometimes the condition of if
> statement folded to constant.)
> 
> With loop C, list is "tuple of local variable symbols", it is similar
> to follows.
> 
> auto __list0 = TestEnum.ONE;
> auto __list1 = TestEnum.TWO;
> auto __list2 = TestEnum.THREE;
> auto __list3 = TestEnum.FOUR;
> alias TypeTuple!(list0, list1, list2, list3) list;
> 
> list itself is compile time tuple, but its elements are evaluated at
> runtime. Loop C is unrolled like A and B, but the conditions are
> evaluated at runtime, then compiler does not warn the branches as
> unreachable.
> 
> Kenji Hara

Hi,
Thanks for the detailed and informative answer. 

I am puzzled, however, that there is an inconsistency. There were 3 examples 
in the test case, which I would have expected to yield the same compiler 
output - but it only generates a warning in the first example.

regards,
ted



-- 
If you're not failing every now and again, it's a sign you're not doing 
anything very innovative.
                                                                                   -- 
Woody Allen



More information about the Digitalmars-d mailing list