On Thu, Jul 2, 2009 at 3:21 PM, Andrew Stubbs<a...@codesourcery.com> wrote:
> Hi all,
>
> I'm fairly sure I have found an aliasing bug in GCC, although I could be
> wrong. I've reproduced it in both 4.4 and mainline.
>
> Consider this testcase, aliasing.c:
>
>    extern void *foo;
>
>    extern inline short **
>    f1 (void)
>    {
>      union
>        {
>          void **v;
>          short **s;
>        } u;
>
>      u.v = (&foo);
>      if (*u.s == 0) *u.s = (short *)42;
>      return u.s;
>    }
>
>    const short *a, *b;
>
>    int
>    f ()
>    {
>      a = *f1();
>      b = *f1();
>    }
>
> The (not very useful) testcase initialises foo to 42, if necessary, and then
> sets both 'a' and 'b' to equal foo. There should be no way that 'a' and 'b'
> can ever be set to zero.
>
> Compile the code as follows:
>
>  sh-linux-gnu-gcc -c aliasing.c -O2 -fdump-tree-all
>
> The dump file aliasing.c.133t.optimized (the last tree dump) then contains:
>
>    f ()
>    {
>      void * foo.3;
>      short int * D.1982;
>      short int * * D.1973;
>
>    <bb 2>:
>      foo.3_10 = foo;
>      D.1982_26 = (short int *) foo.3_10;
>      if (D.1982_26 == 0B)
>        goto <bb 3>;
>      else
>        goto <bb 5>;
>
>    <bb 3>:
>      D.1973_13 = (short int * *) &foo;
>      *D.1973_13 = 42B;
>      a = 0B;
>
>    <bb 4>:
>      b = D.1982_26;
>      return;
>
>    <bb 5>:
>      a = D.1982_26;
>      goto <bb 4>;
>
>    }
>
> This is the state of the code after the tree optimisations. Both 'a' and 'b'
> are set to the initial value of foo, before it was initialised. Not only
> that, but 'a' is explicitly set to zero.
>
> This problem goes away if -fno-strict-aliasing is used.
>
> Is this a compiler bug? Or have I got something wrong in my code?

You are writing to memory of type void * via an lvalue of type short *.

Richard.

> Thanks
>
> Andrew
>

Reply via email to