noalias macro bug [was: Linux and aliasing?]

Jamie Lokier egcs@tantalophile.demon.co.uk
Tue Jun 8 14:40:00 GMT 1999


mark@codesourcery.com wrote:
> The address of `a' is cast to a pointer to a union.  Casting pointers
> around is explicitly permitted by ANSI C.  It's *dereferencing* them
> that's "dodgy".

We do dereference the cast pointer, isn't that dodgy?

> Then, the pointer to a union, is derefenced.  The compiler treats
> accesses through a union as able to alias memory of arbitrary types.

I assume the arbitrary types are "the types of the union fields".

> So, the access through the union may alias `a'.  Just like the manual
> says.

I'm not disagreeing that it may alias `a'.  But I'm questioning it.

If dereferencing a union type may alias memory of any of the types of
its fields, you're absolutely right and I understand this.

That's not what the manual says though.  It says:

>      The practice of reading from a different union member than the one
>      most recently written to (called "type-punning") is common.  Even
>      with `-fstrict-aliasing', type-punning is allowed, provided the
>      memory is accessed through the union type.  So, the code above
>      will work as expected.  However, this code might not:

"The practice of reading a different union member than the one most
recently written..."

That does not apply -- in the example, no union member was written.

> I think you're confusing (perhaps due to inaccuracies in the manual
> text) the concept of a union *variable* and a union *type*.

It could be due to an inaccuracy in the manual.  That's what I'm picking
on, because precise interpretation seems to affect whether the `noalias'
macro should work or not.

> We're talking type-based aliasing, so we're talking about types.  You
> seem to be thinking in terms of union *variables*, which are variables
> that have union type.

Let's name the union _type_ union_t.
Now, ((union_t *)(&a))->__y__ does have the same type as a.

Do you mean to state:

1.  ((union_t *)(&a))->__y__ may alias with a (because of type `int')

2.  therefore ((union_t *)(&a))->__x__ may alias with a (due to union)

I worry that 1. and hence 2. aren't true because of the following argument:

  struct { int x, y; } s;
  int a;

  s.x = 1;
  *(&s.y) = 2;     // 3. can this alias with `x' according to the standard?
  *(&a) = 3;       // 4. can this alias with `x' according to the standard?

I'd expect the *type*-based aliasing rules to consider different *struct*
fields unable to overlap.  Basic efficiency.  If I had the standard I'd check.

So I'd expect the answer to 3. to be "no".
So there's no reason to suppose the answer to 4. is any different.
Which means 1. doesn't apply, and `noalias' doesn't work.

Prove me wrong :-)

-- Jamie


More information about the Gcc mailing list