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

--- Comment #18 from Richard Biener <rguenth at gcc dot gnu.org> ---
We can warn at CFG construction time. Note the ??? though, we'd want to improve
here to avoid duplicate diagnostics.  Tricky cases:

/* Unreachable region entry has a predecessor (backedge).  */
void foo()
{
  return;
  for (int i = 0; i < 5; ++i)
    ;
}

/* Unreachable region not backwards reachable from exit.  */
void bar1()
{
  return;
  __builtin_abort ();
}
void bar2()
{
  return ;
  for (;;);
}

/* Unreachable code in if (0) block.  */
void baz(int *p)
{
   if (0)
     {
        return;
        *p = 0;
     }
}




bootstrap with the prototype currently fails in libgomp:

/home/rguenther/src/trunk/libgomp/oacc-plugin.c: In function
'GOMP_PLUGIN_acc_default_dim':
/home/rguenther/src/trunk/libgomp/oacc-plugin.c:65:7: error: statement is not
reachable [-Werror]
   65 |       return -1;
      |       ^~~~~~
/home/rguenther/src/trunk/libgomp/oacc-profiling.c: In function
'acc_prof_register':
/home/rguenther/src/trunk/libgomp/oacc-profiling.c:354:7: error: statement is
not reachable [-Werror]
  354 |       __builtin_unreachable ();
      |       ^~~~~~~~~~~~~~~~~~~~~
/home/rguenther/src/trunk/libgomp/oacc-profiling.c: In function
'acc_prof_unregister':
/home/rguenther/src/trunk/libgomp/oacc-profiling.c:475:7: error: statement is
not reachable [-Werror]
  475 |       __builtin_unreachable ();
      |       ^~~~~~~~~~~~~~~~~~~~~

the latter two are an issue with inital CFG construction I think, where
group_case_labels turns

void bar (foo x)
{
  <bb 2> :
  switch (x) <default: <L2>, case 0: <L0>, case 1: <L1>>

  <bb 3> :
<L0>:
  goto <L2>;

  <bb 4> :
<L1>:
  __builtin_unreachable ();

  <bb 5> :
<L2>:
  return;

into the following with BB 4 now unreachable.

void bar (foo x)
{
  <bb 2> :
  switch (x) <default: <L2>, case 0: <L0>>

  <bb 3> :
<L0>:
  goto <L2>;

  <bb 4> :
<L1>:
  __builtin_unreachable ();

  <bb 5> :
<L2>:
  return;

The C++ FE also warns about the implicit return in main when there's a
preceeding one (the C frontend "appropriately" assigns an internal
location which supresses the warning).


diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index b3a27bcd17c..64ab2607c56 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -242,7 +242,8 @@ build_gimple_cfg (gimple_seq seq)
   /* Group case nodes to reduce the number of edges.
      We do this after cleaning up dead labels because otherwise we miss
      a lot of obvious case merging opportunities.  */
-  group_case_labels ();
+  /* ???  This interferes with unreachable code diagnostics.  */
+  //group_case_labels ();

   /* Create the edges of the flowgraph.  */
   discriminator_per_locus = new hash_table<locus_discrim_hasher> (13);
@@ -374,6 +375,24 @@ execute_build_cfg (void)
       fprintf (dump_file, "Scope blocks:\n");
       dump_scope_blocks (dump_file, dump_flags);
     }
+
+  find_unreachable_blocks ();
+  basic_block bb;
+  FOR_EACH_BB_FN (bb, cfun)
+    if (!(bb->flags & BB_REACHABLE))
+      for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
+          gsi_next (&gsi))
+       {
+         if ((LOCATION_LOCUS (gimple_location (gsi_stmt (gsi)))
+              > BUILTINS_LOCATION)
+             && !gimple_no_warning_p (gsi_stmt (gsi)))
+           warning_at (gimple_location (gsi_stmt (gsi)), 0,
+                       "statement is not reachable");
+         /* ???  Mark blocks reachable from here.  And even better make
+            sure to process entries to unreachable regions first.  */
+         break;
+       }
+
   cleanup_tree_cfg ();

   bb_to_omp_idx.release ();

Reply via email to