This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH]: Fix PR tree-optimization/21407
On May 11, 2005, at 6:21 PM, Geoff Keating wrote:
One implicit thing that you haven't said is "and then execution
continues as specified in the rest of the standard". The problem
is that in this case, that's not a complete specification
A complete specification isn't required, only enough constraints to
mandate that the right thing happen.
and in fact will in this example quickly lead to undefined
behaviour again.
This is in dispute of course.
[basic.compound] para 3 says "The value representation of pointer
types is implementation-defined."
This is immaterial and means nothing. Well, technically, it means
you cannot printf %x and intuit meaning from what you see... and
that is about it, since we aren't doing that, this is irrelevant.
So just saying "the bit patterns are the same" could produce any
result.
Only so far as the rest of the standard doesn't mandate a particular
case, in this case, i'd claim it does, therefore, it cannot.
So let's say that you actually define the result as having a value
of the same address as the original pointer.
It is, by definition.
OK, so now we have two pointers, different types, same address.
Let's assume that there is an object of type 'int' at that address,
which the original pointer pointed to. Now we have a pointer to
'char' at the same address. Let's assume no object of type 'char'
has been created at that address: there's an exhaustive list of the
ways that objects are created in [intro.object], and none of them
has happened.
Odd, in his code I see:
I i;
and accordingly, the standard says:
An object is created by a definition (_basic.def_)
I don't think this gets any clearer than that. In case you missed
why a and b are also objects and are created by that same line:
2 Objects can contain other objects, called sub-objects. A sub-object
can be a member sub-object (_class.mem_), a base class sub-
object
(clause _class.derived_), or an array element. An object that is
not
a sub-object of any other object is called a complete object.
again, couldn't be clearer. As for the char, it exists by definition:
The object representation of an object of type T is the sequence
of N
unsigned char objects taken up by the object of type T, where N
equals
sizeof(T).
One cannot have a complete object of type T, without the sequence of
N unsigned char objects.
[basic.compound] para 3 says that "If an object of type T is
located at an address A, a pointer of type cv T* whose value is the
address A is said to point to that object, regardless of how the
value was obtained." It doesn't say anything about what happens if
there isn't an object of the right type there.
But there is. There is a character (by definition) and there is an
int, either may be accessed.
So now you have to fill in that blank, or be back at undefined
behaviour again: does this pointer point to an object? What object?
Why guess, just read [basic.life] for the rules. I don't find it
inaccessible. In this case, the int comes into being:
1 The lifetime of an object is a runtime property of the object. The
lifetime of an object of type T begins when:
--storage with the proper alignment and size for type T is
obtained,
and ends:
The lifetime of an object of type T ends when:
--the storage which the object occupies is reused or released.
failure to reuse or release, means it doesn't end, save program
termination:
The storage for these objects shall
last for the duration of the program
(_basic.start.init_,
_basic.start.term_).
You can't find those answers by reading the standard;
I can. Anyone trained to read it should be able to.
The C++ standard says this in almost as many words, [basic.compound]
p3. (C is very different, and I don't think that statement is true
in C.)
C++ is meant to be our understanding of what C says, really, honest.
(1) Ok, this is true only some of the time, but, generally speaking,
it is true, but don't bother pointing out the deviations, I know of
them already.
I think that [expr.add] paragraph 5 is pretty much a statement that
sometimes, when you add and subtract things from pointers, it can
fail: "If [blah blah], the evaluation shall not produce an
overflow; otherwise, the behavior is undefined."
No; 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! It is
mandated to never fail in that case.
It talks about elements of an array object. And that takes us back
to the start, which is "what object, if any, does this pointer
point to?" Is it an array object? How long is it?
The char pointer is a pointer to the object's representation,
really. That is defined to be:
4 The object representation of an object of type T is the sequence of N
unsigned char objects taken up by the object of type T, where N
equals
sizeof(T).
No amount of changing of the char pointer, changes the type, char,
nor the size, N (sizeof(T)), nor the location of the object, nor the
lifetime of the char objects, nor the lifetime of the compete object
(T).
Now, before you ask, how did you come to that conclusion:
2 An rvalue of type "pointer to cv T," where T is an object type, can be
converted to an rvalue of type "pointer to cv void." The
result of
converting a "pointer to cv T" to a "pointer to cv void" points to
the
start of the storage location where the object of type T
resides, as
if the object is a most derived object (_intro.object_) of
type T
(that is, not a base class subobject).
and, before you point out, that has nothing to do with the char *:
A
cv-qualified or cv-unqualified (_basic.type.qualifier_) void*
shall
have the same representation and alignment requirements as a cv-
quali-
fied or cv-unqualified char*.