I don't really know whether this is the right way to treat
CONVERT_EXPR as below, but...  Regtested native
x86_64-linux-gnu.  Ok to commit?

brgds, H-P

-- >8 --
That gcc_unreachable at the default-label seems to be over
the top.  It seems more correct to just say "that's not
constant" to whatever's not known (to be constant), when
looking for matches in switch-statements.

With this patch, the code generated for the (inlined) call to
ifbar equals that to swbar, except for the comparisons being
in another order.

gcc/cp:
        PR c++/113545
        * constexpr.cc (label_matches): Replace call to_unreachable with
        return false.

gcc/testsuite:
        * g++.dg/expr/pr113545.C: New text.
---
 gcc/cp/constexpr.cc                 |  3 +-
 gcc/testsuite/g++.dg/expr/pr113545.C | 49 +++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/expr/pr113545.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 6350fe154085..30caf3322fff 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -6922,7 +6922,8 @@ label_matches (const constexpr_ctx *ctx, tree 
*jump_target, tree stmt)
       break;
 
     default:
-      gcc_unreachable ();
+      /* Something else, like CONVERT_EXPR.  Unknown whether it matches.  */
+      break;
     }
   return false;
 }
diff --git a/gcc/testsuite/g++.dg/expr/pr113545.C 
b/gcc/testsuite/g++.dg/expr/pr113545.C
new file mode 100644
index 000000000000..914ffdeb8e16
--- /dev/null
+++ b/gcc/testsuite/g++.dg/expr/pr113545.C
@@ -0,0 +1,49 @@
+// { dg-do run { target c++11 } }
+
+char foo;
+
+// This one caught a call to gcc_unreachable in
+// cp/constexpr.cc:label_matches, when passed a convert_expr from the
+// cast in the call.
+constexpr unsigned char swbar(__UINTPTR_TYPE__ baz)
+{
+  switch (baz)
+    {
+    case 13:
+      return 11;
+    case 14:
+      return 78;
+    case 2048:
+      return 13;
+    default:
+      return 42;
+    }
+}
+
+// For reference, the equivalent* if-statements.
+constexpr unsigned char ifbar(__UINTPTR_TYPE__ baz)
+{
+  if (baz == 13)
+    return 11;
+  else if (baz == 14)
+    return 78;
+  else if (baz == 2048)
+    return 13;
+  else
+    return 42;
+}
+
+__attribute__ ((__noipa__))
+void xyzzy(int x)
+{
+  if (x != 42)
+    __builtin_abort ();
+}
+
+int main()
+{
+  unsigned const char c = swbar(reinterpret_cast<__UINTPTR_TYPE__>(&foo));
+  xyzzy(c);
+  unsigned const char d = ifbar(reinterpret_cast<__UINTPTR_TYPE__>(&foo));
+  xyzzy(d);
+}
-- 
2.30.2

Reply via email to