This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [C++ patch] Set attributes for C++ runtime library calls
- From: Gabriel Dos Reis <gdr at integrable-solutions dot net>
- To: Mike Stump <mikestump at comcast dot net>
- Cc: Jan Hubicka <hubicka at ucw dot cz>, Alexander Monakov <amonakov at ispras dot ru>, "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>, Jason Merrill <jason at redhat dot com>
- Date: Fri, 23 Aug 2013 23:36:04 -0500
- Subject: Re: [C++ patch] Set attributes for C++ runtime library calls
- References: <20130822131927 dot GA18084 at kam dot mff dot cuni dot cz> <CAAiZkiDRZj-Fzy2+zUo9Z2B5ShvJ6K_duNyX1SKfrEZeX1NNZQ at mail dot gmail dot com> <alpine dot LNX dot 2 dot 00 dot 1308221836460 dot 30125 at monopod dot intra dot ispras dot ru> <20130822152111 dot GB19256 at kam dot mff dot cuni dot cz> <CAAiZkiA5wyTn0A_eMZ8d-crnq0KY0ut6R1ffh+2xsTp51dkWEg at mail dot gmail dot com> <20130822153958 dot GE19256 at kam dot mff dot cuni dot cz> <CAAiZkiCWf43bVyuVJC+D1=ghSLGTXsi5FbWVdUwX1kq4cNvavg at mail dot gmail dot com> <20130822161644 dot GC24022 at kam dot mff dot cuni dot cz> <CAAiZkiC7tztfKcwET95cacX52=xdRf+QuuUEUfOXTF+9QD69DA at mail dot gmail dot com> <960F238C-2F13-43A6-BE3E-65A917278ADA at comcast dot net> <CAAiZkiA-ZtmBTtgiijXuXkvY0x+M=9nat1TXt=vv86gtBun46w at mail dot gmail dot com> <C8BBC63A-ACAA-41CF-8EDD-7C31BA153314 at comcast dot net> <CAAiZkiCD1Dd7b7brFFK55mB8UjHziyq=00d4BBAzhP2rA70vfQ at mail dot gmail dot com> <7D009DAB-04DC-471F-9AE9-60F683F89D59 at comcast dot net> <CAAiZkiDqT_XoUXc7SfSEsSzV2GXhrgAPys0z9vd=KdrZZ__tNw at mail dot gmail dot com> <8C2DBF93-BC4D-464F-9529-B3D763A8304E at comcast dot net> <CAAiZkiBb5E0U+b4Jh8Z-CV8UdkV6iv-QU9qV=XBsqiTh=L_B8A at mail dot gmail dot com> <4E4F2B84-CEA1-4E13-8B37-1F732E6F6EE7 at comcast dot net>
On Fri, Aug 23, 2013 at 10:34 PM, Mike Stump <mikestump@comcast.net> wrote:
> On Aug 23, 2013, at 5:53 PM, Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
>> If you quoted the standard to back up your assertions, I would have been
>> able to "feel free to point this out" :-)
>>
>> The thing is I am still trying to figure out what (1) what you would have liked;
>
> I've directly stated it, not sure how you missed it. The life of the original object does not end.
You made a statement. It was not clear whether it was what you want
or whether it is what the standards mandate.
>> (2) what you believe the standards mandate, with appropriate quote; and
>
> The life of the original object does not end. See below for the quote.
Your assertion or a quote from the standards?
>
>>>> Really?
>>>
>>>>> statement, or, is it merely changing the value?
>>>>
>>>> That is an assignment to an existing int storage.
>>>
>>>>> And what if we do a memcpy (ip, &j, sizeof (int));
>>>>
>>>> Well, the case of 'memcpy' isn't defined by the standard
>>>
>>> Odd, in the c++98 standard memcpy was defined by the standard, as well as the open code that memcpy would be. I find memcpy in [diff.library]. I can quote all the requirements that makes the open code work as well. It is defined.
>>
>> When I say "the case of 'memcpy' isn't defined", I was not saying that
>> the function "memcpy" itself isn't defined by the standard. I was discussing
>> its effect in the scope of this discussion, e.g. lifetime vs. assignment.
>> That isn't defined in the standard.
>
> And yet memcpy is exactly defined and all interactions with the entire rest of the standard are as specified. Those semantics that are defined and required, are, by definition. You can't make them go away by claiming they are undefined.
I have no idea what exactly you are talking about.
If you have a rule in that standards that say that mempcy is assignment,
please share it with us.
>
> int i = 1, j = 2;
> {
> memcpy (&i, &j)
> // here i exists and is 2.
> }
>
> 3.7.1 Static storage duration [basic.stc.static]
>
> 1 All objects which neither have dynamic storage duration nor are local
> have static storage duration. The storage for these objects shall
> last for the duration of the program (_basic.start.init_,
> _basic.start.term_).
>
> This covers why i exists.
The storage duration of an object is not necessarily the same
as its lifetime.
> As for why i has the value 2, gosh:
>
> 7.21.2.1 The memcpy function
>
> Synopsis
>
> [#1]
>
> #include <string.h>
> void *memcpy(void * restrict s1,
> const void * restrict s2,
> size_t n);
>
> Description
>
> [#2] The memcpy function copies n characters from the object
> pointed to by s2 into the object pointed to by s1. If
> copying takes place between objects that overlap, the
> behavior is undefined.
>
>
> 1.6 The C++ memory model [intro.memory]
>
> 1 The fundamental storage unit in the C++ memory model is the byte.
>
> An object of POD4) type
> (_basic.types_) shall occupy contiguous bytes of storage.
>
> 5.3.3 Sizeof [expr.sizeof]
>
> 1 The sizeof operator yields the number of bytes in the object represen-
> tation of its operand. The operand is either an expression, which is
> not evaluated, or a parenthesized type-id. The sizeof operator shall
>
> 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). The value representation of an object is the set of bits
> that hold the value of type T. For POD types, the value representa-
> tion is a set of bits in the object representation that determines a
> value, which is one discrete element of an implementation-defined set
> of values.37)
Yes, but what is the relevance?
>
>>> You can see evidence that we meant for it to work here:
>>>
>>> 2 For any complete POD object type T, whether or not the object holds a
>>> valid value of type T, the underlying bytes (_intro.memory_) making up
>>> the object can be copied into an array of char or unsigned char.36) If
>>> the content of the array of char or unsigned char is copied back into
>>> the object, the object shall subsequently hold its original value.
>>> [Example:
>>> #define N sizeof(T)
>>> char buf[N];
>>> T obj; // obj initialized to its original value
>>> memcpy(buf, &obj, N); // between these two calls to memcpy,
>>> // obj might be modified
>>> memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar type
>>> // holds its original value
>>>
>>> thought, I view this as completely redundant with the standard and should just be a note. From the base standard, in C99 is it defined in 7.24.4.2.3 and I suspect remains largely unchanged from previous standards.
>>>
>>
>> This does not say whether the effect of memcpy is assigment or copy
>> construction.
>
> Right, because it doesn't define taking the bytes of one object and assigning another object to have those bytes. The definition of memcpy does that.
Chapter and verse, please.
>
> char c1, c2;
>
> c1 = c2;
>
> This is defined to take the bytes that comprise c2 (1 byte, by definition), and slam them into c1. After this runs, c1 will have the value of c2. This, is, by definition. We can plainly see the assignment operator. This is assignment, the hint is the spelling of the operator. It is spelled =. This is what the C standard means, when they say copies. copies is defined to mean, =.
so? What is the relevance exactly?
>
>> Which was the point I was making.
>
> Sure it does. Directly, please read the statement again:
>
> The memcpy function copies n characters from the object
> pointed to by s2 into the object pointed to by s1.
Yes, but why is that assignment not copy construction as in
new (p) T (v);
?
That is the question.
> I said what the words mean. I'd said copy means the = operator.
Copy in C++ does not necessarily mean assignment.
> Here is the text for =:
>
> [#3] An assignment operator stores a value in the object
> designated by the left operand.
This does not say that storying a value in an object is assignment.
> This is the very definition of the word copy, trust me. This is how the standard was meant to be read.
See above.
>
>>>>> I think the most logical line of reasoning is that when the requirements of [basic.lval] are met, the, this is a change of value of an object, not a modification to it's lifetime.
>>>>
>>>> Why?
>>>
>>> Because if you end the lifetime of the original int, you destroy the semantic that everyone knows for C. This cannot be done.
>>
>> But:
>> (1) we are not talking about C
>
> Sure we are.
No, we are not. Please look back at my original message that you replied to.
> The semantics of memcpy and its behavior come from C, and are identical to it. Since this is true, I can freely quote the required semantics of the C standard, they are identical.
>
>> (2) C does not have a notion of lifetime -- at least not in the sense of C++.
>
> It absolutely does: Let me quote:
>
> [#1] An object has a storage duration that determines its
> lifetime.
Please give the definition of 'lifetime'.
>
> [#17] Note that if a for loop were used instead of a while |
> loop, the lifetime of the unnamed object would be the body
> of the loop only, and on entry next time around p would be
> pointing to an object which is no longer guaranteed to |
> exist, which would result in undefined behavior.
>
> expression is evaluated. The size of each instance of a
> variable length array type does not change during its
> lifetime.
>
>
> 214The buffer has to have a lifetime at least as great as
> the open stream, so the stream should be closed before a
> buffer that has automatic storage duration is deallocated
> upon block exit.
>
> environment. All objects in static storage shall be
> initialized (set to their initial values) before program
> startup. The manner and timing of such initialization are
>
> [#5] An instance of each object with automatic storage
> duration is associated with each entry into its block. Such
> an object exists and retains its last-stored value during
> the execution of the block and while the block is suspended
> (by a call of a function or receipt of a signal).
>
> [#2] The malloc function allocates space for an object whose
> size is specified by size and whose value is indeterminate.
>
> -- The value of a pointer that refers to space deallocated
> by a call to the free or realloc function is used
> (7.20.3).
>
> [#2] The free function causes the space pointed to by ptr to
> be deallocated, that is, made available for further
> allocation.
But this is not the lifetime in the C++ sense.
> I'll note that C++ merely sought to explain and formalize the rules of C.
Strongly disagree with that note.
> We extended and added a few bits, but, the object model is based upon the C model.
The object model may have been based on C, but it went way beyond C in say that
C++ object model is expressible in C any more -- think empty base optimization.
This isn't just a few bits.
> I can't begin to fathom how you could have possibly missed the notion of lifetime in C.
Most likely because I didn't miss it.
> It right there, an just about exactly matches C++.
Not at all. We tried to make certain constructs have similar byte-level
interpretation, but the conceptual models are completely different.
>
>> So, whatever notion of semantics you think everyone knows of C
>> is largely irrelevant.
>
> No, you must not understand C++ to say this.
Guilty as charged. I must also confess that I do not know of any
body who understands C++ -- not even the collective body of the
C++ standards committee.
> C++ is defined to be, exactly what C is,
I cannot understand the source of this confusion.
> with a few exceptions here and there, and in this case, there are no exceptions. This is by design. I'm sorry if you didn't realize this.
>
Please don't be sorry, the confusion isn't necessarily where you believe it is.
>>>>> So, in the case quoted, since the type of the accesses are both int, we don't reuse the storage, since the requirements of [basic.lval] are met.
>>>>
>>>> Consider:
>>>>
>>>> struct S {
>>>> S(int);
>>>> ~S();
>>>> // …
>>>> };
>>>>
>>>> int main() {
>>>> S s(8);
>>>>
>>>> new (&s) S(9); // #1
>>>> }
>>>>
>>>> Is #1 a reuse of storage to create a new object or assignment?
>>>
>>> Behaves as assignment, s exists post the new, til the closing }.
>>
>> What does not mean concretely?
>
> Concretely, it means exactly what is stated in the standard.
Great! The standards does not state it is assignment.
> I've quoted all the words. copy means =.
No; I am sorry but you are plain wrong on this.
> = is an assignment operator.
Yep, and C++ makes a distinction between copy and assignment.
> Concretely, where did you get lost?
Trying to connect what the standards say and your assertions.
> In the //, one can imagine you're asking about
>
> S (int v) { val = v; }
> int val;
That is one possible imagination; but it isn't the only one.
> to be concrete. We can see the = operator.
In that imagination you just created, yes. But it wasn't there
to begin with.
> This is the assignment operator, by definition.
Yes, but see above.
>>>>> Indeed, the programmer expects that they can access i after *ip = j; and that the _value_ that object, while changed from the original 1, will be 2 just after the *ip = j; statement.
>>>>>
>>>>> Since we know that i must be 3 at the end, we then know what the wording, reused, must mean, cause other meanings that could possibly make it work for you in the case you are considering, would destroy this property of pointers, and everyone knows the semantics of pointers, they are undisputed. Or put another way, you cannot misread reused in this way.
>>>>
>>>> And why do you assert that I misread 'reused' in this way?
>>>
>>> See your email that I originally replied to.
>>>
>>> Let me quote it here:
>>>
>>>> If the user-supplied operator new returns &a, then it must
>>>> also ensure that 'a' is not used anywhere else -- e.g. I you can't
>>>> do lvalue-to-value conversion on 'a' to see what is written there.
>>>> Because its storage has been reused.
>>>
>>> You said it was reused, this is wrong.
>>
>> You keep saying it is wrong without quoting the standards that is the
>> basis for that.
>
> I've quoted the required semantics of the standard. What part was unclear to you?
See above.
>
>>> You use that as backing to say that the lifetime of the original object ends, this is wrong.
>>
>> You *assert* it is wrong.
>
> I quoted the required semantics of the language standard. What part was unclear to you?
The part where you assert imaginary things :-)
-- Gaby