<html>
    <head>
      <base href="https://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - Wrong optimization of type-punning with two pointers involved"
   href="https://llvm.org/bugs/show_bug.cgi?id=28241">28241</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Wrong optimization of type-punning with two pointers involved
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>unspecified
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>-New Bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>ch3root@openwall.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Source code:

----------------------------------------------------------------------
#include <stdio.h>

union u { int i; long l; };

static int f(union u *p, union u *q)
{
  p->i = 1;
  q->l = 0;
  return p->i;
}

static int g(union u *p, long *q)
{
  p->i = 1;
  *q = 0;
  return p->i;
}

int main()
{
  union u u;

  printf("%d %d\n", f(&u, &u), g(&u, &u.l));
}
----------------------------------------------------------------------

Results:

----------------------------------------------------------------------
$ clang -std=c11 -Weverything test.c && ./a.out
0 0

$ clang -std=c11 -Weverything -O3 test.c && ./a.out
1 1
----------------------------------------------------------------------

clang version: clang version 3.9.0 (trunk 271312)

For comparison:

----------------------------------------------------------------------
$ gcc -std=c11 -pedantic -Wall -Wextra -O3 test.c && ./a.out
0 0
----------------------------------------------------------------------

gcc version: gcc (GCC) 7.0.0 20160616 (experimental)


When compiled with `clang -O3` the testcase prints `1 1`. This is wrong, the
right result is `0 0`.

The functions `f` and `g` demonstate two variants of the problem. In both cases
only one union is used and the field `l` is written via the pointer `q` while
the field `i` is later read via the pointer `p`. What is written to `l` should
affect what is read via `i`.

Type-punning is described in C11, 6.5.2.3p3 and footnote 95. There are no
restrictions on how the previous value was written into the union so writing
via another pointer is valid. And the read in this testcase is directly via
union. The code should be fine according to C11.</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>