Linux and aliasing?
Linus Torvalds
torvalds@transmeta.com
Wed Jun 30 15:43:00 GMT 1999
On Sun, 6 Jun 1999, Martin v. Loewis wrote:
>
> Well, no. The 'normal' kind of cast is very common, and frequently
> used in the Linux kernel. For example, if a tty driver routine is
> called (e.g. drivers/char/rocket.c :-), it fetches driver_data and
> casts it to the device-specific type (i.e. (struct r_port *)).
No, but that "normal" kind of cast does not imply a immediate _derefernce_
(which is the only case where my new rule would kick in.
I agree that it is perfectly normal (and unavoidable) to do pointer
casting like
struct specific_struct * mystruct;
mystruct = (struct specific_struct *) data_struct->private_member;
and then use "mystruct". No argument. Linux (and tons of other programs)
do this all over the place, exactly because you have "anonymous" generic
pointers whose usage depends on who is the "owner" of that pointer.
The other obvious case is things like
mystruct = (struct specific_struct *) malloc();
which kind of falls under the same header.
But my proposal would only change cases where you actually dereference
such a cast without ever using the cast for anything else, which I
consider to be "dodgy" code unless the cast is there explicitly as a type
forcing conversion (that would imply no alias information).
"Normal" use like the two examples above would (and should) NOT be
impacted by any proposal of mine.
> In these cases, people typically save the cast result in a variable
> instead of derefencing it, so they would not suffer from your
> anti-aliasing mechanism. These uses of casts are conforming C code:
> The driver put an r_port pointer into driver_data earlier on.
Indeed.
Maybe people worried that those kinds of uses would be changed by the
change I proposed. They wouldn't. I would be upset if they were, and I
would understand that others would be upset if they were. That would imply
a real lack of alias information.
> > grep '\*(.*\* *)' */*.c
>
> It is actually the other casts that the Linux contributors need to
> worry about. Alias problems are very hard to find (as you pointed
> out), and somebody will have to go over the complete kernel source and
> investigate every single cast - if you ever plan to turn-on
> -fstrict-aliasing.
I agree. We need to be careful. But my proposal has two advantages:
- it takes care of the obvious cases (not just for the kernel, but for a
ton of other programs), and has a nice "do what I mean" kind of
semantic for all the cases I found.
In fact, try the above "grep" on the gcc sources themselves. You'll see
code like
*((EMUSHORT *) r) = w[3];
*((EMUSHORT *) r + 1) = w[2];
*((EMUSHORT *) r + 2) = w[1];
*((EMUSHORT *) r + 3) = w[0];
as part of the "PUT_REAL()" macro, and then you'll see usage like
PUT_REAL (g, &r);
return (r);
which is ILLEGAL because strict-aliasing might decide that "r" could be
loaded before PUT_REAL hass changed it, because "EMUSHORT" cannot alias
with "double". But it's _exactly_ the kind of code that my proposal
would just automatically do the right thing for.
It's "Do what I mean!"
Do you see? Gcc _itself_ wouldn't mind having the feature I propose.
Does that make people more likely to realize why I'm proposing it?
Maybe people still thought that this was something kernel-specific?
- The other advantage is that when going through the other cases more
carefully, my proposal would make it trivial to fix them up by just
adding a cast. I consider this part of the proposal to be a smaller
advantage, though.
Oh, well. I don't seem to be convincing people who have all dug themselves
into their own view.
Linus
More information about the Gcc
mailing list