public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-4206] c++: Implement C++23 P2242R3 - Non-literal variables (and labels and gotos) in constexpr functions [
@ 2021-10-06  8:30 Jakub Jelinek
  0 siblings, 0 replies; only message in thread
From: Jakub Jelinek @ 2021-10-06  8:30 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:8892d532d66910e518bc135a851a104322385ca2

commit r12-4206-g8892d532d66910e518bc135a851a104322385ca2
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Wed Oct 6 10:28:31 2021 +0200

    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.

Diff:
---
 gcc/c-family/c-cppbuiltin.c                    |  4 +-
 gcc/cp/constexpr.c                             | 54 +++++++++++++++-----
 gcc/cp/decl.c                                  |  9 ++--
 gcc/cp/parser.c                                |  6 ++-
 gcc/testsuite/g++.dg/cpp1y/constexpr-label.C   |  2 +-
 gcc/testsuite/g++.dg/cpp1y/constexpr-neg1.C    |  6 +--
 gcc/testsuite/g++.dg/cpp23/constexpr-nonlit1.C | 68 ++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/cpp23/constexpr-nonlit2.C | 54 ++++++++++++++++++++
 gcc/testsuite/g++.dg/cpp23/constexpr-nonlit3.C | 10 ++++
 gcc/testsuite/g++.dg/cpp23/constexpr-nonlit4.C | 57 +++++++++++++++++++++
 gcc/testsuite/g++.dg/cpp23/constexpr-nonlit5.C | 57 +++++++++++++++++++++
 gcc/testsuite/g++.dg/cpp23/constexpr-nonlit6.C | 25 ++++++++++
 gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C        |  4 +-
 gcc/testsuite/g++.dg/cpp2a/consteval3.C        |  8 +--
 gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C   |  2 +-
 gcc/testsuite/g++.dg/cpp2a/constexpr-try5.C    | 22 +++++----
 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 a2992733114..60e9e052062 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 e95ff00774f..66d5221692a 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 722e540baba..2d30c790b93 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 c6f1a9796c5..d285a45bf7d 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 a2d113c186f..4994008a77b 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 53f0f1f7a2b..8e9d1ea4943 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 00000000000..c80ea38732f
--- /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 00000000000..0f7b2299e7a
--- /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 00000000000..3b5585dcd84
--- /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 00000000000..e4ed2e36c30
--- /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 00000000000..838f282c1f9
--- /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 00000000000..11cb5189c85
--- /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 7070f598d39..8bb3bf1f00f 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 9fb1f1a0b12..8f9316411b5 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 7700bb7b036..69fe9e26654 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 3b51bf7c901..ed5e40dff95 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 f029e86e076..f2bcec6e4e1 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 }


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-10-06  8:30 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-06  8:30 [gcc r12-4206] c++: Implement C++23 P2242R3 - Non-literal variables (and labels and gotos) in constexpr functions [ Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).