================
@@ -177,3 +177,50 @@ namespace extern_reference_used_as_unknown {
   int y;
   constinit int& g = (x,y); // expected-warning {{left operand of comma 
operator has no effect}}
 }
+
+namespace uninit_reference_used {
+  int y;
+  constexpr int &r = r; // expected-error {{must be initialized by a constant 
expression}} \
+  // nointerpreter-note {{initializer of 'r' is not a constant expression}} \
+  // nointerpreter-note {{declared here}}
+  constexpr int &rr = (rr, y);
+  constexpr int &g() {
+    int &x = x; // expected-warning {{reference 'x' is not yet bound to a 
value when used within its own initialization}} \
+    // nointerpreter-note {{declared here}} \
+    // interpreter-note {{read of uninitialized object is not allowed in a 
constant expression}}
+    return x;
+  }
+  constexpr int &gg = g(); // expected-error {{must be initialized by a 
constant expression}} \
+  // nointerpreter-note {{reference to 'x' is not a constant expression}} \
+  // interpreter-note {{in call to 'g()'}}
+  constexpr int g2() {
+    int &x = x; // expected-warning {{reference 'x' is not yet bound to a 
value when used within its own initialization}} \
+    // interpreter-note {{read of uninitialized object is not allowed in a 
constant expression}}
+    return x;
+  }
+  constexpr int gg2 = g2(); // expected-error {{must be initialized by a 
constant expression}} \
+  // interpreter-note {{in call to 'g2()'}}
+  constexpr int &g3() {
+    int &x = (x,y); // expected-warning{{left operand of comma operator has no 
effect}} \
+    // expected-warning {{reference 'x' is not yet bound to a value when used 
within its own initialization}}
+    return x;
+  }
+  constexpr int &gg3 = g3();
+  typedef decltype(sizeof(1)) uintptr_t;
+  constexpr uintptr_t g4() {
+    uintptr_t * &x = x; // expected-warning {{reference 'x' is not yet bound 
to a value when used within its own initialization}} \
+    // interpreter-note {{read of uninitialized object is not allowed in a 
constant expression}}
+    *(uintptr_t*)x = 10;
+    return 3;
+  }
+  constexpr uintptr_t gg4 = g4(); // expected-error {{must be initialized by a 
constant expression}} \
+  // interpreter-note {{in call to 'g4()'}}
+  constexpr int g5() {
+    int &x = x; // expected-warning {{reference 'x' is not yet bound to a 
value when used within its own initialization}} \
+    // interpreter-note {{read of uninitialized object is not allowed in a 
constant expression}}
+    return 3;
+  }
+  constexpr uintptr_t gg5 = g5(); // interpreter-error {{must be initialized 
by a constant expression}} \
+  // interpreter-note {{in call to 'g5()'}}
----------------
t3nsor wrote:

I think it would be extremely strange if the intent of the standard were to not 
allow this case to be diagnosed. Going by the literal wording, yes, you have an 
id-expression that refers to a reference whose lifetime didn't begin within the 
constant evaluation (because it hasn't begun at all), which makes it an unknown 
reference, but in reality we know exactly what's happening here. It seems like 
the standard may have a defect and the rule for references really should be 
that the reference is unknown only if its *initialization* didn't begin within 
the evaluation of E.

https://github.com/llvm/llvm-project/pull/132990
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to