This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Undefined behavior due to 6.5.16.1p3
- From: Martin Sebor <msebor at redhat dot com>
- To: gcc at gcc dot gnu dot org
- Date: Thu, 12 Mar 2015 13:55:50 -0600
- Subject: Re: Undefined behavior due to 6.5.16.1p3
- Authentication-results: sourceware.org; auth=none
- References: <54FDF3CE dot 6030507 at robbertkrebbers dot nl> <54FF195B dot 5060604 at redhat dot com> <54FF1F7C dot 5050501 at robbertkrebbers dot nl> <54FF2182 dot 1090800 at robbertkrebbers dot nl> <alpine dot DEB dot 2 dot 10 dot 1503102153590 dot 10726 at digraph dot polyomino dot org dot uk> <550042BD dot 8000608 at robbertkrebbers dot nl> <20150311160815 dot GA2967 at ypig dot lip dot ens-lyon dot fr> <20150311161155 dot GM1746 at tucnak dot redhat dot com> <20150311163101 dot GA4384 at ypig dot lip dot ens-lyon dot fr> <5500CD9B dot 2070207 at robbertkrebbers dot nl> <20150312091055 dot GB28490 at ypig dot lip dot ens-lyon dot fr>
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