public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [C++ PATCH] Fix constexpr switch handling (PR c++/77467)
@ 2016-09-05 17:14 Jakub Jelinek
  2016-09-16 20:00 ` Jason Merrill
  0 siblings, 1 reply; 7+ messages in thread
From: Jakub Jelinek @ 2016-09-05 17:14 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

Hi!

cxx_eval_switch_expr assumes that SWITCH_EXPR's body is always a
STATEMENT_LIST, but that doesn't have to be the case.
As the testcase shows, if there are any variable declarations in the
switch body, it can be also a BIND_EXPR, which cxx_eval_constant_expression
handles properly, and as bar in the testcase shows, it can be also just
a single statement (as try isn't allowed in constexpr functions, I think
we just want to do what cxx_eval_statement_list would do on such a statement
if it was wrapped into a STATEMENT_LIST - ignore it, as the case NNN: or default:
is not present.

Bootstrapped/regtested on x86_64-linux and i686-linux?  What about older
branches?

2016-09-05  Jakub Jelinek  <jakub@redhat.com>

	PR c++/77467
	* constexpr.c (cxx_eval_switch_expr): Call cxx_eval_constant_expression
	instead of cxx_eval_statement_list, for body other than STATEMENT_LIST
	or BIND_EXPR don't evaluate the body at all.

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

--- gcc/cp/constexpr.c.jj	2016-08-30 08:42:06.000000000 +0200
+++ gcc/cp/constexpr.c	2016-09-05 11:34:30.185518395 +0200
@@ -3572,8 +3572,12 @@ cxx_eval_switch_expr (const constexpr_ct
   *jump_target = cond;
 
   tree body = TREE_OPERAND (t, 1);
-  cxx_eval_statement_list (ctx, body,
-			   non_constant_p, overflow_p, jump_target);
+  /* If body is a statement other than STATEMENT_LIST or BIND_EXPR,
+     it should be skipped.  E.g. switch (a) b = a;  */
+  if (TREE_CODE (body) == STATEMENT_LIST
+      || TREE_CODE (body) == BIND_EXPR)
+    cxx_eval_constant_expression (ctx, body, false,
+				  non_constant_p, overflow_p, jump_target);
   if (breaks (jump_target) || switches (jump_target))
     *jump_target = NULL_TREE;
   return NULL_TREE;
--- gcc/testsuite/g++.dg/cpp1y/constexpr-77467.C.jj	2016-09-05 11:19:30.593750642 +0200
+++ gcc/testsuite/g++.dg/cpp1y/constexpr-77467.C	2016-09-05 11:37:11.929477518 +0200
@@ -0,0 +1,33 @@
+// PR c++/77467
+// { dg-do compile { target c++14 } }
+
+constexpr int
+foo (const int x, const unsigned n) noexcept
+{
+  switch (n)
+    {
+    case 0:
+      return 1;
+    case 1:
+      return x;
+    default:
+      const auto m = (n >> 1);
+      const auto y = foo (x, m);
+      return ((m << 1) == n) ? y * y : x * y * y;
+    }
+}
+
+static_assert (foo (3, 2) == 9, "");
+static_assert (foo (2, 3) == 8, "");
+
+constexpr int
+bar (int x)
+{
+  int a = x;
+  switch (x)
+    a = x + 1;
+  return a;
+}
+
+static_assert (bar (0) == 0, "");
+static_assert (bar (1) == 1, "");

	Jakub

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

end of thread, other threads:[~2016-09-28 14:38 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-05 17:14 [C++ PATCH] Fix constexpr switch handling (PR c++/77467) Jakub Jelinek
2016-09-16 20:00 ` Jason Merrill
2016-09-16 20:51   ` Jakub Jelinek
2016-09-19 18:49     ` Jason Merrill
2016-09-20 16:29       ` [C++ PATCH] Fix constexpr switch handling (PR c++/77467, take 2) Jakub Jelinek
2016-09-27 21:33         ` Patch ping Jakub Jelinek
2016-09-28 14:42         ` [C++ PATCH] Fix constexpr switch handling (PR c++/77467, take 2) 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).