Skip to content
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

[class.temporary] p6.6 "glvalue operand" is misleading #5352

Open
killerbee13 opened this issue Mar 18, 2022 · 5 comments
Open

[class.temporary] p6.6 "glvalue operand" is misleading #5352

killerbee13 opened this issue Mar 18, 2022 · 5 comments

Comments

@killerbee13
Copy link

[class.temporary] p6.6 states that lifetime extension is applied to the temporary object referred to by "a [cast expression] converting, without a user-defined conversion, a glvalue operand that is one of these expressions to a glvalue that refers to the object designated by the operand, or to its complete object or a subobject thereof,". This appears to indicate that the following code has a dangling reference

class S{};
S&& s = static_cast<S&&>(S{});

because S{} is a prvalue, whereas in fact, according to [expr.static.cast] p4, the temporary materialization conversion is applied to the operand of a static cast, meaning that static_cast<S&&>(S{}) is a conversion of a glvalue to a glvalue.

The same logic applies to const_cast, because converting a prvalue to a glvalue also performs the temporary materialization conversion, see [expr.const.cast] p4. [expr.dynamic.cast] p2 and [expr.reinterpret.cast] p11 explicitly ban conversions of prvalues to glvalues.

Thus, using the term "glvalue operand" in p6.6 serves only to confuse the reader that is not already intimately familiar with [expr.static.cast] and [expr.const.cast], and means nothing at all to those who are because it can be deduced from context.

None of p6.1-6.5 explicitly specify that the expression shall be a glvalue, because all expressions described in p6 are already glvalues. p6.7 and p6.8 are correct because a conditional expression or comma expression returning a prvalue falls under p6.1, as the temporary is materialized from the result rather than within the expression.

I believe that p6.6 would be clearer and suffer no loss of precision if it read "[...] an operand that is one of these expressions to a glvalue that [...]".

@frederick-vs-ja
Copy link
Contributor

frederick-vs-ja commented Mar 19, 2022

I think the term "glvalue operand" is used to indicate that operand must not undergo lvalue-to-rvalue conversion here (otherwise, a distinct temporary object is created). Even though static_cast, etc. ban conversions of prvalues to glvalues, the lvalue-to-rvalue implicit conversion can still happen to the operand.
For example, in the definition:

long&& x = static_cast<long&&>(static_cast<int&&>(0));

Perhaps the first "glvalue" here is redundant, as when a distinct temporary object is created, the original temporary object can no longer be designated by result of the cast. But I don't think it's misleading.

@xmh0511
Copy link
Contributor

xmh0511 commented Mar 19, 2022

None of p6.1-6.5 explicitly specify that the expression shall be a glvalue

These expressions shall be glvalues because p6 impose that requirement

if the glvalue to which the reference is bound was obtained through one of the following

whereas in fact, according to [expr.static.cast] p4, the temporary materialization conversion is applied to the operand of a static cast, meaning that static_cast<S&&>(S{}) is a conversion of a glvalue to a glvalue.

I think the operand of the static_cast is still a prvalue. [expr.static.cast] p4 just means the conversion is reinterpreted to T t = E; defined in [conv] p3 and use that result as the result of the static_cast expression.

This appears to indicate that the following code has a dangling reference

This seems to be the quo status the current wording means. However, most implementations nod toward that the lifetime of the temporary object is extended.

Maybe, we should change [class.temporary] p6.6 to

[cast expression]

converting, without a user-defined conversion, a prvalue operand to a glvalue, or a glvalue operand that is one of these expressions to a glvalue that refers to the object designated by the operand, or to its complete object or a subobject thereof,

@frederick-vs-ja
Copy link
Contributor

This seems to be the quo status the current wording means.

I don't think this is. The following example says that lifetime extension happens in such cases, and both the normative wording and the example are added by P0727R0 (the resolution of CWG1299).

It seems a bit ambiguous on the meaning of the "operand" of static_cast etc.. Presumably the intent of [class.temporary]/6 is considering temporary materialization as a part of the operand.

@xmh0511
Copy link
Contributor

xmh0511 commented Mar 19, 2022

It seems a bit ambiguous on the meaning of the "operand" of static_cast

The subclause [expr.static.cast] is more and less to imply that the expression designated by the symbol v is its operand (static_­cast<T>(v) ).

The static_­cast operator shall not cast away constness ([expr.const.cast]).

otherwise, the lvalue-to-rvalue conversion is applied to the bit-field and the resulting prvalue is used as the operand of the static_­cast for the remainder of this subclause.

Any expression can be explicitly converted to type cv void, in which case the operand is a discarded-value expression ([expr.prop]).

The lvalue-to-rvalue ([conv.lval]), array-to-pointer ([conv.array]), and function-to-pointer ([conv.func]) conversions are applied to the operand.

Hence, if we say that glvalue operand that is one of these expressions, it is equivalent to state that the expression that appears in the place of symbol v shall be a glvalue and shall be one of these expressions, which directly exclude the possibility that v is a prvalue expression. So, I think the current wording didn't well express the intent of the example.

@frederick-vs-ja
Copy link
Contributor

See CWG2666.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants