aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2021-10-06 10:28:31 +0200
committerJakub Jelinek <jakub@redhat.com>2021-10-06 10:28:31 +0200
commit8892d532d66910e518bc135a851a104322385ca2 (patch)
tree4de92e23189314aa0778d012923888b88a9c4a06
parentf43eb7707c06e8824d07d5c87ed2019d796fa8a0 (diff)
downloadgcc-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.c4
-rw-r--r--gcc/cp/constexpr.c54
-rw-r--r--gcc/cp/decl.c9
-rw-r--r--gcc/cp/parser.c6
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-label.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C68
-rw-r--r--gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C54
-rw-r--r--gcc/testsuite/g++.dg/cpp23/constexpr-nonlit3.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp23/constexpr-nonlit4.C57
-rw-r--r--gcc/testsuite/g++.dg/cpp23/constexpr-nonlit5.C57
-rw-r--r--gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/consteval3.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C22
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/constexpr1.C6
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 }