public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: GCC aliasing rules: more aggressive than C99?
       [not found] <loom.20100103T063932-636@post.gmane.org>
@ 2010-01-03 11:06 ` Andrew Haley
  2010-01-05  6:35   ` Patrick Horgan
  0 siblings, 1 reply; 2+ messages in thread
From: Andrew Haley @ 2010-01-03 11:06 UTC (permalink / raw)
  To: Joshua Haberman; +Cc: gcc-help

[ redir to gcc-help ]

On 01/03/2010 05:46 AM, Joshua Haberman wrote:
> The aliasing policies that GCC implements seem to be more strict than
> what is in the C99 standard.  I am wondering if this is true or whether
> I am mistaken (I am not an expert on the standard, so the latter is
> definitely possible).
> 
> The relevant text is:
> 
>   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,
>   [...]
>   * 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
> 
> To me this allows the following:
> 
>   int i;
>     *pu = (union u*)&i;
>   printf("%d\n", pu->x);

I do not believe that this is allowed.  A union of type

   union u { int x; }

is not compatible with the type int.  It might have greater alignment,
it might be larger, and so on.  We do know that a pointer to a union
can be converted to a pointer to each of its members and vice versa.
But, and this is crucial, *that does not mean they are compatible
types*.

> In this example, the object "i", which is of type "int", is having its
> stored value accessed by an lvalue expression of type "union u", which
> includes the type "int" among its members.
> 
> I have seen other articles that interpret the standard in this way.
> See section "Casting through a union (2)" from this article, which
> claims that casts of this sort are legal and that GCC's warnings
> against them are false positives:

>   http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html

It's wrong.

You need to look at the standard's own definition of what constitutes
a compatible type.

<< 1 Two types have compatible type if their types are the
same. Additional rules for determining whether two types are
compatible are described in 6.7.2 for type specifiers,

...

6.7.2.1

A pointer to a structure object, suitably converted, points to its
initial member (or if that member is a bit-field, then to the unit in
which it resides), and vice versa.>>

Rather than reading dubious web sites, you need to refer to the
standard itself when trying to understand C.  There have been several
attampts to summarize the standard, and as far as I'm aware they are
all unreliable.

So please don't believe me: believe the standard.

Andrew.

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: GCC aliasing rules: more aggressive than C99?
  2010-01-03 11:06 ` GCC aliasing rules: more aggressive than C99? Andrew Haley
@ 2010-01-05  6:35   ` Patrick Horgan
  0 siblings, 0 replies; 2+ messages in thread
From: Patrick Horgan @ 2010-01-05  6:35 UTC (permalink / raw)
  Cc: gcc-help

Andrew Haley wrote:
> On 01/03/2010 05:46 AM, Joshua Haberman wrote:
>   
>> ...elision by Patrick...
>> To me this allows the following:
>>
>>   int i;
>>     *pu = (union u*)&i;
>>   printf("%d\n", pu->x);
>>     
>
> I do not believe that this is allowed.  A union of type
>
>    union u { int x; }
>
> is not compatible with the type int.  It might have greater alignment,
> it might be larger, and so on.  
It couldn't have different alignment since the member has to have the 
same alignment it would usually have and padding at the beginning of a 
union is not allowed.  They are certainly layout-compatible types.   I'm 
not sure about larger, why would a compiler add padding to the end?  In 
the C++ spec it couldn't, since they don't have the clause about being 
able to add padding at the end.  Certainly in gcc the size is the same.  
The standard doesn't specify anything about this other than the size 
must be sufficient for the largest member, and that padding may be added 
at the end.  What do you mean by and so on?  Not trying to be 
argumentative or anything, but now I've gotten intrigued.  It's interesting!
> We do know that a pointer to a union
> can be converted to a pointer to each of its members and vice versa.
> But, and this is crucial, *that does not mean they are compatible
> types*.
>   
A pointer to union and a pointer to int are not required to have the 
same representation.   But what about printf("%d\n", (*((union 
u*)&i)).x);  That bypasses the issues about pointers entirely.  I know 
it's silly code, but it seems to fit the aliasing rules. gcc doesn't 
warn about it even with -Wstrict-aliasing=3 and -fstrict-aliasing, nor 
does g++ warn about an equivalent program using cout instead of printf.

Patrick





^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2010-01-05  6:35 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <loom.20100103T063932-636@post.gmane.org>
2010-01-03 11:06 ` GCC aliasing rules: more aggressive than C99? Andrew Haley
2010-01-05  6:35   ` Patrick Horgan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).