https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90167
Bug ID: 90167 Summary: invalid example in GCC documentation wrt. effective type rules Product: gcc Version: 8.3.0 Status: UNCONFIRMED Keywords: documentation Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: lersek at redhat dot com Target Milestone: --- The gcc manual says the following under "-fstrict-aliasing" <https://gcc.gnu.org/onlinedocs/gcc-8.3.0/gcc/Optimize-Options.html>: > union a_union { > int i; > double d; > }; > > [...] > > Similarly, access by taking the address, casting the resulting pointer > and dereferencing the result has undefined behavior, even if the cast > uses a union type, e.g.: > > int f() { > double d = 3.0; > return ((union a_union *) &d)->i; > } I think this particular statement does not match the C99 standard. The C99 standard says, under 6.5p7: > An object shall have its stored value accessed only by an lvalue > expression that has one of the following types: > - a type compatible with the effective type of the object, > - a qualified version of a type compatible with the effective type of > the object, > - a type that is the signed or unsigned type corresponding to the > effective type of the object, > - a type that is the signed or unsigned type corresponding to a > qualified version of the effective type of the object, > - an aggregate or union type that includes one of the aforementioned > types among its members (including, recursively, a member of a > subaggregate or contained union), or > - a character type. The object whose stored value we're accessing is the local variable "d". The effective type of the local variable "d" is "double". (Because it has a declared type, and so the declared type is the effective type.) The expression (*(union a_union *)&d) is an lvalue expression. The expression (*(union a_union *)&d) has type "union a_union", which is a union type that includes "double" among its members (6.5p7 bullet 5). The "double" type of the union member in question is compatible with the "double" type of the object whose stored value we're accessing (6.5p7 bullet 1). That's because both "double" types are identical. Finally, expression (((union a_union *)&d)->i) is equivalent to ((*(union a_union *)&d).i). Therefore the example given by the gcc documentation is valid C, in my opinion.