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
x
whose name appears as a potentially-evaluated expressionex
is odr-used byex
unless applying the lvalue-to-rvalue conversion (7.1) tox
yields a constant expression (8.6) that does not invoke any non-trivial functions and, ifx
is an object,ex
is an element of the set of potential results of an expressione
, where either the lvalue-to-rvalue conversion (7.1) is applied toe
, ore
is 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
x
yields 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
e
is 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