gimple: Wrong -Wimplicit-fallthrough with if(1) [PR103597]
commitd886a5248e66ab911391af18bf955beb87ee8461
authorMarek Polacek <polacek@redhat.com>
Mon, 28 Mar 2022 22:19:20 +0000 (28 18:19 -0400)
committerMarek Polacek <polacek@redhat.com>
Tue, 29 Mar 2022 18:10:37 +0000 (29 14:10 -0400)
treef47537490d8af1be79da3e2789de16eb383f891e
parent89976d082488b3a7dc7520b980f854ce83043d38
gimple: Wrong -Wimplicit-fallthrough with if(1) [PR103597]

This patch fixes a wrong -Wimplicit-fallthrough warning for

    case 0:
      if (1)  // wrong may fallthrough
return 0;
    case 1:

which in .gimple looks like

    <D.1981>: // case 0
    if (1 != 0) goto <D.1985>; else goto <D.1986>;
    <D.1985>:
    D.1987 = 0;
    // predicted unlikely by early return (on trees) predictor.
    return D.1987;
    <D.1986>:  // dead
    <D.1982>: // case 1

and the warning thinks that <D.1986>: falls through to <D.1982>:.  It
does not know that <D.1986> is effectively a dead label, only reachable
through fallthrough from previous instructions, never jumped to.  To
that effect, Jakub introduced UNUSED_LABEL_P, which is set on such dead
labels.

collect_fallthrough_labels has code to deal with cases like

    case 2:
      if (e != 10)
i++; // this may fallthru, warn
      else
return 44;
    case 3:

which collects labels that may fall through.  Here it sees the "goto <D.1990>;"
at the end of the then branch and so when the warning reaches

    ...
    <D.1990>: // from if-then
    <D.1984>: // case 3

it knows it should warn about the possible fallthrough.  But an UNUSED_LABEL_P
is not a label that can fallthrough like that, so it should ignore those.

However, we still want to warn about this:

    case 0:
      if (1)
n++; // falls through
    case 1:

so collect_fallthrough_labels needs to return the "n = n + 1;" statement, rather
than the dead label.

Co-authored-by: Jakub Jelinek <jakub@redhat.com>
PR middle-end/103597

gcc/ChangeLog:

* gimplify.cc (collect_fallthrough_labels): Don't push UNUSED_LABEL_Ps
into labels.  Maybe set prev to the statement preceding UNUSED_LABEL_P.
(gimplify_cond_expr): Set UNUSED_LABEL_P.
* tree.h (UNUSED_LABEL_P): New.

gcc/testsuite/ChangeLog:

* c-c++-common/Wimplicit-fallthrough-39.c: New test.
gcc/gimplify.cc
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-39.c [new file with mode: 0644]
gcc/tree.h