On Wed, Jul 26, 2017 at 9:35 PM, Peter Bergner <berg...@vnet.ibm.com> wrote: > The test case for PR81564 exposes an issue where the case labels for a > switch statement point to blocks that have already been removed by an > earlier call to cleanup_tree_cfg(). In that case, the code in > group_case_labels_stmt() that does: > > base_bb = label_to_block (CASE_LABEL (base_case)); > > ...returns a NULL base_bb and we SEGV later on when we dereference it: > > if (EDGE_COUNT (base_bb->succs) == 0 > ... > > The fix here is to just treat case labels that point to blocks that have > already been deleted similarly to case labels that point to the default > case statement, by removing them. > > This passed bootstrap and regtesting on powerpc64le-linux with no regressions. > Ok for trunk?
Ok. Thanks, Richard. > Peter > > gcc/ > PR middle-end/81564 > * tree-cfg.c (group_case_labels_stmt): Handle already deleted blocks. > > gcc/testsuite/ > PR middle-end/81564 > * gcc.dg/pr81564.c: New test. > > Index: gcc/tree-cfg.c > =================================================================== > --- gcc/tree-cfg.c (revision 250581) > +++ gcc/tree-cfg.c (working copy) > @@ -1701,8 +1701,9 @@ group_case_labels_stmt (gswitch *stmt) > gcc_assert (base_case); > base_bb = label_to_block (CASE_LABEL (base_case)); > > - /* Discard cases that have the same destination as the default case. > */ > - if (base_bb == default_bb) > + /* Discard cases that have the same destination as the default case or > + whose destination blocks have already been removed as unreachable. > */ > + if (base_bb == NULL || base_bb == default_bb) > { > i++; > continue; > Index: gcc/testsuite/gcc.dg/pr81564.c > =================================================================== > --- gcc/testsuite/gcc.dg/pr81564.c (nonexistent) > +++ gcc/testsuite/gcc.dg/pr81564.c (working copy) > @@ -0,0 +1,21 @@ > +/* PR middle-end/81564 ICE in group_case_labels_stmt(). */ > +/* { dg-do compile } */ > +/* { dg-options "-O2" } */ > + > +struct a { > + int b; > + int c; > +}; > + > +void > +foo (void) > +{ > + struct a *e; > + switch (e->c) > + { > + case 7: > + case 3: > + if (__builtin_expect(!0, 0)) > + __builtin_unreachable(); > + } > +} >