The code below compiles in GCC, clang and VS2017 and the expression a->i in the return statement is replaced by its constant value 1. Is it correct to say that this is valid because a is not odr-used in the expression a->i?.
struct A
{
static const int i = 1;
};
int f()
{
A *a = nullptr;
return a->i;
}
PS: I believe a is not odr-used in the expression a->i because it satisfies the "unless" condition in [basic.def.odr]/4, as follows:
A variable
xwhose name appears as a potentially-evaluated expressionexis odr-used byexunless applying the lvalue-to-rvalue conversion (7.1) toxyields a constant expression (8.6) that does not invoke any non-trivial functions and, ifxis an object,exis an element of the set of potential results of an expressione, where either the lvalue-to-rvalue conversion (7.1) is applied toe, oreis a discarded-value expression (8.2).
In particular, the expression ex == a is an element of the set of potential results of the expression e == a->i, according to [basic.def.odr]/2 (2.3), containing the expression ex, where the lvalue-to-rvalue conversion is applied to e.
a is odr-used because you fail the first part of the "unless":
applying the lvalue-to-rvalue conversion (7.1) to
xyields a constant expression (8.6) that does not invoke any non-trivial functions
Applying the lvalue-to-rvalue conversion to a does not yield a constant expression.
The rest is core issues 315 and 232.
Your analysis is broken in two additional ways:
. form of class member access, so you need to rewrite a->i to dot form, i.e., (*a).i, before applying [basic.def.odr]/2.3. a is not a member of the set of potential results of that expression.a is doubly not a member of the set of potential results of that expression.[expr.const]/2.7:
An expression
eis a core constant expression unless the evaluation ofe, following the rules of the abstract machine, would evaluate one of the following expressions:
- [...]
- an lvalue-to-rvalue conversion unless it is applied to
- a non-volatile glvalue of integral or enumeration type that refers to a complete non-volatile const object with a preceding initialization, initialized with a constant expression, or
- a non-volatile glvalue that refers to a subobject of a string literal, or
- a non-volatile glvalue that refers to a non-volatile object defined with
constexpr, or that refers to a non-mutable subobject of such an object, or- a non-volatile glvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of
e;- [...]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With