This is the mail archive of the 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: [C++ patch] Set attributes for C++ runtime library calls

On Fri, Aug 23, 2013 at 10:34 PM, Mike Stump <> wrote:
> On Aug 23, 2013, at 5:53 PM, Gabriel Dos Reis <> 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                      []
> 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:
>  The memcpy function
>        Synopsis
>        [#1]
>                #include &lt;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 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

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