This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Undefined behavior due to 6.5.16.1p3


On 03/11/2015 05:31 PM, Vincent Lefevre wrote:
I disagree that it is an extension. The standard does not say
that "one union member can be active at any time".

The interpretation under which this is allowed in confirmed by
Note 95 of 6.5.2.3p3.
Effective types disallow to access a union member other than the current one arbitrarily, so naively effective types contradict note 95 of 6.5.2.3p3.

I think the GCC interpretation makes sense. See the following excerpt from the "-fstrict-aliasing" description in the gcc man page:

Allow the compiler to assume the strictest aliasing rules applicable to the language being compiled.  For C (and C++), this activates optimizations based on the type of expressions.  In particular, an object of one type is assumed never to reside at the same address as an object of a different type, unless the types are almost the same.  For example, an "unsigned int" can alias an "int", but not a "void*" or a "double". A character type may alias any other type.

Pay special attention to code like this:

    union a_union {
      int i;
      double d;
    };

    int f() {
      union a_union t;
      t.d = 3.0;
      return t.i;
    }

The practice of reading from a different union member than the one most recently written to (called "type-punning") is common.  Even with -fstrict-aliasing, type-punning is allowed, provided the memory is accessed through the union type.  So, the code above works as expected.    However, this code might not:

    int f() {
      union a_union t;
      int* ip;
      t.d = 3.0;
      ip = &t.i;
      return *ip;
    }

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;
    }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]