Subject: Re: About the description of [basic.life]/6
From: Andrew Schepler (aschepler_at_[hidden])
Date: 2020-04-18 08:52:57
On Fri, Apr 17, 2020 at 9:03 PM Tadeus Prastowo <tadeus.prastowo_at_[hidden]>
> On Sat, Apr 18, 2020 at 12:02 AM Andrew Schepler <aschepler_at_[hidden]>
> > That seems mostly right, but a few things still sounded off to me. So
> I'm not sure if I'm agreeing or disagreeing, reading something a way it
> wasn't met, etc., but:
> > Recapping the labels from previous messages:
> > (Sentence-X):
> > "Before the lifetime of an object has started but after the storage
> which the object will occupy has been allocated or, after the lifetime of
> an object has ended and before the storage which the object occupied is
> reused or released, any pointer"
> > (Condition-1):
> > "that represents the address of the storage location where the
> object will be or was located"
> > "may be used but only in limited ways."
> This approach will work on the condition that "before the storage
> which the object occupied is reused" is interpreted as reused _only_
> through the original pointer, which in the example in question is the
> pointer `pb'. If "before the storage which the object occupied is
> reused" is not interpreted as such, the approach will fail for the
> example in question because for the particular point being discussed,
> which is the expression `*pb' being OK, the condition "before the
> storage which the object occupied is reused" does not hold owing to
> the allocated storage being reused through the pointer `this' within
> the member function `mutate'.
Oh, I hadn't noticed that. I don't like that interpretation: "the storage
which the object occupied" is a property of the memory model and the
object, not any particular syntax. Nothing else I know of really supports
"storage reused through a pointer" having particular meaning. Now I think
the example just doesn't match the normative text, and a Defect Report
would be appropriate.
One example that does match the text would be use of a pointer to union
member during the union's lifetime, before the member is manually created
with a placement new-expression and/or after the member is manually
destroyed with a destructor call.
Or, it seems likely the intent was for the wording to apply to cases like
the example, so including pointers which pointed to objects whose lifetime
ended because the unreleased storage was reused, but excluding pointers
which point at the new object per paragraph 8.
It's also confusing that paragraph 8 says "If, ... before the storage which
the object occupied is reused or released, a new object is created at the
storage location which the original object occupied". Isn't creating that
object the exact meaning of "storage is reused"? Maybe it means the storage
was not previously reused? Or maybe in all of paragraphs 6, 7, and 8,
changing "is reused or released" to just "is released", and clarifying that
paragraph 8 has precedence over 6 and 7, would better match the intent?
(The Note and Example in [intro.object]/3 do seem to confirm creating an
object via placement new can be one case of "reused storage".)
> > (Sentence-Y):
> > (Condition-2):
> > "For an object under construction or destruction,"
> > "see [class.cdtor]."
> > (Sentence-A):
> > "Otherwise, such a pointer"
> > (Condition-3 ?):
> > "refers to allocated storage ([basic.stc.dynamic.allocation]),"
> > "and using the pointer as if the pointer were of type void* is
> > (Sentence-B):
> > "Indirection through such a pointer is permitted but the resulting
> lvalue may only be used in limited ways, as described below."
> > (Sentence-C):
> > "The program has undefined behavior if:" ... [through paragraph (6.5)]
> > I would say Sentence-X is the topic sentence for all of paragraph 6,
> including the list (6.1)-(6.5). None of this applies to pointers that do
> not satisfy Condition-1 (like a pointer to an object during its lifetime, a
> pointer with null pointer value, or a pointer with indeterminate value).
> For a pointer to an object satisfying Condition-2 (yes, a special case of
> pointers satisfying Condition-1), [class.cdtor] covers all limitations on
> uses of the pointer. The word "Otherwise" contrasts with Condition-2, so
> that Sentences A, B, and C all apply to pointers which satisfy Condition-1
> but not Condition-2. In Sentence-A, "refers to allocated storage" is not a
> new condition, just a rephrasing or description of Condition-1, with a
> better term to use since we don't want to say "pointer to object" when no
> object exists.
> > So for a pointer P which satisfies Condition-1 and Condition-2:
> > - The rules of [class.cdtor] apply. Sentence-A, Sentence-B, and
> Sentence-C do not apply.
> > And for a pointer P which satisfies Condition-1 but not Condition-2:
> > - Per Sentence-A, it can be used "as if it were of type void*". (This
> is somewhat vague, and might be just descriptive of what's NOT ruled out by
> paragraph 7 and sentence C.)
> > - Per Sentence-B, *P and P->m are valid as long as the rules in
> paragraph 7 which apply to that lvalue are met.
> > - Per Sentence-C, certain uses have undefined behavior.
> If the interpretation of "before the storage which the object occupied
> is reused" in Sentence-X is being reused _only_ through the original
> pointer, I agree with your analysis. Otherwise, I don't.
> > And it's worth noting I'm pretty sure the rules of [class.cdtor] are
> always at least as permissive as the rules from paragraph 7 and Sentence-C:
> anything permitted for a pointer to allocated storage without an object
> under construction or destruction is also allowed for a pointer to an
> object under construction or destruction.
> Noted. Thank you.
> > -- Andrew Schepler
> Best regards,
STD-DISCUSSION list run by firstname.lastname@example.org
Older Archives on Google Groups