Timm =?utf-8?q?Bäder?= <tbae...@redhat.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/100...@github.com>


https://github.com/tbaederr updated 
https://github.com/llvm/llvm-project/pull/100062

>From 18a4a08009ecd8e5a557d77028fc4efdbf5901ce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com>
Date: Tue, 23 Jul 2024 07:02:23 +0200
Subject: [PATCH 1/2] [clang][ExprConst] Allow non-literal types in C++23

Instead of diagnosing non-literal types in C++23, allow them
and later diagnose them differently, e.g. because they have a
non-constexpr constructor, destructor, etc.
---
 clang/lib/AST/ExprConstant.cpp                 |  3 +++
 clang/test/CXX/drs/cwg18xx.cpp                 | 12 ++++++++----
 .../test/SemaCXX/constant-expression-cxx11.cpp | 18 +++++++++++-------
 .../test/SemaCXX/constant-expression-cxx2b.cpp | 10 +++++-----
 clang/test/SemaCXX/cxx23-invalid-constexpr.cpp | 13 ++++++-------
 5 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 5af712dd7257b..a402e6f204aaf 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2404,6 +2404,9 @@ static bool CheckLiteralType(EvalInfo &Info, const Expr 
*E,
   if (!E->isPRValue() || E->getType()->isLiteralType(Info.Ctx))
     return true;
 
+  if (Info.getLangOpts().CPlusPlus23)
+    return true;
+
   // C++1y: A constant initializer for an object o [...] may also invoke
   // constexpr constructors for o and its subobjects even if those objects
   // are of non-literal class types.
diff --git a/clang/test/CXX/drs/cwg18xx.cpp b/clang/test/CXX/drs/cwg18xx.cpp
index 323e56f9c5278..adfdb738e81c9 100644
--- a/clang/test/CXX/drs/cwg18xx.cpp
+++ b/clang/test/CXX/drs/cwg18xx.cpp
@@ -3,8 +3,8 @@
 // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s 
-verify=expected,since-cxx14,cxx98-14,cxx11-17,since-cxx11,since-cxx14 
-fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
 // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s 
-verify=expected,since-cxx14,since-cxx17,cxx11-17,since-cxx11,since-cxx14,cxx17 
-fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
 // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s 
-verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx11,since-cxx14 
-fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s 
-verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx11,since-cxx14 
-fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s 
-verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx11,since-cxx14 
-fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s 
-verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx23,since-cxx11,since-cxx14
 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s 
-verify=expected,since-cxx14,since-cxx17,since-cxx20,since-cxx23,since-cxx11,since-cxx14
 -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
 
 #if __cplusplus == 199711L
 #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
@@ -480,8 +480,12 @@ namespace cwg1872 { // cwg1872: 9
   static_assert(y == 0);
 #endif
   constexpr int z = A<Z>().f();
-  // since-cxx11-error@-1 {{constexpr variable 'z' must be initialized by a 
constant expression}}
-  //   since-cxx11-note@-2 {{non-literal type 'A<Z>' cannot be used in a 
constant expression}}
+  // since-cxx11-error@-1 {{constexpr variable 'z' must be initialized by a 
constant expression}}a
+#if __cplusplus < 202302L
+  //   since-cxx11-note@-3 {{non-literal type 'A<Z>' cannot be used in a 
constant expression}}
+#else
+  //   since-cxx23-note@-5 {{cannot construct object of type 'A<cwg1872::Z>' 
with virtual base class in a constant expression}}
+#endif
 #endif
 }
 
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp 
b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index efb391ba0922d..6df8a4740d6cc 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -std=c++23 -isystem %S/Inputs -fsyntax-only 
-verify=expected,cxx20_23,cxx23    -triple x86_64-linux -Wno-string-plus-int 
-Wno-pointer-arith -Wno-zero-length-array -Wno-c99-designator -fcxx-exceptions 
-pedantic %s -Wno-comment -Wno-tautological-pointer-compare -Wno-bool-conversion
-// RUN: %clang_cc1 -std=c++20 -isystem %S/Inputs -fsyntax-only 
-verify=expected,cxx11_20,cxx20_23 -triple x86_64-linux -Wno-string-plus-int 
-Wno-pointer-arith -Wno-zero-length-array -Wno-c99-designator -fcxx-exceptions 
-pedantic %s -Wno-comment -Wno-tautological-pointer-compare -Wno-bool-conversion
-// RUN: %clang_cc1 -std=c++11 -isystem %S/Inputs -fsyntax-only 
-verify=expected,cxx11_20,cxx11    -triple x86_64-linux -Wno-string-plus-int 
-Wno-pointer-arith -Wno-zero-length-array -Wno-c99-designator -fcxx-exceptions 
-pedantic %s -Wno-comment -Wno-tautological-pointer-compare -Wno-bool-conversion
+// RUN: %clang_cc1 -std=c++23 -isystem %S/Inputs -fsyntax-only 
-verify=expected,cxx20_23,cxx23              -triple x86_64-linux 
-Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array 
-Wno-c99-designator -fcxx-exceptions -pedantic %s -Wno-comment 
-Wno-tautological-pointer-compare -Wno-bool-conversion
+// RUN: %clang_cc1 -std=c++20 -isystem %S/Inputs -fsyntax-only 
-verify=expected,cxx11_20,cxx20_23,pre-cxx23 -triple x86_64-linux 
-Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array 
-Wno-c99-designator -fcxx-exceptions -pedantic %s -Wno-comment 
-Wno-tautological-pointer-compare -Wno-bool-conversion
+// RUN: %clang_cc1 -std=c++11 -isystem %S/Inputs -fsyntax-only 
-verify=expected,cxx11_20,cxx11,pre-cxx23    -triple x86_64-linux 
-Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array 
-Wno-c99-designator -fcxx-exceptions -pedantic %s -Wno-comment 
-Wno-tautological-pointer-compare -Wno-bool-conversion
 
 namespace StaticAssertFoldTest {
 
@@ -1011,10 +1011,12 @@ constexpr bool b(int n) { return &n; }
 static_assert(b(0), "");
 
 struct NonLiteral {
-  NonLiteral();
+  NonLiteral(); // cxx23-note {{declared here}}
   int f();
 };
-constexpr int k = NonLiteral().f(); // expected-error {{constant expression}} 
expected-note {{non-literal type 'NonLiteral'}}
+constexpr int k = NonLiteral().f(); // expected-error {{constant expression}} \
+                                   // pre-cxx23-note {{non-literal type 
'NonLiteral'}} \
+                                   // cxx23-note {{non-constexpr constructor 
'NonLiteral' cannot be used in a constant expression}}
 
 }
 
@@ -1270,8 +1272,10 @@ static_assert(makeComplexWrap(1,0) != complex(0, 1), "");
 
 namespace PR11595 {
   struct A { constexpr bool operator==(int x) const { return true; } };
-  struct B { B(); A& x; };
-  static_assert(B().x == 3, "");  // expected-error {{constant expression}} 
expected-note {{non-literal type 'B' cannot be used in a constant expression}}
+  struct B { B(); A& x; }; // cxx23-note {{declared here}}
+  static_assert(B().x == 3, "");  // expected-error {{constant expression}} \
+                                 // pre-cxx23-note {{non-literal type 'B' 
cannot be used in a constant expression}} \
+                                 // cxx23-note {{non-constexpr constructor 'B' 
cannot be used in a constant expression}}
 
   constexpr bool f(int k) { // cxx11_20-error {{constexpr function never 
produces a constant expression}}
     return B().x == k; // cxx11_20-note {{non-literal type 'B' cannot be used 
in a constant expression}}
diff --git a/clang/test/SemaCXX/constant-expression-cxx2b.cpp 
b/clang/test/SemaCXX/constant-expression-cxx2b.cpp
index 2519839b7ac57..42b3f81cc713d 100644
--- a/clang/test/SemaCXX/constant-expression-cxx2b.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx2b.cpp
@@ -3,7 +3,7 @@
 
 struct NonLiteral { // cxx2a-note {{'NonLiteral' is not literal}} \
                     // cxx23-note 2{{'NonLiteral' is not literal}}
-  NonLiteral() {}
+  NonLiteral() {} // cxx23-note 2{{declared here}}
 };
 
 struct Constexpr{};
@@ -165,9 +165,9 @@ int test_in_lambdas() {
 
   auto non_literal = [](bool b) constexpr {
     if (!b)
-      NonLiteral n; // cxx23-note {{non-literal type 'NonLiteral' cannot be 
used in a constant expression}} \
-                    // cxx2a-error {{variable of non-literal type 'NonLiteral' 
cannot be defined in a constexpr function before C++23}} \
-                    // cxx23-warning {{definition of a variable of non-literal 
type in a constexpr function is incompatible with C++ standards before C++23}}
+      NonLiteral n; // cxx2a-error {{variable of non-literal type 'NonLiteral' 
cannot be defined in a constexpr function before C++23}} \
+                    // cxx23-warning {{definition of a variable of non-literal 
type in a constexpr function is incompatible with C++ standards before C++23}} \
+                   // cxx23-note {{non-constexpr constructor 'NonLiteral' 
cannot be used in a constant expression}}
     return 0;
   };
 
@@ -217,7 +217,7 @@ int test_lambdas_implicitly_constexpr() {
 
   auto non_literal = [](bool b) { // cxx2a-note 2{{declared here}}
     if (b)
-      NonLiteral n; // cxx23-note {{non-literal type 'NonLiteral' cannot be 
used in a constant expression}}
+      NonLiteral n; // cxx23-note {{non-constexpr constructor 'NonLiteral' 
cannot be used in a constant expression}}
     return 0;
   };
 
diff --git a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp 
b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
index 4dc16c59d8058..3229a91fbcefb 100644
--- a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
+++ b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
@@ -25,14 +25,14 @@ constexpr int FT(T N) {
 class NonLiteral { // expected-note {{'NonLiteral' is not literal because it 
is not an aggregate and has no constexpr constructors}}
 public:
   NonLiteral() {}
-  ~NonLiteral() {}
+  ~NonLiteral() {} // expected-note {{declared here}}
 };
 
 constexpr NonLiteral F1() {
   return NonLiteral{};
 }
 
-constexpr int F2(NonLiteral N) {
+constexpr int F2(NonLiteral N) { // expected-note {{non-constexpr function 
'~NonLiteral' cannot be used in a constant expression}}
   return 8;
 }
 
@@ -46,7 +46,7 @@ class Derived1 : public NonLiteral {
 
 
 struct X {
-  X();
+  X(); // expected-note 2{{declared here}}
   X(const X&);
   X(X&&);
   X& operator=(X&);
@@ -80,7 +80,7 @@ struct WrapperNonT {
 };
 
 struct NonDefaultMembers {
-  constexpr NonDefaultMembers() {}; // expected-note {{non-literal type 'X' 
cannot be used in a constant expression}}
+  constexpr NonDefaultMembers() {}; // expected-note 2{{non-constexpr 
constructor 'X' cannot be used in a constant expression}}
   constexpr NonDefaultMembers(NonDefaultMembers const&) {};
   constexpr NonDefaultMembers(NonDefaultMembers &&) {};
   constexpr NonDefaultMembers& operator=(NonDefaultMembers &other) {this->t = 
other.t; return *this;}
@@ -109,7 +109,6 @@ void test() {
   F1();
   NonLiteral L;
   constexpr auto D = F2(L); // expected-error {{constexpr variable 'D' must be 
initialized by a constant expression}}
-                            // expected-note@-1 {{non-literal type 
'NonLiteral' cannot be used in a constant expression}}
 
   constexpr auto E = FT(1); // expected-error {{constexpr variable 'E' must be 
initialized by a constant expression}}
                             // expected-note@-1 {{in call}}
@@ -125,8 +124,8 @@ void test() {
 
   static_assert((NonDefaultMembers(), true),""); // expected-error{{expression 
is not an integral constant expression}} \
                                                  // expected-note {{in call 
to}}
-  constexpr bool FFF = (NonDefaultMembers() == NonDefaultMembers()); // 
expected-error{{must be initialized by a constant expression}} \
-                                                                     // 
expected-note{{non-literal}}
+  constexpr bool FFF = (NonDefaultMembers() == NonDefaultMembers()); // 
expected-error {{must be initialized by a constant expression}} \
+                                                                    // 
expected-note {{in call to 'NonDefaultMembers()'}}
 }
 
 struct A {

>From f55d060fa24f05b6f1fd97cfb4702a146d66618c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com>
Date: Tue, 23 Jul 2024 10:58:35 +0200
Subject: [PATCH 2/2] Address review comments

---
 clang/docs/ReleaseNotes.rst    | 2 ++
 clang/lib/AST/ExprConstant.cpp | 5 +++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8e24087b3dcdb..a8a033160df7b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -269,6 +269,8 @@ C++23 Feature Support
 - Implemented `P2797R0: Static and explicit object member functions with the 
same parameter-type-lists <https://wg21.link/P2797R0>`_.
   This completes the support for "deducing this".
 
+- Removed the restriction to literal types in constexpr functions in C++23 
mode.
+
 C++2c Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index a402e6f204aaf..b87a21c55eba9 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2401,10 +2401,11 @@ static bool 
CheckMemberPointerConstantExpression(EvalInfo &Info,
 /// produce an appropriate diagnostic.
 static bool CheckLiteralType(EvalInfo &Info, const Expr *E,
                              const LValue *This = nullptr) {
-  if (!E->isPRValue() || E->getType()->isLiteralType(Info.Ctx))
+  // The restriction to literal types does not exist in C++23 anymore.
+  if (Info.getLangOpts().CPlusPlus23)
     return true;
 
-  if (Info.getLangOpts().CPlusPlus23)
+  if (!E->isPRValue() || E->getType()->isLiteralType(Info.Ctx))
     return true;
 
   // C++1y: A constant initializer for an object o [...] may also invoke

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to