[Clang] Fix consteval propagation for aggregates and defaulted constructors

This patch does a few things:

* Fix aggregate initialization.
  When an aggregate has an initializer that is immediate-escalating,
  the context in which it is used automatically becomes an immediate function.
  The wording does that by rpretending an aggregate initialization is itself
  an invocation which is not really how clang works, so my previous attempt
  was... wrong.

* Fix initialization of defaulted constructors with immediate escalating
  default member initializers.
  The wording was silent about that case and I did not handled it fully
  https://cplusplus.github.io/CWG/issues/2760.html

* Fix diagnostics
  In some cases clang would produce additional and unhelpful
  diagnostics by listing the invalid references to consteval
  function that appear in immediate escalating functions

Fixes https://github.com/llvm/llvm-project/issues/63742

Reviewed By: aaron.ballman, #clang-language-wg, Fznamznon

Differential Revision: https://reviews.llvm.org/D155175
diff --git a/clang/test/SemaCXX/cxx2a-consteval-default-params.cpp b/clang/test/SemaCXX/cxx2a-consteval-default-params.cpp
index da8315a..be8f7cc 100644
--- a/clang/test/SemaCXX/cxx2a-consteval-default-params.cpp
+++ b/clang/test/SemaCXX/cxx2a-consteval-default-params.cpp
@@ -41,19 +41,21 @@
     }();
 };
 
-consteval int ub(int n) { // expected-note {{declared here}}
+consteval int ub(int n) {
     return 0/n;
 }
 
-struct InitWithLambda {
-    int b = [](int error = undefined()) { // expected-error {{cannot take address of consteval function 'undefined' outside of an immediate invocation}}
+struct InitWithLambda { // expected-note {{'InitWithLambda' is an immediate constructor because the default initializer of 'b' contains a call to a consteval function 'undefined' and that call is not a constant expression}}
+    int b = [](int error = undefined()) {  // expected-note {{undefined function 'undefined' cannot be used in a constant expression}}
         return error;
     }();
-    int c = [](int error = sizeof(undefined()) + ub(0)) { // expected-error {{cannot take address of consteval function 'ub' outside of an immediate invocation}}
+    int c = [](int error = sizeof(undefined()) + ub(0)) {
 
         return error;
     }();
 } i;
+// expected-error@-1 {{call to immediate function 'InitWithLambda::InitWithLambda' is not a constant expression}} \
+   expected-note@-1 {{in call to 'InitWithLambda()'}}
 
 namespace ShouldNotCrash {
     template<typename T>
diff --git a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
index 5e149dd..333b98d 100644
--- a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
+++ b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -std=c++2a -emit-llvm-only -Wno-unused-value %s -verify
-// RUN: %clang_cc1 -std=c++2b -emit-llvm-only -Wno-unused-value %s -verify
+// RUN: %clang_cc1 -std=c++2a -Wno-unused-value %s -verify
+// RUN: %clang_cc1 -std=c++2b -Wno-unused-value %s -verify
 
 consteval int id(int i) { return i; }
 constexpr char id(char c) { return c; }
@@ -34,7 +34,7 @@
 
 template <typename T>
 constexpr T h(T t = id(x)) { // expected-note {{read of non-const variable 'x' is not allowed in a constant expression}} \
-                             // expected-note 2{{'hh<int>' is an immediate function because its body contains a call to a consteval function 'id' and that call is not a constant expression}}
+                             // expected-note {{'hh<int>' is an immediate function because its body contains a call to a consteval function 'id' and that call is not a constant expression}}
     return t;
 }
 
@@ -164,3 +164,169 @@
 int i = g(x); // expected-error {{call to immediate function 'ConstevalConstructor::g<int>' is not a constant expression}} \
               // expected-note {{read of non-const variable 'x' is not allowed in a constant expression}}
 }
+
+
+
+namespace Aggregate {
+consteval int f(int); // expected-note {{declared here}}
+struct S {
+  int x = f(42); // expected-note {{undefined function 'f' cannot be used in a constant expression}} \
+                 // expected-note {{'immediate<int>' is an immediate function because its body contains a call to a consteval function 'f' and that call is not a constant expression}}
+};
+
+constexpr S immediate(auto) {
+    return S{};
+}
+
+void test_runtime() {
+    (void)immediate(0); // expected-error {{call to immediate function 'Aggregate::immediate<int>' is not a constant expression}} \
+                        // expected-note {{in call to 'immediate(0)'}}
+}
+consteval int f(int i) {
+    return i;
+}
+consteval void test() {
+    constexpr S s = immediate(0);
+    static_assert(s.x == 42);
+}
+}
+
+
+
+namespace GH63742 {
+void side_effect(); // expected-note  {{declared here}}
+consteval int f(int x) {
+    if (!x) side_effect(); // expected-note {{non-constexpr function 'side_effect' cannot be used in a constant expression}}
+    return x;
+}
+struct SS {
+  int y = f(1); // Ok
+  int x = f(0); // expected-error {{call to consteval function 'GH63742::f' is not a constant expression}} \
+                // expected-note  {{declared here}} \
+                // expected-note  {{in call to 'f(0)'}}
+  SS();
+};
+SS::SS(){} // expected-note {{in the default initializer of 'x'}}
+
+consteval int f2(int x) {
+    if (!__builtin_is_constant_evaluated()) side_effect();
+    return x;
+}
+struct S2 {
+    int x = f2(0);
+    constexpr S2();
+};
+
+constexpr S2::S2(){}
+S2 s = {};
+constinit S2 s2 = {};
+
+struct S3 {
+    int x = f2(0);
+    S3();
+};
+S3::S3(){}
+
+}
+
+namespace Defaulted {
+consteval int f(int x);
+struct SS {
+  int x = f(0);
+  SS() = default;
+};
+}
+
+namespace DefaultedUse{
+consteval int f(int x);  // expected-note {{declared here}}
+struct SS {
+  int a = sizeof(f(0)); // Ok
+  int x = f(0); // expected-note {{undefined function 'f' cannot be used in a constant expression}}
+
+  SS() = default; // expected-note {{'SS' is an immediate constructor because the default initializer of 'x' contains a call to a consteval function 'f' and that call is not a constant expression}}
+};
+
+void test() {
+    [[maybe_unused]] SS s; // expected-error {{call to immediate function 'DefaultedUse::SS::SS' is not a constant expression}} \
+                           //  expected-note {{in call to 'SS()'}}
+}
+}
+
+namespace UserDefinedConstructors {
+consteval int f(int x) {
+    return x;
+}
+extern int NonConst; // expected-note 2{{declared here}}
+
+struct ConstevalCtr {
+    int y;
+    int x = f(y);
+    consteval ConstevalCtr(int yy)
+    : y(f(yy)) {}
+};
+
+ConstevalCtr c1(1);
+ConstevalCtr c2(NonConst);
+// expected-error@-1 {{call to consteval function 'UserDefinedConstructors::ConstevalCtr::ConstevalCtr' is not a constant expression}} \
+// expected-note@-1 {{read of non-const variable 'NonConst' is not allowed in a constant expression}}
+
+struct ImmediateEscalating {
+    int y;
+    int x = f(y);
+    template<typename T>
+    constexpr ImmediateEscalating(T yy) // expected-note {{ImmediateEscalating<int>' is an immediate constructor because the initializer of 'y' contains a call to a consteval function 'f' and that call is not a constant expression}}
+    : y(f(yy)) {}
+};
+
+ImmediateEscalating c3(1);
+ImmediateEscalating c4(NonConst);
+// expected-error@-1 {{call to immediate function 'UserDefinedConstructors::ImmediateEscalating::ImmediateEscalating<int>' is not a constant expression}} \
+// expected-note@-1 {{read of non-const variable 'NonConst' is not allowed in a constant expression}}
+
+
+struct NonEscalating {
+    int y;
+    int x = f(this->y); // expected-error {{call to consteval function 'UserDefinedConstructors::f' is not a constant expression}} \
+                        // expected-note  {{declared here}} \
+                        // expected-note  {{use of 'this' pointer is only allowed within the evaluation of a call to a 'constexpr' member function}}
+    constexpr NonEscalating(int yy) : y(yy) {} // expected-note {{in the default initializer of 'x'}}
+};
+NonEscalating s = {1};
+
+}
+
+namespace AggregateInit {
+
+consteval int f(int x) {
+    return x;
+}
+
+struct S {
+    int i;
+    int j = f(i);
+};
+
+constexpr S  test(auto) {
+    return {};
+}
+
+S s = test(0);
+
+}
+
+namespace GlobalAggregateInit {
+
+consteval int f(int x) {
+    return x;
+}
+
+struct S {
+    int i;
+    int j = f(i); // expected-error {{call to consteval function 'GlobalAggregateInit::f' is not a constant expression}} \
+                  // expected-note {{implicit use of 'this' pointer is only allowed within the evaluation of a call to a 'constexpr' member function}} \
+                  // expected-note {{declared here}}
+};
+
+S s(0); // expected-note {{in the default initializer of 'j'}}
+
+}