Description
Full name of submitter (unless configured in github; will be published with the issue): Jiang An
Reference (section label): [expr.delete]
Link to reflector thread (if any):
Issue description:
[expr.delete] p4 currently only says
The cast-expression in a delete-expression shall be evaluated exactly once.
When the cast-expression is a glvalue of a pointer type, it doesn't seem guaranteed that the lvalue-to-rvalue conversion from the expression is performed exactly once. Likewise, it doesn't seem guaranteed that the contextual conversion to a pointer from the cast-expression of a class type is performed exactly once. As a result, the destructor call and the operator delete
call may use different pointer values, which possibly results in undefined behavior.
In the following example
struct S;
S* ptr{};
struct S {
S() = default;
~S() {
ptr = this + 1;
}
};
int main() {
ptr = new S;
delete ptr;
}
even though the cast-expression (ptr
) is evaluated only once, the value of the ptr
object is changed by the destructor call, and thus it's not guaranteed that the operator delete
will take the correct pointer value.
It seems that current implementations (correctly) perform the necessary conversions exactly once.
Suggested resolution:
Change [expr.delete] p2 as indicated (CWG1642 might render the changes in this paragraph unnecessary):
If the operand has a class type, the operand is converted to a pointer type by calling the above-mentioned conversion function
, and the. If the possibly converted operand is a glvalue of a pointer type, it is converted to a prvalue of that type by lvalue-to-rvalue conversion (7.3.2 [conv.lval]). The converted operand is used in place of the original operand for the remainder of this subclause. [...]
Change [expr.delete] p4 as indicated:
The cast-expression in a delete-expression, together with the necessary conversions to a prvalue of a pointer type (if any), shall be evaluated exactly once.