-
Notifications
You must be signed in to change notification settings - Fork 8
Description
Full name of submitter (unless configured in github; will be published with the issue): Jiang An
Reference (section label): [expr.const], [dcl.ref]
Link to reflector thread (if any):
Issue description:
Currently, [dcl.ref] p6 states:
The behavior of an evaluation of a reference ([expr.prim.id], [expr.ref]) that does not happen after ([intro.races]) the initialization of the reference is undefined.
While [expr.const] p16 states:
During the evaluation of an expression E as a core constant expression, all id-expressions, splice-expressions, and uses of
*thisthat refer to an object or reference whose lifetime did not begin with the evaluation of E are treated as referring to a specific instance of that object or reference whose lifetime and that of all subobjects (including all union members) includes the entire constant evaluation. For such an object that is not usable in constant expressions, the dynamic type of the object is constexpr-unknown. For such a reference that is not usable in constant expressions, the reference is treated as binding to an unspecified object of the referenced type whose lifetime and that of all subobjects includes the entire constant evaluation and whose dynamic type is constexpr-unknown.
Does [expr.const] p16 intend to mean that all references (to objects) are considered already initialized during constant evaluation, so the UB specified in [dcl.ref] p6 never causes constant evaluation failure?
Consider the following example (where there's implementation divergence, demo):
int n;
constexpr bool fun() {
int& r3 = (r3, n); // runtime-only UB?
return true;
}
int main() {
int& r1 = (r1, n); // UB
constexpr int& r2 = (r2, n); // OK?
fun(); // UB
static_assert(fun()); // OK?
}Per currently rules, it seems that fun() essentially only causes runtime-undefined behavior.
P2280R4 talked about references that are
- function parameters, and
- only forward-declared at the point of constant evaluation,
and didn't talk about self-using in the initialization. Would it be better to slightly tighten the rule to reject "obvious" UB, by excluding the treatment in [expr.const] p16 for a reference that is being initialized?
Or alternatively, would it be better to make certain kinds evaluation of uninitialized reference well-defined, which would make the example UB-free?
Suggested resolution: