public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c++: Fix up potential_constant_expression_1 FOR/WHILE_STMT handling [PR98672]
@ 2021-01-15 16:26 Jakub Jelinek
  2021-01-19 21:01 ` Jason Merrill
  0 siblings, 1 reply; 5+ messages in thread
From: Jakub Jelinek @ 2021-01-15 16:26 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

Hi!

The following testcase is rejected even when it is valid.
The problem is that potential_constant_expression_1 doesn't have the
accurate *jump_target tracking cxx_eval_* has, and when the loop has
a condition that isn't guaranteed to be always true, the body isn't walked
at all.  That is mostly a correct conservative behavior, except that it
doesn't detect if there are any return statements in the body, which means
the loop might return instead of falling through to the next statement.
We already have code for return stmt discovery in code snippets we don't
try to evaluate for switches, so this patch reuses that for FOR_STMT
and WHILE_STMT bodies.

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

Note, I haven't touched FOR_EXPR, with statement expressions it could
have return stmts in it too, or it could have break or continue statements
that wouldn't bind to the current loop but to something outer.  That
case is clearly mishandled by potential_constant_expression_1 even
when the condition is missing or is always true, and it wouldn't surprise me
if cxx_eval_* didn't handle it right either, so I'm deferring that to
separate PR for later.  We'd need proper test coverage for all of that.

2021-01-15  Jakub Jelinek  <jakub@redhat.com>

	PR c++/98672
	* constexpr.c (potential_constant_expression_1) <case FOR_STMT>,
	<case WHILE_STMT>: If the condition isn't constant true, check if
	the loop body can contain a return stmt.

	* g++.dg/cpp1y/constexpr-98672.C: New test.

--- gcc/cp/constexpr.c.jj	2021-01-13 19:19:44.368469462 +0100
+++ gcc/cp/constexpr.c	2021-01-14 12:02:27.347042704 +0100
@@ -8190,7 +8190,17 @@ potential_constant_expression_1 (tree t,
 	  /* If we couldn't evaluate the condition, it might not ever be
 	     true.  */
 	  if (!integer_onep (tmp))
-	    return true;
+	    {
+	      /* Before returning true, check if the for body can contain
+		 a return.  */
+	      hash_set<tree> pset;
+	      check_for_return_continue_data data = { &pset, NULL_TREE };
+	      if (tree ret_expr
+		  = cp_walk_tree (&FOR_BODY (t), check_for_return_continue,
+				  &data, &pset))
+		*jump_target = ret_expr;
+	      return true;
+	    }
 	}
       if (!RECUR (FOR_EXPR (t), any))
 	return false;
@@ -8219,7 +8229,17 @@ potential_constant_expression_1 (tree t,
 	tmp = cxx_eval_outermost_constant_expr (tmp, true);
       /* If we couldn't evaluate the condition, it might not ever be true.  */
       if (!integer_onep (tmp))
-	return true;
+	{
+	  /* Before returning true, check if the while body can contain
+	     a return.  */
+	  hash_set<tree> pset;
+	  check_for_return_continue_data data = { &pset, NULL_TREE };
+	  if (tree ret_expr
+	      = cp_walk_tree (&WHILE_BODY (t), check_for_return_continue,
+			      &data, &pset))
+	    *jump_target = ret_expr;
+	  return true;
+	}
       if (!RECUR (WHILE_BODY (t), any))
 	return false;
       if (breaks (jump_target) || continues (jump_target))
--- gcc/testsuite/g++.dg/cpp1y/constexpr-98672.C.jj	2021-01-14 12:19:24.842438847 +0100
+++ gcc/testsuite/g++.dg/cpp1y/constexpr-98672.C	2021-01-14 12:07:33.935551155 +0100
@@ -0,0 +1,35 @@
+// PR c++/98672
+// { dg-do compile { target c++14 } }
+
+void
+foo ()
+{
+}
+
+constexpr int
+bar ()
+{
+  for (int i = 0; i < 5; ++i)
+    return i;
+  foo ();
+  return 0;
+}
+
+constexpr int
+baz ()
+{
+  int i = 0;
+  while (i < 5)
+    {
+      if (i == 3)
+	return i;
+      else
+	++i;
+    }
+  foo ();
+  return 0;
+}
+
+constexpr int i = bar ();
+constexpr int j = baz ();
+static_assert (i == 0 && j == 3, "");

	Jakub


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-01-21 15:27 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-15 16:26 [PATCH] c++: Fix up potential_constant_expression_1 FOR/WHILE_STMT handling [PR98672] Jakub Jelinek
2021-01-19 21:01 ` Jason Merrill
2021-01-19 21:54   ` [PATCH] c++, v2: " Jakub Jelinek
2021-01-20  7:31     ` Jakub Jelinek
2021-01-21 15:27     ` Jason Merrill

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).