From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2153) id 3C1353858002; Sat, 19 Nov 2022 08:31:23 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3C1353858002 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1668846683; bh=/v8mhuDnqKUKh2KC536MHiYgdiPOqFWQ5ulP1N7WbZM=; h=From:To:Subject:Date:From; b=GCQhOQx9OOT4x4DLSsp9+8BEl/3oisiTEidBCJtMxm1gid8e4JR2ke8XJEu8DBow8 8/I9APrOFb+qlgi3uCEI+Dypb/B6b+sWPqKbJz8BHJSIBAecgmqJig+cPa2d6vzTy0 FoTAQg+iNz1mL/wZTaQLYuG1BcoMFJmiDTB1vnrA= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jakub Jelinek To: gcc-cvs@gcc.gnu.org Subject: [gcc r13-4161] c++: Implement C++23 P2647R1 - Permitting static constexpr variables in constexpr functions X-Act-Checkin: gcc X-Git-Author: Jakub Jelinek X-Git-Refname: refs/heads/master X-Git-Oldrev: 2efb237ffc68ec9bb17982434f5941bfa14f8b50 X-Git-Newrev: 32d16fe9d7e347bc58e7fad316ed7923e1d0f65c Message-Id: <20221119083123.3C1353858002@sourceware.org> Date: Sat, 19 Nov 2022 08:31:23 +0000 (GMT) List-Id: https://gcc.gnu.org/g:32d16fe9d7e347bc58e7fad316ed7923e1d0f65c commit r13-4161-g32d16fe9d7e347bc58e7fad316ed7923e1d0f65c Author: Jakub Jelinek Date: Sat Nov 19 09:26:44 2022 +0100 c++: Implement C++23 P2647R1 - Permitting static constexpr variables in constexpr functions The following patch implements this paper. Per further discussions it is implemented for C++23 only, so isn't treated as a DR, e.g. because the part of the standard the paper is changing didn't even exist in C++20. And we gave up on trying to implement it as a pedwarn rather than error for C++20 and older, because of implicit constexpr lambdas or -fimplicit-constexpr reasons. For C++20 and older, the only change is that passing through definitions of static or thread_local vars usable in constant expressions is now accepted in statement expressions if they aren't inside of constexpr or consteval functions. 2022-11-19 Jakub Jelinek gcc/c-family/ * c-cppbuiltin.cc (c_cpp_builtins): Bump __cpp_constexpr value from 202207L to 202211L. gcc/cp/ * constexpr.cc (cxx_eval_constant_expression): Implement C++23 P2647R1 - Permitting static constexpr variables in constexpr functions. Allow DECL_EXPRs of decl_constant_var_p static or thread_local vars. (potential_constant_expression_1): Similarly, except use decl_maybe_constant_var_p instead of decl_constant_var_p if processing_template_decl. gcc/testsuite/ * g++.dg/cpp23/constexpr-nonlit17.C: New test. * g++.dg/cpp23/constexpr-nonlit18.C: New test. * g++.dg/cpp23/feat-cxx2b.C: Adjust expected __cpp_constexpr value. * g++.dg/ext/stmtexpr19.C: Don't expect an error. * g++.dg/ext/stmtexpr25.C: New test. Diff: --- gcc/c-family/c-cppbuiltin.cc | 2 +- gcc/cp/constexpr.cc | 8 +++- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C | 12 ++++++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C | 49 +++++++++++++++++++++++++ gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C | 4 +- gcc/testsuite/g++.dg/ext/stmtexpr19.C | 2 +- gcc/testsuite/g++.dg/ext/stmtexpr25.C | 17 +++++++++ 7 files changed, 88 insertions(+), 6 deletions(-) diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc index fb11d8754c6..333f3e138d6 100644 --- a/gcc/c-family/c-cppbuiltin.cc +++ b/gcc/c-family/c-cppbuiltin.cc @@ -1074,7 +1074,7 @@ c_cpp_builtins (cpp_reader *pfile) /* Set feature test macros for C++23. */ cpp_define (pfile, "__cpp_size_t_suffix=202011L"); cpp_define (pfile, "__cpp_if_consteval=202106L"); - cpp_define (pfile, "__cpp_constexpr=202207L"); + cpp_define (pfile, "__cpp_constexpr=202211L"); cpp_define (pfile, "__cpp_multidimensional_subscript=202211L"); cpp_define (pfile, "__cpp_named_character_escapes=202207L"); cpp_define (pfile, "__cpp_static_call_operator=202207L"); diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index ad43897b076..0b43ae4ece3 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -7124,7 +7124,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, && (TREE_STATIC (r) || (CP_DECL_THREAD_LOCAL_P (r) && !DECL_REALLY_EXTERN (r))) /* Allow __FUNCTION__ etc. */ - && !DECL_ARTIFICIAL (r)) + && !DECL_ARTIFICIAL (r) + && !decl_constant_var_p (r)) { if (!ctx->quiet) { @@ -9630,7 +9631,10 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case DECL_EXPR: tmp = DECL_EXPR_DECL (t); - if (VAR_P (tmp) && !DECL_ARTIFICIAL (tmp)) + if (VAR_P (tmp) && !DECL_ARTIFICIAL (tmp) + && (processing_template_decl + ? !decl_maybe_constant_var_p (tmp) + : !decl_constant_var_p (tmp))) { if (CP_DECL_THREAD_LOCAL_P (tmp) && !DECL_REALLY_EXTERN (tmp)) { diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C new file mode 100644 index 00000000000..a4c78bb43ef --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C @@ -0,0 +1,12 @@ +// P2647R1 - Permitting static constexpr variables in constexpr functions +// { dg-do compile { target c++23 } } + +constexpr char +test () +{ + static const int x = 5; + static constexpr char c[] = "Hello World"; + return *(c + x); +} + +static_assert (test () == ' '); diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C new file mode 100644 index 00000000000..8e230ef3bc3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C @@ -0,0 +1,49 @@ +// P2647R1 - Permitting static constexpr variables in constexpr functions +// { dg-do compile { target c++14 } } + +constexpr int +f1 (int x) +{ + if (x) + throw 1; + return 0; +} + +constexpr int +f2 () +{ + static const int a = f1 (1); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int +f3 () +{ + static const int a = 5; // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int +f4 () // { dg-message "declared here" "" { target c++20_down } } +{ // { dg-message "is not usable as a 'constexpr' function because:" "" { target c++23 } .-1 } + static const int a = f1 (1); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; // { dg-error "'a' defined 'static' in 'constexpr' context" "" { target c++23 } .-1 } +} + +constexpr int a4 = f4 (); // { dg-error "called in a constant expression" } + +constexpr int +f5 () +{ + static const int a = f1 (0); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int +f6 () +{ + static const int a = f1 (0); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +constexpr int a6 = f6 (); // { dg-error "called in a constant expression" "" { target c++20_down } } diff --git a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C index 3ce36e45cb7..6f4f6bcaad0 100644 --- a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C +++ b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C @@ -134,8 +134,8 @@ #ifndef __cpp_constexpr # error "__cpp_constexpr" -#elif __cpp_constexpr != 202207 -# error "__cpp_constexpr != 202207" +#elif __cpp_constexpr != 202211 +# error "__cpp_constexpr != 202211" #endif #ifndef __cpp_decltype_auto diff --git a/gcc/testsuite/g++.dg/ext/stmtexpr19.C b/gcc/testsuite/g++.dg/ext/stmtexpr19.C index 0c19a210f70..be395b69065 100644 --- a/gcc/testsuite/g++.dg/ext/stmtexpr19.C +++ b/gcc/testsuite/g++.dg/ext/stmtexpr19.C @@ -8,7 +8,7 @@ const test* setup() { static constexpr test atest = { - ({ static const int inner = 123; &inner; }) // { dg-error "static" } + ({ static const int inner = 123; &inner; }) }; return &atest; diff --git a/gcc/testsuite/g++.dg/ext/stmtexpr25.C b/gcc/testsuite/g++.dg/ext/stmtexpr25.C new file mode 100644 index 00000000000..79c40fc61c4 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/stmtexpr25.C @@ -0,0 +1,17 @@ +// PR c++/81073 +// { dg-options "" } +// { dg-do compile { target c++11 } } + +struct test { const int *addr; }; + +const test* setup() +{ + static constexpr test atest = + { + ({ static const int inner = (throw 1, 1); &inner; }) // { dg-error "static" "" } + }; + + return &atest; +} + +int main(){}