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]
Other format: [Raw text]

Re: [PATCH]: Fix PR tree-optimization/21407



On 11/05/2005, at 11:39 AM, Mark Mitchell wrote:


If you asked someone twenty years ago whether these kinds of operations were legal, the answer would have been uniformly yes. Now, opinions differ, because people are seeing more benefits of restricting these operations. But, the standards still don't say.

  struct I {
    virtual void f(); // I is not a POD.
    int a;
    int b;
  };

  void g() {
    I i;
    int *a_p = &i.b;
    /* 8 is a magic number! */
    I* i_p = (I*)((char *) a_p - 8);
    i_p->a = 3;
  }

There's no casting between pointers and integers. There are reinterpet_casts between pointers. The mapping is implementation- defined, but, in practice, all implementations on, say, IA32, are going to leave the bit-pattern unchanged. I just don't see anything that says conclusively that this code is invalid.

In C++, this code clearly invokes unspecified behaviour, initially with the cast of a_p to 'char *'. Now, if we want to specify the behaviour, that's fine; but I think it's a bit strange to say "and now that we've specified this behaviour, we don't understand what our specification means".


If we specify that reinterpret_cast<char *> gives a pointer into an array made up of the sequence of bytes in which the complete object is contained (see [intro.memory], and [intro.object] for a definition of 'complete object'), and we define reverse casts too, then clearly this code is valid. Obviously this statement makes certain limitations, for instance the C++ standard does not appear to require that an object is contained in a flat piece of memory (it says "region", not "range" or "contiguous region"), but this statement does.

Or, we could say that reinterpret_cast<char *> gives a pointer into an array made up of the sequence of bytes that contains the object, and that trying to create a pointer outside that array invokes undefined behaviour. This is like the ISO C definition, which I explained at <http://gcc.gnu.org/ml/gcc-patches/2005-05/ msg00909.html>. We could then define that a reverse cast must refer to a sub-object of the object that was pointed to by the original pointer. This is what I proposed for ISO C in that message. (ISO C+ + uses "sub-object" to mean what in ISO C is a "member object".)

Or, we could not define reinterpret_cast<char *>, so it gives a pointer of which any use other than casting it back to the original type is undefined behaviour. That would work too.

Or, we could have a compiler flag to choose between these, and implement them all!

Attachment: smime.p7s
Description: S/MIME cryptographic signature


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