Why does this code break strict-aliasing rules?

Andrew Haley aph@redhat.com
Fri Nov 13 10:21:00 GMT 2009


Jonathan Lennox wrote:
> John S. Fine wrote:
> 
>> Jonathan Lennox wrote:
>>> Am I missing something, or is gcc mis-compiling correct code?
>>>
>> gcc is correct.
>>
>> You put a value into union derived_union* u and then read a value out
>> of ((struct base*)u)
>>
>> That is a violation of strict aliasing.
>>
>> Annoying as it is, the compiler is free to assume the value you put in
>> is unrelated to the value you read, so the value you put in u is never
>> used, so the optimizer can remove that operation.
> 
> But I didn't put a value into derived_union* u -- every time I
> initialize, read, or write the structure, I'm accessing it via a 'struct
> base' or 'struct base *'.  The function call just casts to a
> derived_union*, and then casts back.
> 
> I was under the impression it was valid to cast between a pointer to a
> structure element and a pointer to the containing structure, so long as
> the underlying memory really is the containing structure -- this is how
> you can implement something equivalent to casting between C++ base and
> derived classes, e.g.  Was I wrong?

That's not what you're doing here.  Of course, you can cast a structure
pointer to the type of its first element, and back.  But here you are
casting a pointer to a type that the object to which it points does not
have:

struct derived2
{
	struct base base;
	double c;
};

union derived_union
{
	struct derived1 d1;
	struct derived2 d2;
};

...
	struct derived2 d2 = { {5, 5}, 5.0 };
	int d2_a;

	set_base_a_field((union derived_union*)&d2, 0);

Here, the underlying memory really is *not* of type derived_union.

> Is there any convenient way to get this code to work reliably, without
> either restructuring my objects or having to use the big hammer of
> -fno-strict-aliasing?

Do not lie to the compiler, or it will bite you.

Andrew.



More information about the Gcc-help mailing list