[llvm-bugs] [Bug 28241] New: Wrong optimization of type-punning with two pointers involved

via llvm-bugs llvm-bugs at lists.llvm.org
Tue Jun 21 08:24:18 PDT 2016


https://llvm.org/bugs/show_bug.cgi?id=28241

            Bug ID: 28241
           Summary: Wrong optimization of type-punning with two pointers
                    involved
           Product: clang
           Version: unspecified
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: -New Bugs
          Assignee: unassignedclangbugs at nondot.org
          Reporter: ch3root at openwall.com
                CC: llvm-bugs at lists.llvm.org
    Classification: Unclassified

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.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20160621/201efe8c/attachment-0001.html>


More information about the llvm-bugs mailing list