diff options
author | Jakub Jelinek <jakub@redhat.com> | 2022-11-19 09:26:44 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2022-11-19 09:26:44 +0100 |
commit | 32d16fe9d7e347bc58e7fad316ed7923e1d0f65c (patch) | |
tree | e590f605c52120dec6d2d39361ca7c02c9c883f4 | |
parent | 2efb237ffc68ec9bb17982434f5941bfa14f8b50 (diff) | |
download | gcc-32d16fe9d7e347bc58e7fad316ed7923e1d0f65c.zip gcc-32d16fe9d7e347bc58e7fad316ed7923e1d0f65c.tar.gz gcc-32d16fe9d7e347bc58e7fad316ed7923e1d0f65c.tar.bz2 |
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 <jakub@redhat.com>
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.
-rw-r--r-- | gcc/c-family/c-cppbuiltin.cc | 2 | ||||
-rw-r--r-- | gcc/cp/constexpr.cc | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C | 49 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/stmtexpr19.C | 2 | ||||
-rw-r--r-- | 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 fb11d87..333f3e1 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 ad43897..0b43ae4 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 0000000..a4c78bb --- /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 0000000..8e230ef --- /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 3ce36e4..6f4f6bc 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 0c19a21..be395b6 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 0000000..79c40fc --- /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(){} |