Spurious compiler warning ?

kenji hara k.hara.pg at gmail.com
Thu Nov 3 01:29:14 PDT 2011


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


More information about the Digitalmars-d mailing list