public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/95857] New: Silencing an unused label warning with (void)&&label; can make gcc segfault
@ 2020-06-24  7:17 pskocik at gmail dot com
  2020-06-24  7:54 ` [Bug c/95857] [8/9/10/11 Regression] " rguenth at gcc dot gnu.org
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: pskocik at gmail dot com @ 2020-06-24  7:17 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95857

            Bug ID: 95857
           Summary: Silencing an unused label warning with (void)&&label;
                    can make gcc segfault
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: pskocik at gmail dot com
  Target Milestone: ---

Created attachment 48777
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48777&action=edit
preprocessed reproducer that crashes gcc >= 8.1 at -O2/-O3/-Os

In certain more complex contexts and with optimization on (>= -O2), silencing
-Wunused-label warnings  with
(void)&&label; will make gcc segfault.

The attached example ( https://gcc.godbolt.org/z/iEhgL2 ) obtained with creduce
 crashes gcc >= 8.1 when compiled at -O2/-O3/-Os.

I haven't observed the bug in older versions of gcc.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug c/95857] [8/9/10/11 Regression] Silencing an unused label warning with (void)&&label; can make gcc segfault
  2020-06-24  7:17 [Bug c/95857] New: Silencing an unused label warning with (void)&&label; can make gcc segfault pskocik at gmail dot com
@ 2020-06-24  7:54 ` rguenth at gcc dot gnu.org
  2020-06-29 10:04 ` jakub at gcc dot gnu.org
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: rguenth at gcc dot gnu.org @ 2020-06-24  7:54 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95857

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Target Milestone|---                         |8.5
           Priority|P3                          |P2
           Keywords|                            |ice-on-valid-code
            Summary|Silencing an unused label   |[8/9/10/11 Regression]
                   |warning with (void)&&label; |Silencing an unused label
                   |can make gcc segfault       |warning with (void)&&label;
                   |                            |can make gcc segfault
            Version|unknown                     |8.4.0
      Known to work|                            |7.4.0

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug c/95857] [8/9/10/11 Regression] Silencing an unused label warning with (void)&&label; can make gcc segfault
  2020-06-24  7:17 [Bug c/95857] New: Silencing an unused label warning with (void)&&label; can make gcc segfault pskocik at gmail dot com
  2020-06-24  7:54 ` [Bug c/95857] [8/9/10/11 Regression] " rguenth at gcc dot gnu.org
@ 2020-06-29 10:04 ` jakub at gcc dot gnu.org
  2020-06-29 19:40 ` jakub at gcc dot gnu.org
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-06-29 10:04 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95857

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
     Ever confirmed|0                           |1
   Last reconfirmed|                            |2020-06-29
                 CC|                            |jakub at gcc dot gnu.org
             Status|UNCONFIRMED                 |NEW

--- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Started with r8-546-gca4d28516878755a01ab8c2ba48d083100aba3fb

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug c/95857] [8/9/10/11 Regression] Silencing an unused label warning with (void)&&label; can make gcc segfault
  2020-06-24  7:17 [Bug c/95857] New: Silencing an unused label warning with (void)&&label; can make gcc segfault pskocik at gmail dot com
  2020-06-24  7:54 ` [Bug c/95857] [8/9/10/11 Regression] " rguenth at gcc dot gnu.org
  2020-06-29 10:04 ` jakub at gcc dot gnu.org
@ 2020-06-29 19:40 ` jakub at gcc dot gnu.org
  2020-07-02  9:39 ` cvs-commit at gcc dot gnu.org
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-06-29 19:40 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95857

--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Slightly simplified:
struct E { int e; };
int bar (void), baz (void);

void
foo (void)
{
  struct E a = { 0 };
  struct E i = { 0 };
  if (baz ())
    i.e = 1;
  else
    a.e = -2;
  switch (a.e)
    {
    case -2:
    lab1:
      switch (i.e)
        {
        case -3:
        case 2:
          if (i.e-- != 2)
            __builtin_unreachable ();
          (void) &&lab2;
        lab2:
          baz ();
          goto lab1;
        case 0:
          bar ();
        }
    }
}

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug c/95857] [8/9/10/11 Regression] Silencing an unused label warning with (void)&&label; can make gcc segfault
  2020-06-24  7:17 [Bug c/95857] New: Silencing an unused label warning with (void)&&label; can make gcc segfault pskocik at gmail dot com
                   ` (2 preceding siblings ...)
  2020-06-29 19:40 ` jakub at gcc dot gnu.org
@ 2020-07-02  9:39 ` cvs-commit at gcc dot gnu.org
  2020-07-02  9:40 ` [Bug c/95857] [8/9/10 " jakub at gcc dot gnu.org
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2020-07-02  9:39 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95857

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Assignee|unassigned at gcc dot gnu.org      |jakub at gcc dot gnu.org
             Status|NEW                         |ASSIGNED

--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Created attachment 48813
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48813&action=edit
gcc11-pr95857.patch

Untested fix.  The problem is that while normal labels on bb removal are
removed and their label_to_block becomes NULL, that is not what is done with
forced/non-local labels, those are instead moved to some neightbouring block,
and if some later case label refers to them, they will see that random other
block; now if they are kept around because of this rather than thrown away,
that means we might not have an edge to them etc.

--- Comment #4 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:00f24f56732861d09a9716fa5b6b8a96c2289143

commit r11-1783-g00f24f56732861d09a9716fa5b6b8a96c2289143
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Thu Jul 2 11:38:20 2020 +0200

    tree-cfg: Fix ICE with switch stmt to unreachable opt and forced labels
[PR95857]

    The following testcase ICEs, because during the cfg cleanup, we see:
      switch (i$e_11) <default: <L12> [33.33%], case -3: <lab2> [33.33%], case
0: <L10> [33.33%], case 2: <lab2> [33.33%]>
    ...
    lab2:
      __builtin_unreachable ();
    where lab2 is FORCED_LABEL.  The way it works, we go through the case
labels
    and when we reach the first one that points to gimple_seq_unreachable*
    basic block, we remove the edge (if any) from the switch bb to the bb
    containing the label and bbs reachable only through that edge we've just
    removed.  Once we do that, we must throw away all other cases that use
    the same label (or some other labels from the same bb we've removed the
edge
    to and the bb).  To avoid quadratic behavior, this is not done by walking
    all remaining cases immediately before removing, but only when processing
    them later.
    For normal labels this works, fine, if the label is in a deleted bb, it
will
    have NULL label_to_block and we handle that case, or, if the unreachable bb
    has some other edge to it, only the edge will be removed and not the bb,
    and again, find_edge will not find the edge and we only remove the case.
    And if a label would be to some other block, that other block wouldn't have
    been removed earlier because there would be still an edge from the switch
    block.
    Now, FORCED_LABEL (and I think DECL_NONLOCAL too) break this, because
    those labels aren't removed, but instead moved to some surrounding basic
    block.  So, when we later process those, when their gimple_seq_unreachable*
    basic block is removed, label_to_block will return some unrelated block
    (in the testcase the switch bb), so we decide to keep the case which
doesn't
    seem to be unreachable, but we don't really have an edge from the switch
    block to the block the label got moved to.

    I thought first about punting in gimple_seq_unreachable* on
    FORCED_LABEL/DECL_NONLOCAL labels, but that might penalize even code that
    doesn't care, so this instead just makes sure that for
    FORCED_LABEL/DECL_NONLOCAL labels that are being removed (and thus moved
    randomly) we remember in a hash_set the fact that those labels should be
    treated as removed for the purpose of the optimization, and later on
    handle those labels that way.

    2020-07-02  Jakub Jelinek  <jakub@redhat.com>

            PR tree-optimization/95857
            * tree-cfg.c (group_case_labels_stmt): When removing an unreachable
            base_bb, remember all forced and non-local labels on it and later
            treat those as if they have NULL label_to_block.  Formatting fix.
            Fix a comment typo.

            * gcc.dg/pr95857.c: New test.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug c/95857] [8/9/10 Regression] Silencing an unused label warning with (void)&&label; can make gcc segfault
  2020-06-24  7:17 [Bug c/95857] New: Silencing an unused label warning with (void)&&label; can make gcc segfault pskocik at gmail dot com
                   ` (3 preceding siblings ...)
  2020-07-02  9:39 ` cvs-commit at gcc dot gnu.org
@ 2020-07-02  9:40 ` jakub at gcc dot gnu.org
  2020-07-12  6:49 ` cvs-commit at gcc dot gnu.org
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-07-02  9:40 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95857

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|[8/9/10/11 Regression]      |[8/9/10 Regression]
                   |Silencing an unused label   |Silencing an unused label
                   |warning with (void)&&label; |warning with (void)&&label;
                   |can make gcc segfault       |can make gcc segfault

--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Fixed on the trunk so far.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug c/95857] [8/9/10 Regression] Silencing an unused label warning with (void)&&label; can make gcc segfault
  2020-06-24  7:17 [Bug c/95857] New: Silencing an unused label warning with (void)&&label; can make gcc segfault pskocik at gmail dot com
                   ` (4 preceding siblings ...)
  2020-07-02  9:40 ` [Bug c/95857] [8/9/10 " jakub at gcc dot gnu.org
@ 2020-07-12  6:49 ` cvs-commit at gcc dot gnu.org
  2020-09-16 19:22 ` cvs-commit at gcc dot gnu.org
  2020-09-17 17:52 ` jakub at gcc dot gnu.org
  7 siblings, 0 replies; 9+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2020-07-12  6:49 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95857

--- Comment #6 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-10 branch has been updated by Jakub Jelinek
<jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:1ba192b5b7d2509b833f288000f21d6294420ace

commit r10-8466-g1ba192b5b7d2509b833f288000f21d6294420ace
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Thu Jul 2 11:38:20 2020 +0200

    tree-cfg: Fix ICE with switch stmt to unreachable opt and forced labels
[PR95857]

    The following testcase ICEs, because during the cfg cleanup, we see:
      switch (i$e_11) <default: <L12> [33.33%], case -3: <lab2> [33.33%], case
0: <L10> [33.33%], case 2: <lab2> [33.33%]>
    ...
    lab2:
      __builtin_unreachable ();
    where lab2 is FORCED_LABEL.  The way it works, we go through the case
labels
    and when we reach the first one that points to gimple_seq_unreachable*
    basic block, we remove the edge (if any) from the switch bb to the bb
    containing the label and bbs reachable only through that edge we've just
    removed.  Once we do that, we must throw away all other cases that use
    the same label (or some other labels from the same bb we've removed the
edge
    to and the bb).  To avoid quadratic behavior, this is not done by walking
    all remaining cases immediately before removing, but only when processing
    them later.
    For normal labels this works, fine, if the label is in a deleted bb, it
will
    have NULL label_to_block and we handle that case, or, if the unreachable bb
    has some other edge to it, only the edge will be removed and not the bb,
    and again, find_edge will not find the edge and we only remove the case.
    And if a label would be to some other block, that other block wouldn't have
    been removed earlier because there would be still an edge from the switch
    block.
    Now, FORCED_LABEL (and I think DECL_NONLOCAL too) break this, because
    those labels aren't removed, but instead moved to some surrounding basic
    block.  So, when we later process those, when their gimple_seq_unreachable*
    basic block is removed, label_to_block will return some unrelated block
    (in the testcase the switch bb), so we decide to keep the case which
doesn't
    seem to be unreachable, but we don't really have an edge from the switch
    block to the block the label got moved to.

    I thought first about punting in gimple_seq_unreachable* on
    FORCED_LABEL/DECL_NONLOCAL labels, but that might penalize even code that
    doesn't care, so this instead just makes sure that for
    FORCED_LABEL/DECL_NONLOCAL labels that are being removed (and thus moved
    randomly) we remember in a hash_set the fact that those labels should be
    treated as removed for the purpose of the optimization, and later on
    handle those labels that way.

    2020-07-02  Jakub Jelinek  <jakub@redhat.com>

            PR tree-optimization/95857
            * tree-cfg.c (group_case_labels_stmt): When removing an unreachable
            base_bb, remember all forced and non-local labels on it and later
            treat those as if they have NULL label_to_block.  Formatting fix.
            Fix a comment typo.

            * gcc.dg/pr95857.c: New test.

    (cherry picked from commit 00f24f56732861d09a9716fa5b6b8a96c2289143)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug c/95857] [8/9/10 Regression] Silencing an unused label warning with (void)&&label; can make gcc segfault
  2020-06-24  7:17 [Bug c/95857] New: Silencing an unused label warning with (void)&&label; can make gcc segfault pskocik at gmail dot com
                   ` (5 preceding siblings ...)
  2020-07-12  6:49 ` cvs-commit at gcc dot gnu.org
@ 2020-09-16 19:22 ` cvs-commit at gcc dot gnu.org
  2020-09-17 17:52 ` jakub at gcc dot gnu.org
  7 siblings, 0 replies; 9+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2020-09-16 19:22 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95857

--- Comment #7 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-9 branch has been updated by Jakub Jelinek
<jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:62714a106493d0f1f22ff98c2dff2204f09cfcc0

commit r9-8903-g62714a106493d0f1f22ff98c2dff2204f09cfcc0
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Thu Jul 2 11:38:20 2020 +0200

    tree-cfg: Fix ICE with switch stmt to unreachable opt and forced labels
[PR95857]

    The following testcase ICEs, because during the cfg cleanup, we see:
      switch (i$e_11) <default: <L12> [33.33%], case -3: <lab2> [33.33%], case
0: <L10> [33.33%], case 2: <lab2> [33.33%]>
    ...
    lab2:
      __builtin_unreachable ();
    where lab2 is FORCED_LABEL.  The way it works, we go through the case
labels
    and when we reach the first one that points to gimple_seq_unreachable*
    basic block, we remove the edge (if any) from the switch bb to the bb
    containing the label and bbs reachable only through that edge we've just
    removed.  Once we do that, we must throw away all other cases that use
    the same label (or some other labels from the same bb we've removed the
edge
    to and the bb).  To avoid quadratic behavior, this is not done by walking
    all remaining cases immediately before removing, but only when processing
    them later.
    For normal labels this works, fine, if the label is in a deleted bb, it
will
    have NULL label_to_block and we handle that case, or, if the unreachable bb
    has some other edge to it, only the edge will be removed and not the bb,
    and again, find_edge will not find the edge and we only remove the case.
    And if a label would be to some other block, that other block wouldn't have
    been removed earlier because there would be still an edge from the switch
    block.
    Now, FORCED_LABEL (and I think DECL_NONLOCAL too) break this, because
    those labels aren't removed, but instead moved to some surrounding basic
    block.  So, when we later process those, when their gimple_seq_unreachable*
    basic block is removed, label_to_block will return some unrelated block
    (in the testcase the switch bb), so we decide to keep the case which
doesn't
    seem to be unreachable, but we don't really have an edge from the switch
    block to the block the label got moved to.

    I thought first about punting in gimple_seq_unreachable* on
    FORCED_LABEL/DECL_NONLOCAL labels, but that might penalize even code that
    doesn't care, so this instead just makes sure that for
    FORCED_LABEL/DECL_NONLOCAL labels that are being removed (and thus moved
    randomly) we remember in a hash_set the fact that those labels should be
    treated as removed for the purpose of the optimization, and later on
    handle those labels that way.

    2020-07-02  Jakub Jelinek  <jakub@redhat.com>

            PR tree-optimization/95857
            * tree-cfg.c (group_case_labels_stmt): When removing an unreachable
            base_bb, remember all forced and non-local labels on it and later
            treat those as if they have NULL label_to_block.  Formatting fix.
            Fix a comment typo.

            * gcc.dg/pr95857.c: New test.

    (cherry picked from commit 00f24f56732861d09a9716fa5b6b8a96c2289143)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug c/95857] [8/9/10 Regression] Silencing an unused label warning with (void)&&label; can make gcc segfault
  2020-06-24  7:17 [Bug c/95857] New: Silencing an unused label warning with (void)&&label; can make gcc segfault pskocik at gmail dot com
                   ` (6 preceding siblings ...)
  2020-09-16 19:22 ` cvs-commit at gcc dot gnu.org
@ 2020-09-17 17:52 ` jakub at gcc dot gnu.org
  7 siblings, 0 replies; 9+ messages in thread
From: jakub at gcc dot gnu.org @ 2020-09-17 17:52 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95857

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|ASSIGNED                    |RESOLVED
         Resolution|---                         |FIXED

--- Comment #8 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Fixed for 8.5 in r8-10508-gcac9ff3a809f90236dc737a51eb8ff0e9088783c and by the
above commit for 9.4+ too.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2020-09-17 17:52 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-24  7:17 [Bug c/95857] New: Silencing an unused label warning with (void)&&label; can make gcc segfault pskocik at gmail dot com
2020-06-24  7:54 ` [Bug c/95857] [8/9/10/11 Regression] " rguenth at gcc dot gnu.org
2020-06-29 10:04 ` jakub at gcc dot gnu.org
2020-06-29 19:40 ` jakub at gcc dot gnu.org
2020-07-02  9:39 ` cvs-commit at gcc dot gnu.org
2020-07-02  9:40 ` [Bug c/95857] [8/9/10 " jakub at gcc dot gnu.org
2020-07-12  6:49 ` cvs-commit at gcc dot gnu.org
2020-09-16 19:22 ` cvs-commit at gcc dot gnu.org
2020-09-17 17:52 ` jakub at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).