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