diff options
author | Jakub Jelinek <jakub@redhat.com> | 2021-10-06 10:28:31 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2021-10-06 10:28:31 +0200 |
commit | 8892d532d66910e518bc135a851a104322385ca2 (patch) | |
tree | 4de92e23189314aa0778d012923888b88a9c4a06 | |
parent | f43eb7707c06e8824d07d5c87ed2019d796fa8a0 (diff) | |
download | gcc-8892d532d66910e518bc135a851a104322385ca2.zip gcc-8892d532d66910e518bc135a851a104322385ca2.tar.gz gcc-8892d532d66910e518bc135a851a104322385ca2.tar.bz2 |
c++: Implement C++23 P2242R3 - Non-literal variables (and labels and gotos) in constexpr functions [PR102612]
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.
2021-10-06 Jakub Jelinek <jakub@redhat.com>
PR c++/102612
gcc/c-family/
* c-cppbuiltin.c (c_cpp_builtins): For -std=c++23 predefine
__cpp_constexpr to 202110L 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) <case DECL_EXPR>: Diagnose declarations
of initialization of static or thread_local vars.
(cxx_eval_constant_expression) <case GOTO_EXPR>: Diagnose goto
statements for C++23.
(potential_constant_expression_1) <case DECL_EXPR>: Swap the
CP_DECL_THREAD_LOCAL_P and TREE_STATIC checks.
(potential_constant_expression_1) <case LABEL_EXPR>: Allow labels for
C++23. Adjust error message for older standards to mention it.
gcc/testsuite/
* g++.dg/cpp23/feat-cxx2b.C: Expect __cpp_constexpr 202110L 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/cpp23/constexpr-nonlit4.C: New test.
* g++.dg/cpp23/constexpr-nonlit5.C: New test.
* g++.dg/cpp23/constexpr-nonlit6.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.
-rw-r--r-- | gcc/c-family/c-cppbuiltin.c | 4 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 54 | ||||
-rw-r--r-- | gcc/cp/decl.c | 9 | ||||
-rw-r--r-- | gcc/cp/parser.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/constexpr-label.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C | 68 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C | 54 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp23/constexpr-nonlit3.C | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp23/constexpr-nonlit4.C | 57 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp23/constexpr-nonlit5.C | 57 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C | 25 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/consteval3.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C | 22 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/diagnostic/constexpr1.C | 6 |
17 files changed, 353 insertions, 41 deletions
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c index a299273..60e9e05 100644 --- a/gcc/c-family/c-cppbuiltin.c +++ b/gcc/c-family/c-cppbuiltin.c @@ -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, "__cpp_constexpr=201907L"); + if (cxx_dialect <= cxx20) + cpp_define (pfile, "__cpp_constexpr=201907L"); cpp_define (pfile, "__cpp_constexpr_in_decltype=201711L"); cpp_define (pfile, "__cpp_conditional_explicit=201806L"); cpp_define (pfile, "__cpp_consteval=201811L"); @@ -1071,6 +1072,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=202110L"); } if (flag_concepts) { diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index e95ff00..66d5221 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -109,14 +109,15 @@ ensure_literal_type_for_constexpr_object (tree decl) explain_non_literal_class (type); decl = error_mark_node; } - else + else if (cxx_dialect < cxx23) { if (!is_instantiation_of_constexpr (current_function_decl)) { auto_diagnostic_group d; error_at (DECL_SOURCE_LOCATION (decl), "variable %qD of non-literal type %qT in " - "%<constexpr%> function", decl, type); + "%<constexpr%> function only available with " + "%<-std=c++2b%> or %<-std=gnu++2b%>", decl, type); explain_non_literal_class (type); decl = error_mark_node; } @@ -6345,6 +6346,26 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, r = void_node; break; } + + if (VAR_P (r) + && (TREE_STATIC (r) || CP_DECL_THREAD_LOCAL_P (r)) + /* Allow __FUNCTION__ etc. */ + && !DECL_ARTIFICIAL (r)) + { + gcc_assert (cxx_dialect >= cxx23); + if (!ctx->quiet) + { + if (CP_DECL_THREAD_LOCAL_P (r)) + error_at (loc, "control passes through declaration of %qD " + "with thread storage duration", r); + else + error_at (loc, "control passes through declaration of %qD " + "with static storage duration", r); + } + *non_constant_p = true; + break; + } + if (AGGREGATE_TYPE_P (TREE_TYPE (r)) || VECTOR_TYPE_P (TREE_TYPE (r))) { @@ -7049,10 +7070,18 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, break; case GOTO_EXPR: - *jump_target = TREE_OPERAND (t, 0); - gcc_assert (breaks (jump_target) || continues (jump_target) - /* Allow for jumping to a cdtor_label. */ - || returns (jump_target)); + if (breaks (&TREE_OPERAND (t, 0)) + || continues (&TREE_OPERAND (t, 0)) + /* Allow for jumping to a cdtor_label. */ + || returns (&TREE_OPERAND (t, 0))) + *jump_target = TREE_OPERAND (t, 0); + else + { + gcc_assert (cxx_dialect >= cxx23); + if (!ctx->quiet) + error_at (loc, "%<goto%> is not a constant expression"); + *non_constant_p = true; + } break; case LOOP_EXPR: @@ -8736,18 +8765,18 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, tmp = DECL_EXPR_DECL (t); if (VAR_P (tmp) && !DECL_ARTIFICIAL (tmp)) { - if (TREE_STATIC (tmp)) + if (CP_DECL_THREAD_LOCAL_P (tmp)) { if (flags & tf_error) error_at (DECL_SOURCE_LOCATION (tmp), "%qD declared " - "%<static%> in %<constexpr%> context", tmp); + "%<thread_local%> in %<constexpr%> context", tmp); return false; } - else if (CP_DECL_THREAD_LOCAL_P (tmp)) + else if (TREE_STATIC (tmp)) { if (flags & tf_error) error_at (DECL_SOURCE_LOCATION (tmp), "%qD declared " - "%<thread_local%> in %<constexpr%> context", tmp); + "%<static%> in %<constexpr%> context", tmp); return false; } else if (!check_for_uninitialized_const_var @@ -9025,10 +9054,11 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case LABEL_EXPR: t = LABEL_EXPR_LABEL (t); - if (DECL_ARTIFICIAL (t)) + if (DECL_ARTIFICIAL (t) || cxx_dialect >= cxx23) return true; else if (flags & tf_error) - error_at (loc, "label definition is not a constant expression"); + error_at (loc, "label definition in %<constexpr%> function only " + "available with %<-std=c++2b%> or %<-std=gnu++2b%>"); return false; case ANNOTATE_EXPR: diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 722e540..2d30c79 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5709,17 +5709,20 @@ start_decl (const cp_declarator *declarator, } if (current_function_decl && VAR_P (decl) - && DECL_DECLARED_CONSTEXPR_P (current_function_decl)) + && DECL_DECLARED_CONSTEXPR_P (current_function_decl) + && cxx_dialect < cxx23) { bool ok = false; if (CP_DECL_THREAD_LOCAL_P (decl)) error_at (DECL_SOURCE_LOCATION (decl), - "%qD declared %<thread_local%> in %qs function", decl, + "%qD declared %<thread_local%> in %qs function only " + "available with %<-std=c++2b%> or %<-std=gnu++2b%>", decl, DECL_IMMEDIATE_FUNCTION_P (current_function_decl) ? "consteval" : "constexpr"); else if (TREE_STATIC (decl)) error_at (DECL_SOURCE_LOCATION (decl), - "%qD declared %<static%> in %qs function", decl, + "%qD declared %<static%> in %qs function only available " + "with %<-std=c++2b%> or %<-std=gnu++2b%>", decl, DECL_IMMEDIATE_FUNCTION_P (current_function_decl) ? "consteval" : "constexpr"); else diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index c6f1a97..d285a45 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -14176,9 +14176,11 @@ cp_parser_jump_statement (cp_parser* parser) case RID_GOTO: if (parser->in_function_body - && DECL_DECLARED_CONSTEXPR_P (current_function_decl)) + && DECL_DECLARED_CONSTEXPR_P (current_function_decl) + && cxx_dialect < cxx23) { - error ("%<goto%> in %<constexpr%> function"); + error ("%<goto%> in %<constexpr%> function only available with " + "%<-std=c++2b%> or %<-std=gnu++2b%>"); cp_function_chain->invalid_constexpr = true; } diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-label.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-label.C index a2d113c..4994008 100644 --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-label.C +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-label.C @@ -4,6 +4,6 @@ constexpr int f () { -x: // { dg-error "label definition is not a constant expression" } +x: // { dg-error "label definition in 'constexpr' function only available with" "" { target c++20_down } } return 42; } diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C index 53f0f1f..8e9d1ea 100644 --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C @@ -4,12 +4,12 @@ struct A { A(); }; constexpr int f(int i) { static int j = i; // { dg-error "static" } - thread_local int l = i; // { dg-error "thread_local" } - goto foo; // { dg-error "goto" } + thread_local int l = i; // { dg-error "thread_local" "" { target c++20_down } } + goto foo; // { dg-error "goto" "" { target c++20_down } } foo: asm("foo"); // { dg-error "asm" "" { target c++17_down } } int k; // { dg-error "uninitialized" "" { target c++17_down } } - A a; // { dg-error "non-literal" } + A a; // { dg-error "non-literal" "" { target c++20_down } } return i; } diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C new file mode 100644 index 0000000..c80ea38 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C @@ -0,0 +1,68 @@ +// P2242R3 +// { dg-do compile { target c++14 } } + +constexpr int +foo () +{ +lab: // { dg-error "label definition in 'constexpr' function only available with" "" { target c++20_down } } + return 1; +} + +constexpr int +bar (int x) +{ + if (x) + goto lab; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } } + return 1; +lab: + return 0; +} + +constexpr int +baz (int x) +{ + if (!x) + return 1; + static int a; // { dg-error "'a' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } } + return ++a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" "" { target c++17_down } .-1 } +} + +constexpr int +qux (int x) +{ + if (!x) + return 1; + thread_local int a; // { dg-error "'a' declared 'thread_local' in 'constexpr' function only available with" "" { target c++20_down } } + return ++a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" "" { target c++17_down } .-1 } +} + +constexpr int +garply (int x) +{ + if (!x) + return 1; + extern thread_local int a; // { dg-error "'a' declared 'thread_local' in 'constexpr' function only available with" "" { target c++20_down } } + return ++a; +} + +struct S { S (); ~S (); int s; }; // { dg-message "'S' is not literal because:" "" { target c++20_down } } + // { dg-message "'S' has a non-trivial destructor" "" { target c++17_down } .-1 } + // { dg-message "'S' does not have 'constexpr' destructor" "" { target { c++20_only } } .-2 } + +constexpr int +corge (int x) +{ + if (!x) + return 1; + S s; // { dg-error "variable 's' of non-literal type 'S' in 'constexpr' function only available with" "" { target c++20_down } } + return 0; +} + +#if __cpp_constexpr >= 202110L +static_assert (foo ()); +static_assert (bar (0)); +static_assert (baz (0)); +static_assert (qux (0)); +static_assert (garply (0)); +static_assert (corge (0)); +#endif diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C new file mode 100644 index 0000000..0f7b229 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C @@ -0,0 +1,54 @@ +// P2242R3 +// { dg-do compile } +// { dg-options "-std=c++2b" } + +constexpr int +foo () +{ +lab: + return 1; +} + +constexpr int +bar (int x) +{ + if (x) + goto lab; // { dg-error "'goto' is not a constant expression" } + return 1; +lab: + return 0; +} + +constexpr int +baz (int x) +{ + if (!x) + return 1; + static int a; // { dg-error "control passes through declaration of 'a' with static storage duration" } + return ++a; +} + +constexpr int +qux (int x) +{ + if (!x) + return 1; + thread_local int a; // { dg-error "control passes through declaration of 'a' with thread storage duration" } + return ++a; +} + +struct S { S (); ~S (); int s; }; // { dg-message "'S::S\\\(\\\)' declared here" } + +constexpr int +corge (int x) +{ + if (!x) + return 1; + S s; // { dg-error "call to non-'constexpr' function 'S::S\\\(\\\)'" } + return 0; +} + +constexpr int a = bar (1); // { dg-message "in 'constexpr' expansion of" } +constexpr int b = baz (1); // { dg-message "in 'constexpr' expansion of" } +constexpr int c = qux (1); // { dg-message "in 'constexpr' expansion of" } +constexpr int d = corge (1); // { dg-message "in 'constexpr' expansion of" } diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit3.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit3.C new file mode 100644 index 0000000..3b5585d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit3.C @@ -0,0 +1,10 @@ +// P2242R3 +// { dg-do compile { target c++14 } } + +constexpr int +foo () +{ + goto lab; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } } +lab: // { dg-error "'goto' is not a constant expression" "" { target { c++23 } } .-1 } + return 1; +} diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit4.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit4.C new file mode 100644 index 0000000..e4ed2e3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit4.C @@ -0,0 +1,57 @@ +// { dg-do compile } +// { dg-options "-std=c++2b" } + +int qux (); + +constexpr int +foo (int x) +{ + switch (x) + { + static int v = qux (); + case 12: + return 1; + } + return 0; +} + +constexpr int +bar (int x) +{ + switch (x) + { + thread_local int v = qux (); + case 12: + return 1; + } + return 0; +} + +constexpr int +baz (int x) +{ + switch (x) + { + static const int v = qux (); // { dg-message "'v' was not initialized with a constant expression" } + case 12: + return v; + } + return 0; +} + +constexpr int +corge (int x) +{ + switch (x) + { + const thread_local int v = qux (); // { dg-message "'v' was not initialized with a constant expression" } + case 12: + return v; + } + return 0; +} + +constexpr int a = foo (12); +constexpr int b = bar (12); +constexpr int c = baz (12); // { dg-error "the value of 'v' is not usable in a constant expression" } +constexpr int d = corge (12); // { dg-error "the value of 'v' is not usable in a constant expression" } diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit5.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit5.C new file mode 100644 index 0000000..838f282 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit5.C @@ -0,0 +1,57 @@ +// { dg-do compile } +// { dg-options "-std=c++2b" } + +int qux (); + +constexpr int +foo (int x) +{ + switch (x) + { + static const int v = 6; + case 12: + return v; + } + return 0; +} + +constexpr int +bar (int x) +{ + switch (x) + { + thread_local const int v = 7; + case 12: + return 7; + } + return 0; +} + +constexpr int +baz (int x) +{ + switch (x) + { + static int v = 6; // { dg-message "int v' is not const" } + case 12: + return v; + } + return 0; +} + +constexpr int +corge (int x) +{ + switch (x) + { + thread_local int v = 6; // { dg-message "int v' is not const" } + case 12: + return v; + } + return 0; +} + +constexpr int a = foo (12); +constexpr int b = bar (12); +constexpr int c = baz (12); // { dg-error "the value of 'v' is not usable in a constant expression" } +constexpr int d = corge (12); // { dg-error "the value of 'v' is not usable in a constant expression" } diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C new file mode 100644 index 0000000..11cb518 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C @@ -0,0 +1,25 @@ +// P2242R3 +// { dg-do compile } +// { dg-options "-std=c++2b" } + +constexpr int +foo () +{ + goto lab; // { dg-error "'goto' is not a constant expression" } +lab: + return 1; +} + +constexpr int +bar () +{ + static int a; // { dg-error "'a' declared 'static' in 'constexpr' context" } + return ++a; +} + +constexpr int +baz (int x) +{ + thread_local int a; // { dg-error "'a' declared 'thread_local' in 'constexpr' context" } + return ++a; +} diff --git a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C index 7070f59..8bb3bf1 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 != 201907 -# error "__cpp_constexpr != 201907" +#elif __cpp_constexpr != 202110 +# error "__cpp_constexpr != 202110" #endif #ifndef __cpp_decltype_auto diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval3.C b/gcc/testsuite/g++.dg/cpp2a/consteval3.C index 9fb1f1a..8f93164 100644 --- a/gcc/testsuite/g++.dg/cpp2a/consteval3.C +++ b/gcc/testsuite/g++.dg/cpp2a/consteval3.C @@ -1,5 +1,4 @@ -// { dg-do compile } -// { dg-options "-std=c++2a" } +// { dg-do compile { target c++20 } } struct S { S () : a (0), b (1) {} int a, b; }; int f1 (); // { dg-message "previous declaration 'int f1\\(\\)'" } @@ -57,7 +56,8 @@ template consteval float f12 (float x); // { dg-error "explicit instantiation sh consteval int f13 (int x) { - static int a = 5; // { dg-error "'a' declared 'static' in 'consteval' function" } - thread_local int b = 6; // { dg-error "'b' declared 'thread_local' in 'consteval' function" } + static int a = 5; // { dg-error "'a' declared 'static' in 'consteval' function only available with" "" { target c++20_only } } + // { dg-error "'a' declared 'static' in 'constexpr' context" "" { target c++23 } .-1 } + thread_local int b = 6; // { dg-error "'b' declared 'thread_local' in 'consteval' function only available with" "" { target c++20_only } } return x; } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C index 7700bb7..69fe9e2 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C @@ -180,6 +180,6 @@ f7 () constexpr int f8 () { - T t4; // { dg-error "variable 't4' of non-literal type 'T' in 'constexpr' function" } + T t4; // { dg-error "variable 't4' of non-literal type 'T' in 'constexpr' function only available with" "" { target c++20_down } } return 0; } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C index 3b51bf7..ed5e40d 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C @@ -5,14 +5,15 @@ constexpr int foo () try { // { dg-warning "function-try-block body of 'constexpr' function only available with" "" { target c++17_down } } int a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" "" { target c++17_down } } - static double b = 1.0;// { dg-error "'b' declared 'static' in 'constexpr' function" } - goto l; // { dg-error "'goto' in 'constexpr' function" } + static double b = 1.0;// { dg-error "'b' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } } + // { dg-error "'b' declared 'static' in 'constexpr' context" "" { target c++23 } .-1 } + goto l; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } } l:; return 0; } catch (...) { long int c; // { dg-error "uninitialized variable 'c' in 'constexpr' function" "" { target c++17_down } } - static float d = 2.0f;// { dg-error "'d' declared 'static' in 'constexpr' function" } - goto l2; // { dg-error "'goto' in 'constexpr' function" } + static float d = 2.0f;// { dg-error "'d' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } } + goto l2; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } } l2:; return -1; } @@ -20,20 +21,21 @@ try { // { dg-warning "function-try-block body of 'constexpr' function only av constexpr int bar () { int a; // { dg-error "uninitialized variable 'a' in 'constexpr' function" "" { target c++17_down } } - static long double b = 3.0;// { dg-error "'b' declared 'static' in 'constexpr' function" } - goto l; // { dg-error "'goto' in 'constexpr' function" } + static long double b = 3.0;// { dg-error "'b' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } } + // { dg-error "'b' declared 'static' in 'constexpr' context" "" { target c++23 } .-1 } + goto l; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } } l:; try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } } short c; // { dg-error "uninitialized variable 'c' in 'constexpr' function" "" { target c++17_down } } - static float d; // { dg-error "'d' declared 'static' in 'constexpr' function" } + static float d; // { dg-error "'d' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } } // { dg-error "uninitialized variable 'd' in 'constexpr' function" "" { target c++17_down } .-1 } - goto l2; // { dg-error "'goto' in 'constexpr' function" } + goto l2; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } } l2:; return 0; } catch (int) { char e; // { dg-error "uninitialized variable 'e' in 'constexpr' function" "" { target c++17_down } } - static int f = 5; // { dg-error "'f' declared 'static' in 'constexpr' function" } - goto l3; // { dg-error "'goto' in 'constexpr' function" } + static int f = 5; // { dg-error "'f' declared 'static' in 'constexpr' function only available with" "" { target c++20_down } } + goto l3; // { dg-error "'goto' in 'constexpr' function only available with" "" { target c++20_down } } l3:; return 1; } diff --git a/gcc/testsuite/g++.dg/diagnostic/constexpr1.C b/gcc/testsuite/g++.dg/diagnostic/constexpr1.C index f029e86..f2bcec6 100644 --- a/gcc/testsuite/g++.dg/diagnostic/constexpr1.C +++ b/gcc/testsuite/g++.dg/diagnostic/constexpr1.C @@ -1,5 +1,7 @@ // { dg-do compile { target c++11 } } -constexpr int foo() { thread_local int i __attribute__((unused)) {}; return 1; } // { dg-error "40:.i. declared .thread_local." } +constexpr int foo() { thread_local int i __attribute__((unused)) {}; return 1; } // { dg-error "40:.i. declared .thread_local." "" { target c++20_down } } +// { dg-error "40:.i. declared .thread_local. in .constexpr. context" "" { target c++23 } .-1 } -constexpr int bar() { static int i __attribute__((unused)) {}; return 1; } // { dg-error "34:.i. declared .static." } +constexpr int bar() { static int i __attribute__((unused)) {}; return 1; } // { dg-error "34:.i. declared .static." "" { target c++20_down } } +// { dg-error "34:.i. declared .static. in .constexpr. context" "" { target c++23 } .-1 } |