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.

Reply via email to