public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jakub Jelinek <jakub@redhat.com>
To: Jason Merrill <jason@redhat.com>
Cc: Jonathan Wakely <jwakely@redhat.com>,
	gcc-patches@gcc.gnu.org, Marek Polacek <polacek@redhat.com>
Subject: [PATCH] c++, v5: Implement C++23 P2647R1 - Permitting static constexpr variables in constexpr functions
Date: Fri, 18 Nov 2022 10:10:10 +0100	[thread overview]
Message-ID: <Y3dL8nv/qF+qb1j3@tucnak> (raw)
In-Reply-To: <9674a824-0b3d-ee36-cc66-f788fe0d0058@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 2160 bytes --]

On Thu, Nov 17, 2022 at 07:28:56PM -0500, Jason Merrill wrote:
> On 11/17/22 15:42, Jakub Jelinek wrote:
> > On Thu, Nov 17, 2022 at 07:42:40PM +0100, Jakub Jelinek via Gcc-patches wrote:
> > > I thought for older C++ this is to catch
> > > void
> > > foo ()
> > > {
> > >    constexpr int a = ({ static constexpr int b = 2; b; });
> > > }
> > > and for C++23 the only 3 spots that diagnose those.
> > > But perhaps for C++20 or older we can check if the var has a context
> > > of a constexpr function (then assume cp_finish_decl errored or pedwarned
> > > already) and only error or pedwarn otherwise.
> 
> We could, but I wouldn't bother to enforce this specially for
> statement-expressions, which are already an extension.

Ok.

> OTOH, we should test that static constexpr is handled properly for lambdas,
> i.e. this should still fail:
> 
> constexpr int q = [](int i)
> { static constexpr int x = 42; return x+i; }(24);

I guess that is related on how to handle the
lambda-generic-func1.C constexpr-lambda16.C
FAILs.

Attached are 3 patches, one is just an updated version of the previous
patch with simplified constexpr.cc (and fixed the function comment
Marek talked about), this one will accept the statement
expression case with decl_constant_var_p static in it, and passes
GXX_TESTSUITE_STDS=98,11,14,17,20,2b make check-g++ \
RUNTESTFLAGS="--target_board=unix\{-m32,-m64\} dg.exp='constexpr-nonlit* feat-cxx2b* stmtexpr19.C stmtexpr25.C lambda-generic-func1.C constexpr-lambda16.C'"
except for:
+FAIL: g++.dg/cpp1y/lambda-generic-func1.C  -std=c++17 (test for excess errors)
+FAIL: g++.dg/cpp1y/lambda-generic-func1.C  -std=c++20 (test for excess errors)
+FAIL: g++.dg/cpp1z/constexpr-lambda16.C  -std=c++17 (test for excess errors)
+FAIL: g++.dg/cpp1z/constexpr-lambda16.C  -std=c++20 (test for excess errors)
plus the testcase above needs to be dealt with if we want to pedwarn on it
for older C++.

The third one is if we just want something for C++23 and don't want to touch
C++20 and older at all (that one doesn't regress anything), the second one
similarly but will no longer reject the statement expression cases for C++11
.. 20.

	Jakub

[-- Attachment #2: R656 --]
[-- Type: text/plain, Size: 12930 bytes --]

2022-11-18  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.
	* decl.cc (diagnose_static_in_constexpr): New function.
	(start_decl): Remove diagnostics of static or thread_local
	vars in constexpr or consteval functions.
	(cp_finish_decl): Call diagnose_static_in_constexpr.
gcc/testsuite/
	* g++.dg/cpp23/constexpr-nonlit17.C: New test.
	* g++.dg/cpp23/constexpr-nonlit18.C: New test.
	* g++.dg/cpp23/constexpr-nonlit19.C: New test.
	* g++.dg/cpp23/constexpr-nonlit20.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.

--- gcc/c-family/c-cppbuiltin.cc.jj	2022-11-18 09:00:17.102704379 +0100
+++ gcc/c-family/c-cppbuiltin.cc	2022-11-18 09:32:00.389372850 +0100
@@ -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");
--- gcc/cp/constexpr.cc.jj	2022-11-18 09:00:17.108704295 +0100
+++ gcc/cp/constexpr.cc	2022-11-18 09:35:39.822342414 +0100
@@ -7098,7 +7098,8 @@ cxx_eval_constant_expression (const cons
 	    && (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)
 	      {
@@ -9586,7 +9587,10 @@ potential_constant_expression_1 (tree t,
 
     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))
 	    {
--- gcc/cp/decl.cc.jj	2022-11-18 09:03:51.592704514 +0100
+++ gcc/cp/decl.cc	2022-11-18 09:32:00.393372795 +0100
@@ -5600,6 +5600,57 @@ groktypename (cp_decl_specifier_seq *typ
   return type;
 }
 
+/* For C++20 and older diagnose static or thread_local decls in constexpr
+   or consteval functions.  If they are usable in constant expressions,
+   just pedwarn on them.  */
+
+static void
+diagnose_static_in_constexpr (tree decl)
+{
+  if (cxx_dialect >= cxx23)
+    return;
+  if (current_function_decl
+      && VAR_P (decl)
+      && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+    {
+      bool ok = false;
+      if (processing_template_decl
+	  ? decl_maybe_constant_var_p (decl)
+	  : decl_constant_var_p (decl))
+	{
+	  if (CP_DECL_THREAD_LOCAL_P (decl) && !DECL_REALLY_EXTERN (decl))
+	    pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic,
+		     "%qD defined %<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))
+	    pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic,
+		     "%qD defined %<static%> in %qs function only available "
+		     "with %<-std=c++2b%> or %<-std=gnu++2b%>", decl,
+		     DECL_IMMEDIATE_FUNCTION_P (current_function_decl)
+		     ? "consteval" : "constexpr");
+	  ok = true;
+	}
+      else if (CP_DECL_THREAD_LOCAL_P (decl) && !DECL_REALLY_EXTERN (decl))
+	error_at (DECL_SOURCE_LOCATION (decl),
+		  "%qD defined %<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 defined %<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
+	ok = true;
+      if (!ok)
+	cp_function_chain->invalid_constexpr = true;
+    }
+}
+
 /* Process a DECLARATOR for a function-scope or namespace-scope
    variable or function declaration.
    (Function definitions go through start_function; class member
@@ -5860,29 +5911,6 @@ start_decl (const cp_declarator *declara
       DECL_THIS_STATIC (decl) = 1;
     }
 
-  if (current_function_decl && VAR_P (decl)
-      && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
-      && cxx_dialect < cxx23)
-    {
-      bool ok = false;
-      if (CP_DECL_THREAD_LOCAL_P (decl) && !DECL_REALLY_EXTERN (decl))
-	error_at (DECL_SOURCE_LOCATION (decl),
-		  "%qD defined %<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 defined %<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
-	ok = true;
-      if (!ok)
-	cp_function_chain->invalid_constexpr = true;
-    }
-
   if (!processing_template_decl && VAR_P (decl))
     start_decl_1 (decl, initialized);
 
@@ -8424,6 +8452,9 @@ cp_finish_decl (tree decl, tree init, bo
 	  set_user_assembler_name (decl, asmspec);
 	  DECL_HARD_REGISTER (decl) = 1;
 	}
+
+      diagnose_static_in_constexpr (decl);
+
       return;
     }
 
@@ -8749,6 +8780,8 @@ cp_finish_decl (tree decl, tree init, bo
       && !DECL_HARD_REGISTER (decl))
     targetm.lower_local_decl_alignment (decl);
 
+  diagnose_static_in_constexpr (decl);
+
   invoke_plugin_callbacks (PLUGIN_FINISH_DECL, decl);
 }
 
--- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C.jj	2022-11-18 09:32:00.393372795 +0100
+++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C	2022-11-18 09:32:00.393372795 +0100
@@ -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 () == ' ');
--- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C.jj	2022-11-18 09:32:00.394372781 +0100
+++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C	2022-11-18 09:32:00.394372781 +0100
@@ -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 ();
--- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit19.C.jj	2022-11-18 09:32:00.394372781 +0100
+++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit19.C	2022-11-18 09:32:00.394372781 +0100
@@ -0,0 +1,50 @@
+// P2647R1 - Permitting static constexpr variables in constexpr functions
+// { dg-do compile { target c++14 } }
+// { dg-options "-pedantic" }
+
+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-warning "'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-warning "'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-warning "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } }
+  return 0;
+}
+
+constexpr int a6 = f6 ();
--- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit20.C.jj	2022-11-18 09:32:00.394372781 +0100
+++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit20.C	2022-11-18 09:32:00.394372781 +0100
@@ -0,0 +1,50 @@
+// P2647R1 - Permitting static constexpr variables in constexpr functions
+// { dg-do compile { target c++14 } }
+// { dg-options "-Wno-pedantic" }
+
+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;
+  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);
+  return 0;
+}
+
+constexpr int
+f6 ()
+{
+  static const int a = f1 (0);
+  return 0;
+}
+
+constexpr int a6 = f6 ();
--- gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C.jj	2022-11-18 09:00:17.293701708 +0100
+++ gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C	2022-11-18 09:32:00.394372781 +0100
@@ -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
--- gcc/testsuite/g++.dg/ext/stmtexpr19.C.jj	2022-11-18 09:00:17.367700673 +0100
+++ gcc/testsuite/g++.dg/ext/stmtexpr19.C	2022-11-18 09:43:20.682975254 +0100
@@ -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;
--- gcc/testsuite/g++.dg/ext/stmtexpr25.C.jj	2022-11-18 09:43:08.505143556 +0100
+++ gcc/testsuite/g++.dg/ext/stmtexpr25.C	2022-11-18 09:44:39.672883560 +0100
@@ -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(){}

[-- Attachment #3: R656h --]
[-- Type: text/plain, Size: 5799 bytes --]

2022-11-18  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.

--- gcc/c-family/c-cppbuiltin.cc.jj	2022-11-18 09:00:17.102704379 +0100
+++ gcc/c-family/c-cppbuiltin.cc	2022-11-18 09:32:00.389372850 +0100
@@ -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");
--- gcc/cp/constexpr.cc.jj	2022-11-18 09:00:17.108704295 +0100
+++ gcc/cp/constexpr.cc	2022-11-18 09:35:39.822342414 +0100
@@ -7098,7 +7098,8 @@ cxx_eval_constant_expression (const cons
 	    && (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)
 	      {
@@ -9586,7 +9587,10 @@ potential_constant_expression_1 (tree t,
 
     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))
 	    {
--- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C.jj	2022-11-18 09:32:00.393372795 +0100
+++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C	2022-11-18 09:32:00.393372795 +0100
@@ -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 () == ' ');
--- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C.jj	2022-11-18 09:32:00.394372781 +0100
+++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C	2022-11-18 09:57:48.159986371 +0100
@@ -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 } }
--- gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C.jj	2022-11-18 09:00:17.293701708 +0100
+++ gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C	2022-11-18 09:32:00.394372781 +0100
@@ -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
--- gcc/testsuite/g++.dg/ext/stmtexpr19.C.jj	2022-11-18 09:00:17.367700673 +0100
+++ gcc/testsuite/g++.dg/ext/stmtexpr19.C	2022-11-18 09:43:20.682975254 +0100
@@ -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;
--- gcc/testsuite/g++.dg/ext/stmtexpr25.C.jj	2022-11-18 09:43:08.505143556 +0100
+++ gcc/testsuite/g++.dg/ext/stmtexpr25.C	2022-11-18 09:44:39.672883560 +0100
@@ -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(){}

[-- Attachment #4: R656i --]
[-- Type: text/plain, Size: 5920 bytes --]

2022-11-18  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
	for C++23.
	(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.

--- gcc/c-family/c-cppbuiltin.cc.jj	2022-11-18 09:00:17.102704379 +0100
+++ gcc/c-family/c-cppbuiltin.cc	2022-11-18 09:32:00.389372850 +0100
@@ -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");
--- gcc/cp/constexpr.cc.jj	2022-11-18 09:00:17.108704295 +0100
+++ gcc/cp/constexpr.cc	2022-11-18 09:35:39.822342414 +0100
@@ -7098,7 +7098,8 @@ cxx_eval_constant_expression (const cons
 	    && (TREE_STATIC (r)
 		|| (CP_DECL_THREAD_LOCAL_P (r) && !DECL_REALLY_EXTERN (r)))
 	    /* Allow __FUNCTION__ etc.  */
-	    && !DECL_ARTIFICIAL (r))
+	    && !DECL_ARTIFICIAL (r)
+	    && (cxx_dialect < cxx23 || !decl_constant_var_p (r)))
 	  {
 	    if (!ctx->quiet)
 	      {
@@ -9586,7 +9587,10 @@ potential_constant_expression_1 (tree t,
 
     case DECL_EXPR:
       tmp = DECL_EXPR_DECL (t);
-      if (VAR_P (tmp) && !DECL_ARTIFICIAL (tmp))
+      if (VAR_P (tmp) && !DECL_ARTIFICIAL (tmp)
+	  && (cxx_dialect < cxx23 || (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))
 	    {
--- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C.jj	2022-11-18 09:32:00.393372795 +0100
+++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit17.C	2022-11-18 09:32:00.393372795 +0100
@@ -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 () == ' ');
--- gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C.jj	2022-11-18 09:32:00.394372781 +0100
+++ gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C	2022-11-18 09:57:48.159986371 +0100
@@ -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 } }
--- gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C.jj	2022-11-18 09:00:17.293701708 +0100
+++ gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C	2022-11-18 09:32:00.394372781 +0100
@@ -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
--- gcc/testsuite/g++.dg/ext/stmtexpr19.C.jj	2022-11-18 09:00:17.367700673 +0100
+++ gcc/testsuite/g++.dg/ext/stmtexpr19.C	2022-11-18 09:43:20.682975254 +0100
@@ -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; }) // { dg-error "static" "" { target c++20_down } .-1 }
     };
 
   return &atest;
--- gcc/testsuite/g++.dg/ext/stmtexpr25.C.jj	2022-11-18 09:43:08.505143556 +0100
+++ gcc/testsuite/g++.dg/ext/stmtexpr25.C	2022-11-18 09:44:39.672883560 +0100
@@ -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(){}

  reply	other threads:[~2022-11-18  9:10 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-11 17:07 [PATCH] c++: " Jakub Jelinek
2022-11-13 11:45 ` [PATCH] c++, v2: " Jakub Jelinek
2022-11-15 23:36   ` Jason Merrill
2022-11-15 23:50     ` Jakub Jelinek
2022-11-16  0:27       ` Jonathan Wakely
2022-11-16  6:19         ` Jakub Jelinek
2022-11-16 13:20           ` Jason Merrill
2022-11-16 14:08             ` Jakub Jelinek
2022-11-16 14:33               ` Jason Merrill
2022-11-16 14:46                 ` Jakub Jelinek
2022-11-16 20:26                   ` Jason Merrill
2022-11-17  9:13                     ` [PATCH] c++, v3: " Jakub Jelinek
2022-11-17 14:42                       ` Jason Merrill
2022-11-17 18:42                         ` Jakub Jelinek
2022-11-17 20:42                           ` [PATCH] c++, v4: " Jakub Jelinek
2022-11-18  0:15                             ` Marek Polacek
2022-11-18  7:48                               ` Jakub Jelinek
2022-11-18 15:03                                 ` Marek Polacek
2022-11-18 15:14                                   ` Jakub Jelinek
2022-11-18 16:24                                   ` Jason Merrill
2022-11-18 16:34                                     ` Jakub Jelinek
2022-11-18 16:52                                       ` Jason Merrill
2022-11-18  0:28                             ` Jason Merrill
2022-11-18  9:10                               ` Jakub Jelinek [this message]
2022-11-16  0:26     ` [PATCH] c++, v2: " Jonathan Wakely

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Y3dL8nv/qF+qb1j3@tucnak \
    --to=jakub@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jason@redhat.com \
    --cc=jwakely@redhat.com \
    --cc=polacek@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).