cor3ntin updated this revision to Diff 478321. cor3ntin added a comment. Add an evaluation test.
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D138851/new/ https://reviews.llvm.org/D138851 Files: 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
Index: clang/www/cxx_status.html =================================================================== --- clang/www/cxx_status.html +++ clang/www/cxx_status.html @@ -1523,7 +1523,7 @@ <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> Index: clang/test/SemaCXX/constant-expression-cxx2b.cpp =================================================================== --- clang/test/SemaCXX/constant-expression-cxx2b.cpp +++ clang/test/SemaCXX/constant-expression-cxx2b.cpp @@ -6,6 +6,8 @@ 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 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 @@ // 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 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; // expected-warning {{before C++2b}} + static constexpr Constexpr s; // expected-warning {{before C++2b}} + return t.f() + s.f(); +} +static_assert(evaluate_static_constexpr() == 84); Index: clang/test/Lexer/cxx-features.cpp =================================================================== --- clang/test/Lexer/cxx-features.cpp +++ 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 Index: clang/lib/Frontend/InitPreprocessor.cpp =================================================================== --- clang/lib/Frontend/InitPreprocessor.cpp +++ clang/lib/Frontend/InitPreprocessor.cpp @@ -606,7 +606,7 @@ 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" Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -5049,8 +5049,10 @@ 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; Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -662,7 +662,8 @@ - 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 ----------------------------------
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits