Re: ANSI alias rules checker in GCC, other optimizing compilers

"Arthur J. O'Dwyer" <ajonospam@andrew.cmu.edu>
18 Jan 2007 01:45:15 -0500

          From comp.compilers

Related articles
ANSI alias rules checker in GCC, other optimizing compilers andreybokhanko@gmail.com (2007-01-16)
Re: ANSI alias rules checker in GCC, other optimizing compilers ian@airs.com (Ian Lance Taylor) (2007-01-17)
Re: ANSI alias rules checker in GCC, other optimizing compilers andreybokhanko@gmail.com (Andrey Bokhanko) (2007-01-17)
Re: ANSI alias rules checker in GCC, other optimizing compilers andreybokhanko@gmail.com (Andrey Bokhanko) (2007-01-17)
Re: ANSI alias rules checker in GCC, other optimizing compilers ian@airs.com (Ian Lance Taylor) (2007-01-17)
Re: ANSI alias rules checker in GCC, other optimizing compilers silvius.rus@gmail.com (Silvius Rus) (2007-01-17)
Re: ANSI alias rules checker in GCC, other optimizing compilers ajonospam@andrew.cmu.edu (Arthur J. O'Dwyer) (2007-01-18)
Re: ANSI alias rules checker in GCC, other optimizing compilers andreybokhanko@gmail.com (2007-01-20)
| List of all articles for this month |
From: "Arthur J. O'Dwyer" <ajonospam@andrew.cmu.edu>
Newsgroups: comp.compilers
Date: 18 Jan 2007 01:45:15 -0500
Organization: Carnegie Mellon, Pittsburgh, PA
References: 07-01-047 07-01-054
Keywords: GCC, analysis
Posted-Date: 18 Jan 2007 01:45:15 EST

On Wed, 17 Jan 2007, Ian Lance Taylor wrote:
> "Andrey Bokhanko" <andreybokhanko@gmail.com> writes:
>> Also, can you give me examples of cases when GCC generates false
>> warnings and when it doesn't catch "proper" ANSI rules violations?
>
> gcc currently generates a false warning for:
>
> int i;
> void foo () { short *p = (short *)&i; *(int *)p = 1; }
>
> gcc currently does not generate a warning fo:
>
> int i;
> void foo () { short *p = (short *)(void *)&i; *p = 1; }


> [Those warnings seem appropriate. Casting int* to short* depends on
> byte order, (void *) is your way to say you know, you don't
> care. -John]


      IMHO, the first warning is spurious, because no aliasing rule is
being broken. The byte order of 'i' doesn't matter; all that matters
is whether a value of type (int*) can be losslessly converted to (short*)
and back. (ANSI C doesn't guarantee this, but all known C implementations
do, so warning about it seems silly.)
      IMHO, John's rationale that a cast to (void*) or (unsigned char*)
should suppress the second warning, thus making GCC's behavior correct
in the second case, is reasonable. However, another programmer might
reasonably argue that /any/ cast-expression is "your way to say you
know, and you don't care", and that if you're using the -Wstrict-aliasing
option, that's your way of saying "never mind, I do care, please!"




      Getting back to the topic of warnings: You /could/ implement such a
warning system in the following way, but I don't know of anyone who
does it like this:


      (1) Attach an "original type" to each pointer-expression; for example,
the original type of (unsigned char*)(&i+5) would be "(pointer to) int".
(The original type of a pointer which is a parameter to a function could
be its declared type; e.g., int *pi would have original type "(pointer
to) int", and we'd trust the user not to pass "bad" values between
functions.)
      A single expression might have a /set/ of original types, if its value
could have come from two or more assignments. Or you could just have a
special original-type value meaning "unknown".


      (2) Any time a pointer-expression is dereferenced, check its original
type A. If it differs from the expression's current type B, make a note
somewhere that objects of type B might be aliased as type A.


      (3) Do the same thing, any time a pointer-expression of original type A
is passed to a function expecting an argument of type B.


      (4) At the end of this process, you'll have a list of places to emit
GCC-style warnings; but also, you'll have a list of types involved in
aliasing trickery, and you might be able to feed that back into
optimization. (For example, after processing an entire program that
contains the definitions


          struct S { int foo; char k; int bar; } s;
          struct T { int foo; char k; char i, j; int bar; } t;


you might learn that 'struct S' is never aliased with 'struct T', and
therefore (by the "as-if rule") you don't need to keep their initial
segments the same; you can lay out S as


            |__foo__|_|_|_|k|__bar__|


and T as


            |__foo__|_|k|i|j|__bar__|


if that'll make it faster for you to access 's.k'.


      Now, that particular example requires whole-program optimization,
but I bet someone could come up with an example that didn't.


-Arthur


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.