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/12/2015 03:10 AM, Vincent Lefevre wrote:
On 2015-03-12 00:19:55 +0100, Robbert Krebbers wrote:
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.

Well, this depends on the interpretation of effective types in the
case of a union. For instance, when writing

   union { char a[16]; int b; } u;
   u.b = 1;

you don't set the member only (an int), but the whole union object is
affected, even bytes that are not parts of the int. So, one may see
the effective type as being the union type.

The purpose of the term /effective type/ is to make it possible
to talk about types of allocated objects (those with no declared
type). In the example above, u.b is declared to have the type
int and assigning to it doesn't change the type of other members
of the union. But because u.a has a character type the value of
u.b can be accessed via u.a (or any other lvalue of that type).


The item "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" about aliasing
is also very unclear.

The purpose of this bullet is to allow access to subobjects
of otherwise incompatible aggregate types that contain members
of compatible types. For example:

  // Types A and B are incompatible.
  struct A { int a; };
  struct B { unsigned b; double d; };

  struct A *x = malloc (sizeof *x);
  struct B *y = malloc (sizeof *y);

  // Allocated objects *x and *y have no type, declared
  // or effective (yet).

  *x = (struct A){ 0 };
  *y = (struct B){ 0, 0 };

  // *x has effective type A and *y has effective type B.

  // Access initial element of *y by an lvalue of an aggregate
  // type whose first member's effective type is compatible with
  // the effective type of the first member of *x.

   *x = *(struct A*)y;

   // The effective type of *x is still A.

Martin


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