cplusplus / CWG

Core Working Group
23 stars 7 forks source link

[expr.const] p8 unspecified object vs. usable in constant expressions #340

Open xmh0511 opened 1 year ago

xmh0511 commented 1 year ago

Full name of submitter (unless configured in github; will be published with the issue): Jim X

[expr.const] p8 says

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.

With this definition, when checking [expr.const] p5.9

an lvalue-to-rvalue conversion unless it is applied to

  • a non-volatile glvalue that refers to an object that is usable in constant expressions, or
  • a non-volatile glvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of E;

The definition clearly says the lifetime of the unspecified object does not begin within the evaluation of E, instead, it includes the evaluation of E, hence the second bullet is not satisfied. However, the wording "unspecified object" does not clear say whether the object is usable in constant expression or not because it is unspecified. Consider this example

int main(){
   int a = 0;
   int& rf = a;
   constexpr int v = rf;  // #1
}

The id-expression rf refers to a reference that is the kind of one in [expr.const] p8, so it is treated as if it is bound to an unspecified object, so whether #1 is a well-defined constant expression or not is unspecified? Is this the intent here?

Suggested Resolution

We may want to say

the reference is treated as binding to an unspecified object of the referenced type that is not usable in constant expressions and whose lifetime and that of all subobjects includes the entire constant evaluation and whose dynamic type is constexpr-unknown.

frederick-vs-ja commented 7 months ago

There're possibly some other unclear properties of unspecified objects.

GCC currently accepts this example (Godbolt link), while it seems totally unclear whether p + n is a constant subexpression when p points to an unspecfied object.

void fun(int& ref) {
  static_assert(((42 + &ref), true));
}

Possibly related to a yet-to-report issue in P2280R4.