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();
> +  }
> +}
>

Reply via email to