-
Notifications
You must be signed in to change notification settings - Fork 7
CWG2721 [basic.life] When exactly is "the storage which the object occupies [...] reused"? #278
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
Comments
Vote for 1 |
Perhaps we can separate the bullet to make the intent of interpretation (1) clear:
Could this be interfered by implicit object creation? (Although implicit object creation can be considered not happening in constant evaluation.) Edit: perhaps implicit creation should also be considered:
|
As the opener of the original clang bug, I was surprised to see that it appeared to "work" on gcc. As much as I would have liked for this to be valid because it simplifies some code to avoid a self-move-assignment check, I also couldn't figure out how implementations could actually make this work with things like NRVO, which feels like the far more important optimization to support. So coming at this from a purely pragmatic instead of conceptual angle, it seems like a resolution like the proposed option 1 would be better. To make sure I understand option 1 fully, this would mean that in struct s {
int m;
};
void f() {
s x{1};
new(&x) s(x.m);
} |
I think you mean would be UB, but yes
(https://timsong-cpp.github.io/cppwp/n4868/expr.new#23.sentence-1) So by the time the evaluation of |
Full name of submitter (unless configured in github; will be published with the issue): Richard Smith
Reference (section label): [basic.life]/1.5
Link to reflector thread (if any):
Issue description:
[basic.life]/1.5 says:
but what does that mean? In llvm/llvm-project#61562 we have two possible interpretations:
new (p) T(x)
, the lifetime of*p
ends whenp
is returned fromvoid* operator new(size_t, void*)
, beforex
is evaluated.new (p) T(x)
, the lifetime of*p
ends the moment the constructor body starts executing, afterx
is evaluated.Note that interpretation (2) only works when the initialization is performed by a constructor or if
T
is a non-class type, and we must use interpretation (1) for aggregate initialization because the evaluation ofx
can directly initialize a part of the resulting object.Suggested resolution:
To me, it seems that the most consistent and simplest model is that the lifetime of
*p
ends the moment thatp
is returned from anoperator new
function invoked by a new-expression, and in particular, the object no longer exists in the evaluation of the new-initializer.Alternatively, we could say that the the lifetime ends as late as possible -- the moment anything actually starts initializing the new object (perhaps, when a constructor starts running or a value is stored for the object or any of its subobjects). That's probably going to be challenging for constant interpreters to model, though.
The text was updated successfully, but these errors were encountered: