[clang] 5607fc0 - [Clang] Permit static constexpr variables in constexpr functions

Corentin Jabot via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 28 12:38:38 PST 2022


Author: Corentin Jabot
Date: 2022-11-28T21:38:31+01:00
New Revision: 5607fc002dd43514a605ba1e83735e74340ec95d

URL: https://github.com/llvm/llvm-project/commit/5607fc002dd43514a605ba1e83735e74340ec95d
DIFF: https://github.com/llvm/llvm-project/commit/5607fc002dd43514a605ba1e83735e74340ec95d.diff

LOG: [Clang] Permit static constexpr variables in constexpr functions

This implement the C++23 paper P2647R1 (adopted in Kona)

Reviewed By: #clang-language-wg, erichkeane

Differential Revision: https://reviews.llvm.org/D138851

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/AST/ExprConstant.cpp
    clang/lib/Frontend/InitPreprocessor.cpp
    clang/test/Lexer/cxx-features.cpp
    clang/test/SemaCXX/constant-expression-cxx2b.cpp
    clang/www/cxx_status.html

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3dcd65e3b25e1..3f99bc2f7c939 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -662,7 +662,8 @@ C++2b Feature Support
 - Support label at end of compound statement (`P2324 <https://wg21.link/p2324r2>`_).
 - Implemented `P1169R4: static operator() <https://wg21.link/P1169R4>`_.
 - Implemented "char8_t Compatibility and Portability Fix" (`P2513R3 <https://wg21.link/P2513R3>`_).
-  This Change was applied to C++20 as a Defect Report.
+  This change was applied to C++20 as a Defect Report.
+- Implemented "Permitting static constexpr variables in constexpr functions" (`P2647R1 <https://wg21.link/P2647R1>_`).
 
 CUDA/HIP Language Changes in Clang
 ----------------------------------

diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index df8b420e55a6b..08130e03ff90b 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -5049,8 +5049,10 @@ static EvalStmtResult EvaluateSwitch(StmtResult &Result, EvalInfo &Info,
 static bool CheckLocalVariableDeclaration(EvalInfo &Info, const VarDecl *VD) {
   // An expression E is a core constant expression unless the evaluation of E
   // would evaluate one of the following: [C++2b] - a control flow that passes
-  // through a declaration of a variable with static or thread storage duration.
-  if (VD->isLocalVarDecl() && VD->isStaticLocal()) {
+  // through a declaration of a variable with static or thread storage duration
+  // unless that variable is usable in constant expressions.
+  if (VD->isLocalVarDecl() && VD->isStaticLocal() &&
+      !VD->isUsableInConstantExpressions(Info.Ctx)) {
     Info.CCEDiag(VD->getLocation(), diag::note_constexpr_static_local)
         << (VD->getTSCSpec() == TSCS_unspecified ? 0 : 1) << VD;
     return false;

diff  --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index bdff0bd04f290..53a5f13e24afe 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -606,7 +606,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
     Builder.defineMacro("__cpp_unicode_literals", "200710L");
     Builder.defineMacro("__cpp_user_defined_literals", "200809L");
     Builder.defineMacro("__cpp_lambdas", "200907L");
-    Builder.defineMacro("__cpp_constexpr", LangOpts.CPlusPlus2b   ? "202110L"
+    Builder.defineMacro("__cpp_constexpr", LangOpts.CPlusPlus2b   ? "202211L"
                                            : LangOpts.CPlusPlus20 ? "201907L"
                                            : LangOpts.CPlusPlus17 ? "201603L"
                                            : LangOpts.CPlusPlus14 ? "201304L"

diff  --git a/clang/test/Lexer/cxx-features.cpp b/clang/test/Lexer/cxx-features.cpp
index c12f2d20b66c1..e577801560292 100644
--- a/clang/test/Lexer/cxx-features.cpp
+++ b/clang/test/Lexer/cxx-features.cpp
@@ -297,7 +297,7 @@
 #error "wrong value for __cpp_lambdas"
 #endif
 
-#if check(constexpr, 0, 200704, 201304, 201603, 201907, 202110)
+#if check(constexpr, 0, 200704, 201304, 201603, 201907, 202211)
 #error "wrong value for __cpp_constexpr"
 #endif
 

diff  --git a/clang/test/SemaCXX/constant-expression-cxx2b.cpp b/clang/test/SemaCXX/constant-expression-cxx2b.cpp
index 5a5fe6c1b7ab2..e52dc1400f3d5 100644
--- a/clang/test/SemaCXX/constant-expression-cxx2b.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx2b.cpp
@@ -6,6 +6,8 @@ struct NonLiteral { // cxx2a-note {{'NonLiteral' is not literal}} \
   NonLiteral() {}
 };
 
+struct Constexpr{};
+
 #if __cplusplus > 202002L
 
 constexpr int f(int n) {  // expected-error {{constexpr function never produces a constant expression}}
@@ -82,15 +84,15 @@ constexpr int k_evaluated(int n) {
 constexpr int ke = k_evaluated(1); // expected-error {{constexpr variable 'ke' must be initialized by a constant expression}} \
                                    // expected-note {{in call}}
 
-constexpr int static_constexpr() { // expected-error {{constexpr function never produces a constant expression}}
-  static constexpr int m = 42;     // expected-note {{control flows through the definition of a static variable}} \
-                                   // cxx2b-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++2b}}
+constexpr int static_constexpr() {
+  static constexpr int m = 42;     // cxx2b-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++2b}}
+  static constexpr Constexpr foo; // cxx2b-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++2b}}
   return m;
 }
 
-constexpr int thread_local_constexpr() { // expected-error {{constexpr function never produces a constant expression}}
-  thread_local constexpr int m = 42;     // expected-note {{control flows through the definition of a thread_local variable}} \
-                                         // cxx2b-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++2b}}
+constexpr int thread_local_constexpr() {
+  thread_local constexpr int m = 42; // cxx2b-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++2b}}
+  thread_local constexpr Constexpr foo; // cxx2b-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++2b}}
   return m;
 }
 
@@ -135,9 +137,8 @@ constexpr int d = label();
 // Test that explicitly constexpr lambdas behave correctly,
 // This is to be contrasted with the test for implicitly constexpr lambdas below.
 int test_in_lambdas() {
-  auto a = []() constexpr {  // expected-error{{constexpr function never produces a constant expression}}
-    static const int m = 32; // expected-note {{control flows through the definition of a static variable}} \
-                             // cxx2b-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++2b}}
+  auto a = []() constexpr {
+    static const int m = 32; // cxx2b-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++2b}}
     return m;
   };
 
@@ -240,3 +241,16 @@ constexpr auto dependent_var_def_lambda() {
 constexpr auto non_literal_valid_in_cxx2b = dependent_var_def_lambda<NonLiteral>()(true); // \
     // cxx2a-error {{constexpr variable 'non_literal_valid_in_cxx2b' must be initialized by a constant expression}} \
     // cxx2a-note {{non-constexpr function}}
+
+
+constexpr double evaluate_static_constexpr() {
+  struct Constexpr{
+    constexpr double f() const {
+      return 42;
+    }
+  };
+  thread_local constexpr Constexpr t; // cxx2b-warning {{before C++2b}}
+  static constexpr Constexpr s; // cxx2b-warning {{before C++2b}}
+  return t.f() + s.f();
+}
+static_assert(evaluate_static_constexpr() == 84);

diff  --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index e3b75654d515c..e296d5d3c597c 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -1523,7 +1523,7 @@ <h2 id="cxx23">C++2b implementation status</h2>
     <tr>
       <td>Permitting static constexpr variables in constexpr functions (DR)</td>
       <td><a href="https://wg21.link/P2647R1">P2647R1</a></td>
-      <td class="none" align="center">No</td>
+      <td class="unreleased" align="center">Clang 16</td>
     </tr>
     <tr>
       <td>consteval needs to propagate up (DR)</td>


        


More information about the cfe-commits mailing list