www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 16521] New: Wrong code generation with switch + static foreach

https://issues.dlang.org/show_bug.cgi?id=16521

          Issue ID: 16521
           Summary: Wrong code generation with switch + static foreach
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Linux
            Status: NEW
          Severity: major
          Priority: P1
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: mathias.lang sociomantic.com

The following code:

```
void main ()
{
    sformat(0, uint.max);
}

void sformat (Args...) (int index, Args args)
{
JT: switch (index)
    {
        foreach (idx, unused; args)
        {
        case idx:
            assert(unused == args[idx], "Borken compiler");
            break JT;
        }

    default:
        assert(0);
    }
}
```

Triggers the assert.
Obviously `unused` and `args[idx]` should always be the same.
Here's the generated ASM:

```
000000000042237c <D main>:
  42237c:       55                      push   %rbp
  42237d:       48 8b ec                mov    %rsp,%rbp
  422380:       31 f6                   xor    %esi,%esi
  422382:       bf ff ff ff ff          mov    $0xffffffff,%edi
  422387:       e8 08 00 00 00          callq  422394
<test.sformat!(uint).sformat(int, uint)>
  42238c:       31 c0                   xor    %eax,%eax
  42238e:       5d                      pop    %rbp
  42238f:       c3                      retq   
  422390:       0f 1f 40 00             nopl   0x0(%rax)

0000000000422394 <test.sformat!(uint).sformat(int, uint)>:
  422394:       55                      push   %rbp
  422395:       48 8b ec                mov    %rsp,%rbp
  422398:       48 83 ec 20             sub    $0x20,%rsp
  42239c:       89 7d f8                mov    %edi,-0x8(%rbp)
  42239f:       85 f6                   test   %esi,%esi
  4223a1:       74 02                   je     4223a5
<test.sformat!(uint).sformat(int, uint)+0x11>
  4223a3:       eb 37                   jmp    4223dc
<test.sformat!(uint).sformat(int, uint)+0x48>
  4223a5:       8b 45 f0                mov    -0x10(%rbp),%eax ; <== Access to
unitialized variable `unused`
  4223a8:       3b 45 f8                cmp    -0x8(%rbp),%eax
  4223ab:       74 2d                   je     4223da
<test.sformat!(uint).sformat(int, uint)+0x46>
  4223ad:       41 b8 0d 00 00 00       mov    $0xd,%r8d
  4223b3:       b9 00 54 44 00          mov    $0x445400,%ecx
  4223b8:       b8 06 00 00 00          mov    $0x6,%eax
  4223bd:       48 89 c2                mov    %rax,%rdx
  4223c0:       48 89 55 e8             mov    %rdx,-0x18(%rbp)
  4223c4:       ba 07 54 44 00          mov    $0x445407,%edx
  4223c9:       bf 0f 00 00 00          mov    $0xf,%edi
  4223ce:       48 89 d6                mov    %rdx,%rsi
  4223d1:       48 8b 55 e8             mov    -0x18(%rbp),%rdx
  4223d5:       e8 ce 00 00 00          callq  4224a8 <_d_assert_msg>
  4223da:       eb 0a                   jmp    4223e6
<test.sformat!(uint).sformat(int, uint)+0x52>
  4223dc:       bf 12 00 00 00          mov    $0x12,%edi
  4223e1:       e8 2e 00 00 00          callq  422414 <test.__assert(int)>
  4223e6:       c9                      leaveq 
  4223e7:       c3                      retq   
  4223e8:       0f 1f 40 00             nopl   0x0(%rax)
```

Tested with v2.070.0 and v2.071.1
The latest master (cce7909) hints at the bug:
test.d(8): Deprecation: 'switch' skips declaration of variable
test.sformat!uint.sformat.unused at test.d(10)

--
Sep 21 2016