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