struct s1
{
        int a;
        int b;

        double c;
};

struct s2
{
        long long a;
        long long b;
};

union us
{
        struct s1 us1;
        struct s2 us2;
};

void foo1(struct s1 s)
{
        printf("Got %d %d %f\n", s.a, s.b, s.c);
}

void __attribute__((noinline, used, noclone)) foo(void)
{
        struct s1 s = {1, 2, 3.0};

        asm("");

        foo1(s);

        foo1(((union us *)&s)->us1);
}

Neither gcc 4.4 or 4.5 warn about the union cast, however 4.4 will mention a
strict-aliasing problem if foo1() is forced not to be inlined.  gcc 4.5 outputs
incorrect results.  4.4 outputs the correct 1,2,3 unless foo1() is forced to be
not inlined, in which case it also has incorrect output.

My understanding is that casting to the union type is okay because union us
contains struct s1 as a member.  We then access the union member that
corresponds to the original type. (No undefined behaviour.)  So it looks like
the lack of strict aliasing warning in 4.5 is correct.  However, the wrong code
generation that results is obviously then problematic.


-- 
           Summary: Union cast leads to wrong code generation. (Strict
                    aliasing not warned about?)
           Product: gcc
           Version: 4.5.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: svfuerst at gmail dot com
 GCC build triplet: x86_64-linux
  GCC host triplet: x86_64-linux
GCC target triplet: x86_64-linux


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44275

Reply via email to