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