Re: [PATCH] c++: Implement C++23 P2242R3 - Non-literal variables (and labels and gotos) in constexpr functions
On 10/5/21 08:39, Jakub Jelinek wrote: Hi! The following patch implements C++23 P2242R3 - Non-literal variables (and labels and gotos) in constexpr functions. I think it is mostly straightforward, don't diagnose certain statements/declarations just because of their presence in constexpr/consteval functions, but (except for the non-literal type var declarations which ought to be caught by e.g. constructor or destructor call during evaluation not being constexpr and for labels which are now always allowed) diagnose it during constexpr evaluation. The only unclear thing to me is "a control flow that passes through a declaration". The patch implements diagnostics when encountering a DECL_EXPR for such variables. But because constexpr/consteval functions support switch statements, another thing that can happen is jump over such a declaration. Consider e.g. following testcase (not included in the patch). When evaluating foo (12) or bar (12) the patch accepts those as constant expressions, eventhough it jumps across such declarations. For baz (12) and corge (12) it rejects them not because of jumping across such declarations, but because those static or thread_local variables aren't initialized with constant expressions and are accessed. If baz/corge is modified not to have const keyword, they are rejected because the vars aren't aren't const. If they have const keyword and are initialized by constant expression, accesses to those vars are accepted. Is that ok? That seems correct to me. If they have static initialization, they are initialized. Some comments in the patch below. So far regtested with GXX_TESTSUITE_STDS=98,11,14,17,20,2b make -j32 -k check-g++ ok for trunk if it passes full bootstrap/regtest? // { dg-do compile } // { dg-options "-std=c++2b" } int qux (); constexpr int foo (int x) { switch (x) { static int bar = qux (); case 12: return 1; } return 0; } constexpr int bar (int x) { switch (x) { thread_local int bar = qux (); case 12: return 1; } return 0; } constexpr int baz (int x) { switch (x) { static const int bar = qux (); // { dg-message "'bar' was not initialized with a constant expression" } case 12: return bar; } return 0; } constexpr int corge (int x) { switch (x) { const thread_local int bar = qux (); // { dg-message "'bar' was not initialized with a constant expression" } case 12: return bar; } return 0; } constexpr int a = foo (12); constexpr int b = bar (12); constexpr int c = baz (12); // { dg-error "the value of 'bar' is not usable in a constant expression" } constexpr int d = corge (12); // { dg-error "the value of 'bar' is not usable in a constant expression" } 2021-10-05 Jakub Jelinek gcc/c-family/ * c-cppbuiltin.c (c_cpp_builtins): For -std=c++23 predefine __cpp_constexpr to 202103L rather than 201907L. gcc/cp/ * parser.c (cp_parser_jump_statement): Implement C++23 P2242R3. Allow goto expressions in constexpr function bodies for C++23. Adjust error message for older standards to mention it. * decl.c (start_decl): Allow static and thread_local declarations in constexpr function bodies for C++23. Adjust error message for older standards to mention it. * constexpr.c (ensure_literal_type_for_constexpr_object): Allow declarations of variables with non-literal type in constexpr function bodies for C++23. Adjust error message for older standards to mention it. (cxx_eval_constant_expression) : Diagnose declarations of initialization of static or thread_local vars. (cxx_eval_constant_expression) : Diagnose goto statements for C++23. (potential_constant_expression_1) : Allow declarations of static and thread_local vars for C++23. (potential_constant_expression_1) : Allow labels for C++23. gcc/testsuite/ * g++.dg/cpp23/feat-cxx2b.C: Expect __cpp_constexpr 202103L rather than 201907L. * g++.dg/cpp23/constexpr-nonlit1.C: New test. * g++.dg/cpp23/constexpr-nonlit2.C: New test. * g++.dg/cpp23/constexpr-nonlit3.C: New test. * g++.dg/diagnostic/constexpr1.C: Only expect some diagnostics for c++20_down. * g++.dg/cpp1y/constexpr-label.C: Likewise. * g++.dg/cpp1y/constexpr-neg1.C: Likewise. * g++.dg/cpp2a/constexpr-try5.C: Likewise. Adjust some expected wording. * g++.dg/cpp2a/constexpr-dtor3.C: Likewise. * g++.dg/cpp2a/consteval3.C: Likewise. Add effective target c++20 and remove dg-options. --- gcc/c-family/c-cppbuiltin.c.jj 2021-09-21 23:31:01.016248936 +0200 +++ gcc/c-family/c-cppbuiltin.c 2021-10-05 12:54:29.898321379 +0200 @@ -1052,7 +1052,8 @@ c_cpp_builtins (cpp_reader *pfile) cpp_define (pfile,
[PATCH] c++: Implement C++23 P2242R3 - Non-literal variables (and labels and gotos) in constexpr functions
Hi! The following patch implements C++23 P2242R3 - Non-literal variables (and labels and gotos) in constexpr functions. I think it is mostly straightforward, don't diagnose certain statements/declarations just because of their presence in constexpr/consteval functions, but (except for the non-literal type var declarations which ought to be caught by e.g. constructor or destructor call during evaluation not being constexpr and for labels which are now always allowed) diagnose it during constexpr evaluation. The only unclear thing to me is "a control flow that passes through a declaration". The patch implements diagnostics when encountering a DECL_EXPR for such variables. But because constexpr/consteval functions support switch statements, another thing that can happen is jump over such a declaration. Consider e.g. following testcase (not included in the patch). When evaluating foo (12) or bar (12) the patch accepts those as constant expressions, eventhough it jumps across such declarations. For baz (12) and corge (12) it rejects them not because of jumping across such declarations, but because those static or thread_local variables aren't initialized with constant expressions and are accessed. If baz/corge is modified not to have const keyword, they are rejected because the vars aren't aren't const. If they have const keyword and are initialized by constant expression, accesses to those vars are accepted. Is that ok? So far regtested with GXX_TESTSUITE_STDS=98,11,14,17,20,2b make -j32 -k check-g++ ok for trunk if it passes full bootstrap/regtest? // { dg-do compile } // { dg-options "-std=c++2b" } int qux (); constexpr int foo (int x) { switch (x) { static int bar = qux (); case 12: return 1; } return 0; } constexpr int bar (int x) { switch (x) { thread_local int bar = qux (); case 12: return 1; } return 0; } constexpr int baz (int x) { switch (x) { static const int bar = qux ();// { dg-message "'bar' was not initialized with a constant expression" } case 12: return bar; } return 0; } constexpr int corge (int x) { switch (x) { const thread_local int bar = qux (); // { dg-message "'bar' was not initialized with a constant expression" } case 12: return bar; } return 0; } constexpr int a = foo (12); constexpr int b = bar (12); constexpr int c = baz (12); // { dg-error "the value of 'bar' is not usable in a constant expression" } constexpr int d = corge (12); // { dg-error "the value of 'bar' is not usable in a constant expression" } 2021-10-05 Jakub Jelinek gcc/c-family/ * c-cppbuiltin.c (c_cpp_builtins): For -std=c++23 predefine __cpp_constexpr to 202103L rather than 201907L. gcc/cp/ * parser.c (cp_parser_jump_statement): Implement C++23 P2242R3. Allow goto expressions in constexpr function bodies for C++23. Adjust error message for older standards to mention it. * decl.c (start_decl): Allow static and thread_local declarations in constexpr function bodies for C++23. Adjust error message for older standards to mention it. * constexpr.c (ensure_literal_type_for_constexpr_object): Allow declarations of variables with non-literal type in constexpr function bodies for C++23. Adjust error message for older standards to mention it. (cxx_eval_constant_expression) : Diagnose declarations of initialization of static or thread_local vars. (cxx_eval_constant_expression) : Diagnose goto statements for C++23. (potential_constant_expression_1) : Allow declarations of static and thread_local vars for C++23. (potential_constant_expression_1) : Allow labels for C++23. gcc/testsuite/ * g++.dg/cpp23/feat-cxx2b.C: Expect __cpp_constexpr 202103L rather than 201907L. * g++.dg/cpp23/constexpr-nonlit1.C: New test. * g++.dg/cpp23/constexpr-nonlit2.C: New test. * g++.dg/cpp23/constexpr-nonlit3.C: New test. * g++.dg/diagnostic/constexpr1.C: Only expect some diagnostics for c++20_down. * g++.dg/cpp1y/constexpr-label.C: Likewise. * g++.dg/cpp1y/constexpr-neg1.C: Likewise. * g++.dg/cpp2a/constexpr-try5.C: Likewise. Adjust some expected wording. * g++.dg/cpp2a/constexpr-dtor3.C: Likewise. * g++.dg/cpp2a/consteval3.C: Likewise. Add effective target c++20 and remove dg-options. --- gcc/c-family/c-cppbuiltin.c.jj 2021-09-21 23:31:01.016248936 +0200 +++ gcc/c-family/c-cppbuiltin.c 2021-10-05 12:54:29.898321379 +0200 @@ -1052,7 +1052,8 @@ c_cpp_builtins (cpp_reader *pfile) cpp_define (pfile, "__cpp_init_captures=201803L"); cpp_define (pfile, "__cpp_generic_lambdas=201707L"); cpp_define (pfile, "__cpp_designated_initializers=201707L"); - cpp_define (pfile,