[Bug c++/80460] Incorrect fallthrough warning after [[noreturn]] function inside always-true conditional

2021-01-26 Thread mpolacek at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80460

Marek Polacek  changed:

   What|Removed |Added

 Status|ASSIGNED|NEW
 CC||mpolacek at gcc dot gnu.org

[Bug c++/80460] Incorrect fallthrough warning after [[noreturn]] function inside always-true conditional

2017-04-19 Thread thiago at kde dot org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80460

--- Comment #7 from Thiago Macieira  ---
(In reply to Jakub Jelinek from comment #1)
> The warning is done before optimizations (except GENERIC opts), and can
> hardly be done much later.

I imagined it would be the case. Treat this as low priority.

I've added the [[fallthrough]] to the source code where this appeared to
silence the warning. Arguably, the author should have used Q_UNREACHABLE()
there too, not Q_ASSERT(!"message").

[Bug c++/80460] Incorrect fallthrough warning after [[noreturn]] function inside always-true conditional

2017-04-19 Thread mpolacek at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80460

--- Comment #6 from Marek Polacek  ---
But even that is not enough for

  switch (i) 
{   
case 0:
  goto X;
  if (0) // nowarn
X:
nop (); 
  else
die (); 
case 1:; 
  i++;
}

because we need to remember whether the then branch contained any labels.

[Bug c++/80460] Incorrect fallthrough warning after [[noreturn]] function inside always-true conditional

2017-04-19 Thread mpolacek at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80460

--- Comment #5 from Marek Polacek  ---
Actually, nothing I imagined wouldn't work for the case when the else branch is
dead :(.

A patch that helps with bogus warning for dead then branches:
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1912,6 +1912,7 @@ collect_fallthrough_labels (gimple_stmt_iterator *gsi_p,
   if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_COND)
{
  gcond *cond_stmt = as_a  (gsi_stmt (*gsi_p));
+ bool false_p = gimple_cond_false_p (cond_stmt);
  tree false_lab = gimple_cond_false_label (cond_stmt);
  location_t if_loc = gimple_location (cond_stmt);

@@ -1956,7 +1957,9 @@ collect_fallthrough_labels (gimple_stmt_iterator *gsi_p,
= gimple_call_internal_p (gsi_stmt (*gsi_p), IFN_FALLTHROUGH);
  gsi_next (gsi_p);
  tree goto_dest = gimple_goto_dest (gsi_stmt (*gsi_p));
- if (!fallthru_before_dest)
+ /* If FALSE_P, the then branch is dead, do not collect
+the label.  */
+ if (!fallthru_before_dest && !false_p)
{
  struct label_entry l = { goto_dest, if_loc };
  labels->safe_push (l);

[Bug c++/80460] Incorrect fallthrough warning after [[noreturn]] function inside always-true conditional

2017-04-19 Thread mpolacek at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80460

Marek Polacek  changed:

   What|Removed |Added

 Status|UNCONFIRMED |ASSIGNED
   Last reconfirmed||2017-04-19
   Assignee|unassigned at gcc dot gnu.org  |mpolacek at gcc dot 
gnu.org
 Ever confirmed|0   |1

--- Comment #4 from Marek Polacek  ---
I think it shouldn't affect those at all.

Another idea is to return fake FALLTHROUGH () if the else branch is dead.  Let
me see.

extern void die (void) __attribute__((noreturn));
extern void nop (void);

void
f (int i)
{
  switch (i)
{
case 0:
  if (1)
die ();
  else
nop ();
case 1:;
  i++;
}

  switch (i)
{
case 0:
  if (0)
die ();
  else
nop ();
case 1:;
  i++;
}

  switch (i)
{
case 0:
  if (1)
nop ();
  else
die ();
case 1:;
  i++;
}

  switch (i)
{
case 0:
  if (0)
nop ();
  else
die ();
case 1:;
  i++;
}
}

[Bug c++/80460] Incorrect fallthrough warning after [[noreturn]] function inside always-true conditional

2017-04-19 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80460

--- Comment #3 from Jakub Jelinek  ---
Would that disable warning for:
if (0)
  switch (x)
{
case 5:
  x++;
case 6:
  x += 17;
  break;
}
?
Perhaps that is ok.  Wouldn't that also disable warning for:
  if (x > 24)
goto lab;
  if (0)
{
 lab:
  switch (x)
{
case 37:
  x++;
case 38:
  x += 18;
  break;
}
}
?  On the latter we should warn...

[Bug c++/80460] Incorrect fallthrough warning after [[noreturn]] function inside always-true conditional

2017-04-19 Thread mpolacek at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80460

--- Comment #2 from Marek Polacek  ---
I thought we could (in collect_fallthrough_labels) look at the GIMPLE_COND, see
if its OP0 and OP1 are INTEGER_CSTs, and if they are, determine which branch
cannot be taken, and then maybe don't do
  labels->safe_push (l);
which should suppress the warning.

[Bug c++/80460] Incorrect fallthrough warning after [[noreturn]] function inside always-true conditional

2017-04-19 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80460

Jakub Jelinek  changed:

   What|Removed |Added

 CC||jakub at gcc dot gnu.org,
   ||mpolacek at gcc dot gnu.org

--- Comment #1 from Jakub Jelinek  ---
The warning is done before optimizations (except GENERIC opts), and can hardly
be done much later.
In *.original we have:
case 0:;
<;
case 1:;
<;
and what the warning code sees in *.gimple when it is performed is:
  switch (i) , case 0: , case 1: >
  :
  if (1 != 0) goto ; else goto ;
  :
  qt_assert ();
  :
  qt_noop ();
  :
  qt_noop ();
  :

So, to get rid of the warning, we'd need to do some optimization already during
the gimplification, perhaps if we have COND_EXPR with constant condition scan
the non-active branch and if there are no labels in there, don't try to
gimplify it at all?  Walking it for all COND_EXPRs with constant condition
would have undesirable compile time complexity though if there are any labels.
And trying to prove if some code is reachable or not reachable at
gimplification time is not really doable, we don't have CFG.
Moving the warning later is also undesirable, because the IL would be mangled
and wouldn't match the original source the way we need.