[PATCH] c++: Fix up constexpr CLEANUP_POINT_EXPR and TRY_FINALLY_EXPR handling [PR97790]

Jakub Jelinek jakub@redhat.com
Wed Nov 11 15:26:46 GMT 2020


Hi!

As the testcase shows, CLEANUP_POINT_EXPR (and I think TRY_FINALLY_EXPR too)
suffer from the same problem that I was trying to fix in
r10-3597-g1006c9d4395a939820df76f37c7b085a4a1a003f
for CLEANUP_STMT, namely that if in the middle of the body expression of
those stmts is e.g. return stmt, goto, break or continue (something that
changes *jump_target and makes it start skipping stmts), we then skip the
cleanups too, which is not appropriate - the cleanups were either queued up
during the non-skipping execution of the body (for CLEANUP_POINT_EXPR), or
for TRY_FINALLY_EXPR are relevant already after entering the body block.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2020-11-11  Jakub Jelinek  <jakub@redhat.com>

	PR c++/97790
	* constexpr.c (cxx_eval_constant_expression) <case CLEANUP_POINT_EXPR,
	case TRY_FINALLY_EXPR>: For evaluation of cleanups use initially
	recorded jump_target pointee rather than whatever ends up in it
	after evaluation of the body operand.

	* g++.dg/cpp2a/constexpr-dtor9.C: New test.

--- gcc/cp/constexpr.c.jj	2020-11-04 09:35:10.025029335 +0100
+++ gcc/cp/constexpr.c	2020-11-11 13:52:37.538466295 +0100
@@ -6008,6 +6008,7 @@ cxx_eval_constant_expression (const cons
 	auto_vec<tree, 2> cleanups;
 	vec<tree> *prev_cleanups = ctx->global->cleanups;
 	ctx->global->cleanups = &cleanups;
+	tree initial_jump_target = jump_target ? *jump_target : NULL_TREE;
 	r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0),
 					  lval,
 					  non_constant_p, overflow_p,
@@ -6019,19 +6020,24 @@ cxx_eval_constant_expression (const cons
 	FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup)
 	  cxx_eval_constant_expression (ctx, cleanup, false,
 					non_constant_p, overflow_p,
-					jump_target);
+					jump_target ? &initial_jump_target
+					: NULL);
       }
       break;
 
     case TRY_FINALLY_EXPR:
-      r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
+      {
+	tree initial_jump_target = jump_target ? *jump_target : NULL_TREE;
+	r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
+					  non_constant_p, overflow_p,
+					  jump_target);
+	if (!*non_constant_p)
+	  /* Also evaluate the cleanup.  */
+	  cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), true,
 					non_constant_p, overflow_p,
-					jump_target);
-      if (!*non_constant_p)
-	/* Also evaluate the cleanup.  */
-	cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), true,
-				      non_constant_p, overflow_p,
-				      jump_target);
+					jump_target ? &initial_jump_target
+					: NULL);
+      }
       break;
 
     case CLEANUP_STMT:
--- gcc/testsuite/g++.dg/cpp2a/constexpr-dtor9.C.jj	2020-11-11 13:57:16.572334917 +0100
+++ gcc/testsuite/g++.dg/cpp2a/constexpr-dtor9.C	2020-11-11 13:57:45.510010165 +0100
@@ -0,0 +1,31 @@
+// PR c++/97790
+// { dg-do compile { target c++20 } }
+
+struct S
+{
+  int *d;
+  int n;
+  constexpr S () : d(new int[1]{}), n(1) {}
+  constexpr ~S () { delete [] d; }
+};
+
+constexpr S
+foo ()
+{
+  return S ();
+}
+
+constexpr int
+bar ()
+{
+  return foo ().n;
+}
+
+constexpr int
+baz ()
+{
+  return S ().n;
+}
+
+constexpr int a = baz ();
+constexpr int b = bar ();

	Jakub



More information about the Gcc-patches mailing list