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: Mike Stump <mikestump at comcast dot net>
- To: Gabriel Dos Reis <gdr at integrable-solutions 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 17:32:23 -0700
- 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>
On Aug 22, 2013, at 7:16 PM, Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
>>> My reasoning (for C++98, but the same is true for C++11) is based
>>> on 3.8/1:
>>> […]
>>> The lifetime of an object of type T ends when:
>>> -- if T is a class type with a non-trivial destructor (12.4),
>>> the destructor call starts, or
>>> -- the storage which the object occupies is reused or released.
>>>
>>> Doing a placement-new on the storage occupied by 'a' is reusing
>>> its storage, therefore ending its lifetime.
>>
>> The problem is that reused is not well defined,
>
> I am not quite so sure.
If it were, there would be a definition of it. If there were, you could quote it and we could discuss it. I know what it means, and I have a nice theoretical backing for it and the actual definition would require 3 pages to explain.
> But even so, in light of this, I don't think you original assertion is definitive.
Nothing is ever definitive. Now, if you want to say I quoted something wrong, or that I am reading the standard wrong, or that it doesn't apply as I think it does, feel free to point this out. I do view this as as a two way street, despite the certainty I might profess.
>> so, we are into the weeds right there.
>>
>> int i, j;
>>
>> int *ip = &i;
>>
>> i = 1;
>> j = 2;
>> *ip = j;
>> ++i;
>> ++j;
>>
>> here, we sees the storage being reused in the *ip = j;
>
> 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.
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.
>> Is that reused, or merely changing the value.
>
> The current proposal is that it constructs an int value, therefore
> is moral equivalent of copy-constructor call.
I'd be interested in the final resolution. You have a DR number for the issue or a paper where they talk about the issues?
>> 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.
>> 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 }.
>> 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 use that as backing to say that the lifetime of the original object ends, this is wrong.