This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: PATCH: `__norestrict' type qualifier




On 18 Jul 1999, Patrick J. LoPresti wrote:
>
>  torvalds> In all fairness it also gathered a lot of people who didn't
>  torvalds> like it, but none on tecnical grounds (several on the
>  torvalds> grounds of "don't add extensions to the language").
> 
> (I also just finished reading most of the comp.std.c discussion)
> 
> To be completely fair, there was at least one reasonable technical
> objection to the keyword as an extension to the standard: It would
> seem to *require* that implementations allow access to the bits in an
> object of one type via a pointer of another type.

I never understood that argument. It didn't make any real sense to me.

That particular argument hinged on completely false premises: it assumed
that the "norestrict" proposal would somehow magically make all the other
rules for strictly conforming pointer use go away. It doesn't. The
programmer is still supposed to know about alignment and other things.

"norestrict" does not magically make the pointer a "super-pointer", with
X-ray vision and the power to leap tall buildings. If you want to write a
strictly conforming program, you still have to follow all the other rules,
and among those rules are that you cannot just do anything you want with
pointers.

For example, here is a hypothetical strictly conforming program that uses
the "norestrict" keyword (assuming it was to be made part of the
standard), and that actually takes advantage of what norestrict guarantees
without breaking any other rules:

	void *p = malloc(sizeof(unsigned long));
	unsigned short norestrict *sp = (unsigned short norestrict *) p;
	unsigned int norestrict *ip = (unsigned int norestrict *) p;
	unsigned int sum;

	*sp = 5;
	sum = *sp;
	*ip = 10;
	sum += *ip;

Think about what the C language guarantees are about the above program
with and without the "norestrict" keyword.

-- spoiler follows --

Without "norestrict" the compiler could re-order the accesses to *ip wrt
the accesses to *sp (because they "cannot" alias), resulting in a
completely random result. There is no guarantee that the above will result
in "sum" having the value 15.

(Admittedly, in this particular example any good compiler would just
optimize things away and get 15 without even bothering to worry about
aliases, but you should think like a language lawyer for a while).

In contrast, with "norestrict" the above suddenly has well-defined
behaviour (and the behaviour is the one that makes sense to a human).
There are no other language rules being broken: all pointer casts are
legal as "malloc()" is guaranteed to return a pointer that can be used
with any type, and all accesses to the pointer have been done with the
same type as the assignment was done. Thus a conforming compiler HAS to
end up with 15 in the sum. But IF AND ONLY IF "norestrict" is there.

Yes, the above is a completely made up and bogus piece of code. But I
think it shows how "norestrict" can actually result in well-defined
behaviour - without implying any other rules were broken.

Of course, in real life "norestrict" would almost always be used in
non-portable code, and I'm not really claiming otherwise. But I think too
many people think that "non-portable" means "evil". It doesn't, really. In
the end, you have to be unportable when doing real work - maybe most
programmers don't need to, but people implementing libraries and the like
do have to know about the particular architecture they'll end up running
on..

Or have I missed something?

		Linus

PS. The other reason that the bit-wise argument does not make any sense at
all is that a implementation is _already_ required to make the bit-wise
representation available regardless of "norestrict", simply because of
the implied "norestrict" on any "char *" access:

	double f = 0.12345678;
	int i;
	char *p;

	p = (char *)f;
	for (i = 0; i < sizeof(f) ; i++)
		printf("byte %d: %02x\n", i, (unsigned char) *p);

no?


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]