This is the mail archive of the gcc-patches@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: PR3609


> Date: Thu, 09 Aug 2001 18:44:03 -0700
> From: Mark Mitchell <mark@codesourcery.com>
> cc: "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>

> --On Thursday, August 09, 2001 06:36:54 PM -0700 Geoff Keating 
> <geoffk@geoffk.org> wrote:
> 
> >
> > The appropriate place in the standard is section 6.3.2.3 paragraph 5,
> > which says
> >
> >   An integer may be converted to any pointer type.  Except as previously
> >   specified, the result is implementation-defined, might not be correctly
> >   aligned, might not point to an entity of the referenced type, and
> >   might be a trap representation.
> 
> Wow, it's weird for me to be in this role.  Normally, I'm the one
> arguing for making the compiler as strict as possible.
> 
> I agree, that says that it is implementation-defined, which is what
> I said all along -- but what does that mean?  It does mean we can
> do whatever we want, but usually implementation-defined (as opposed
> to undefined) means that you are supposed to do something vaguely
> sensible.  For example,
> 
>  (char*)(size_t)"foo"
> 
> is implementation-defined -- but it would be an unimpressive
> implementation that made that come out to anything but the address
> of the string, assuming enough bits in a size_t.

Some implementations can't do things like that in general, because
they have strict pointer safety in hardware.  For GCC, though, I would
expect that casting integers to pointers will always do the obvious
thing, and likewise the reverse; at the least, casting a pointer to an
integer and back again should give the original pointer.

I had to quote the bit of the C standard I did, because adding to an
integer would be OK; it is the cast back to a pointer that isn't
valid.  But I think a reasonable way for GCC to define the behaviour
is that

(T *)  (((ptrint_t) foo) + N)

where 'foo' is a T*, and N is divisible by sizeof(T), is equivalent to

foo + (N / sizeof (T))

and then the code has undefined behavour by section 6.5.6, para 8, see
below.

I think a very useful project would be to go through the standard,
look at all the places where it says "implementation-defined", and
document them in the GCC manual.

> I think it's pretty surprising that:
> 
>   strlen ("foo" + 100);
> 
> will have a different result from:
> 
>   char *f = "foo" + 100;
>   strlen (f);
> 
> In general, if introducing a temporary actually makes your code behave 
> differently, that's kinda weird.

This is completely different code from the example we had before.
This code has explicitly undefined behaviour in the C standard,
because 100 is more than the size of `"foo"', as section 6.5.6
paragraph 8:

  [When adding an integer to a pointer] If both the pointer operand
  and the result point to elements of the same array object, or one
  past the last element of the array object, the evaluation shall
  not produce an overflow; otherwise, the behaviour is undefined.

Treating two functionally-identical chunks of code differently
usually means we miss an optimisation; I'd hope that constant
propagation would make the two versions identical.

-- 
- Geoffrey Keating <geoffk@geoffk.org>


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