New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[stmt.jump]/2 Fixed wording that does not apply to objects whose lifetime has ended #2872
Conversation
I agree the existing wording is sub-optimal, but it's not at all clear to me that we want to go this way. For example, [stmt.dcl] p2 wants to say the same thing we say in [stmt.jump], but says that "variables" are destroyed, not objects. Also, the issue of a mutilated object that we claim is "destroyed" is more pervasive, see e.g. [expr.delete] p1. However, for this case, p3 seems to fix the issue. |
@jensmaurer Throughout the standard, variable is used as a synonym for object, so it would be appropriate to keep it that way for the sake of consistency. Hence, in the proposed wording, "object to which the variable refers" is used to disambiguate from variables that denote references. As for [stmt.dcl]/2, I believe that is just a small issue with the wording, as reference do not have a storage duration, nor can they be destroyed as they are not objects. |
[basic] p6
[basic.stc] p3
Maybe it simplifies the presentation if we claim that references can be destroyed as well (except it's a no-op)? This is moving away from "editorial" land, though. |
@jensmaurer Specifying that references can be destroyed would be the way to go then, as it would clear up the wording for this particular instance as well as make it clear what is meant in [stmt.dcl]/2. It would also resolve the numerous instsnces where variables are said to be destroyed: |
Given those other locations, maybe the minimal fix is simply to replace "object" with "variable" in the text at issue? This would make the text parallel to the other appearances. |
@jensmaurer I think that is good, but some minor changes should made, such as replacing "constructed" with "declared", as without this change this would occur: |
On the other hand, we really want "constructed" in the sense of "control flowed through the declaration". It's not enough that the variable is declared in block scope; you must have also actually reached the declaration:
|
I think we really want "objects" not "variables that refer to objects", in order to deal properly with lifetime-extended temporaries. Can someone explain the problem with the status quo? [basic.life]p9 seems to already cover the case where an explicit destructor call on a variable precedes a |
@zygoloid, temporaries (also lifetime-extended ones) are fully covered by [class.temporary] p7 (nowadays under [basic]), so don't seem to need special treatment here. The problem with "object" is that being an "object" is a run-time property. So, in this example:
Since the "x" object has already been destroyed at #1, arguably the phrase "objects with automatic storage duration are destroyed" doesn't apply to "x" (the object is already gone according to [intro.object] p1). However, we want this case to be undefined behavior per [basic.life] by invoking the destructor of C on the automatic storage which used to contain the object "x". |
I don't think [class.temporary]p7 says when or whether the temporary in this case is destroyed:
The first sentence does not apply. The second sentence does not apply. And the third sentence adds no constraints. But the wording (surprisingly) found in [stmt.jump]p2 currently does cover it: the This wording probably belongs in [basic.life], likely immediately preceding paragraph 7, which talks about an "implicit destructor call" as if we'd already said there would be one, which we didn't. In fact, the first place where we actually say that destructors get implicitly called seems to be in [class.temporary]/4, and the primary place where we say that destructors get run seems to be [class.dtor]p12. [stmt.dcl]/2 also says "Variables with automatic storage duration [...] are destroyed on exit from the block" but doesn't cover temporaries. We have a lot of redundancy here, some wording using the wrong terminology (these days, we should be talking about objects being destroyed, not about destructors), and plenty of wording in surprising places. :-( I think a more substantial overhaul would be a good idea, with the intention being:
|
@zygoloid Is there even a way to specify using objects? As stated in [basic.life] p4, the wording in the standard only applies to objects during their lifetime. So in a basic case such as
There would be no way to specify this in terms of an object, as one simply does not exist. Specifying this in terms of a variable is one of the ways to do it, however, references currently are not destroyed, so we would either have to specify that this only applies to variables referring to objects, or specify that references can be destroyed. Rewording and reorganizing where implicit destruction is specified sounds like a good idea, as currently the wording is spread out all over the place, inconsistent, and in this case of the clause referenced by the issue, incorrect. |
@zygoloid, I follow your argument, but that makes [basic.stc.thread] p2 insufficient, too, because it also doesn't directly talk about references. My approach:
I'm feeling this is getting large enough to escape editorial scope, but let's see. |
Editorial meeting: This needs a paper to CWG, which should also fix the incorrect assumption that a variable is-an object. (Instead, a variable refers to an object or similar.) This should also address that re-entering a function creates fresh objects for the block-scope variables. Also, the destructor call at the end of a scope presumably uses a pointer to the original object, which may not point to a replacement meanwhile created at the same storage location. |
@jensmaurer Alright, I'll start on that then. |
@jensmaurer Finally getting around to writing the paper, one approach I was thinking about goes as follows:
Thoughts? |
Initial thoughts:
|
Whoops! Forgot to include that here. Something along the lines of "the region of storage occupied by an exception object is acquired in an unspecified way, except as explicitly noted in [...]"
Maybe we add a term "defining statement" in [stmt.dcl] which would be relative to a variable.
Perhaps I phrased this incorrectly. Pointers will still point to objects, however they will at the same time point to the storage at the address the represent. However, the fact that pointer to object can point to an object that no longer exists still remains problematic. Thank you for the feedback :) |
Objects created by new-expression have dynamic storage duration, not automatic |
Fixes #2871