[COMMITTED,50/51] ada: Avoid definition of unused label for LOOP_STMT

Message ID 20260602084541.3829876-50-poulhies@adacore.com
State Committed
Headers
Series [COMMITTED,01/51] ada: Rename Private_Component function |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm fail Patch failed to apply
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-aarch64-bootstrap fail Patch failed to apply
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 fail Patch failed to apply

Commit Message

Marc Poulhiès June 2, 2026, 8:45 a.m. UTC
  The gimplification of LOOP_STMT has a systematic end label definition,
that may be unused. For example, an endless loop maybe gimplified to:

      <D.5765>:
      # USE = anything
      # CLB = anything
      totoD.5747 ();
      goto <D.5765>;
      <D.5749>:

Later, the gimple_seq_may_fallthru() will decide that this block can
fallthru as the last statement is a single label that may be jumped to
from somewhere else.

Only defining this label if we also emit jumps to it helps the compiler
correctly decide if the block can fallthru or not.

In particular, if a function, with a local object needing finalization
and the No_Return aspect, is an endless loop then the spurious warning
that the function is still returning is not emitted anymore.

gcc/ada/ChangeLog:

	* gcc-interface/trans.cc (gnat_to_gnu) <N_Exit_Statement>: Mark
	the label tree as used.
	(gnat_gimplify_stmt) <LOOP_STMT>: Do not emit end label
	definition in unused.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/gcc-interface/trans.cc | 32 ++++++++++++++++++++------------
 1 file changed, 20 insertions(+), 12 deletions(-)
  

Patch

diff --git a/gcc/ada/gcc-interface/trans.cc b/gcc/ada/gcc-interface/trans.cc
index 5140ed8bbfd..7df32d67ea9 100644
--- a/gcc/ada/gcc-interface/trans.cc
+++ b/gcc/ada/gcc-interface/trans.cc
@@ -7993,13 +7993,17 @@  gnat_to_gnu (Node_Id gnat_node)
       break;
 
     case N_Exit_Statement:
-      gnu_result
-	= build2 (EXIT_STMT, void_type_node,
-		  (Present (Condition (gnat_node))
-		   ? gnat_to_gnu (Condition (gnat_node)) : NULL_TREE),
-		  (Present (Name (gnat_node))
-		   ? get_gnu_tree (Entity (Name (gnat_node)))
-		   : LOOP_STMT_LABEL (gnu_loop_stack->last ()->stmt)));
+      {
+	tree end_loop_label = Present (Name (gnat_node))
+	  ? get_gnu_tree (Entity (Name (gnat_node)))
+	  : LOOP_STMT_LABEL (gnu_loop_stack->last ()->stmt);
+	gnu_result
+	  = build2 (EXIT_STMT, void_type_node,
+	      (Present (Condition (gnat_node))
+		? gnat_to_gnu (Condition (gnat_node)) : NULL_TREE),
+		end_loop_label);
+	TREE_USED (end_loop_label) = 1;
+      }
       break;
 
     case N_Simple_Return_Statement:
@@ -9532,6 +9536,8 @@  gnat_gimplify_stmt (tree *stmt_p)
 	    gnu_cond
 	      = build3 (COND_EXPR, void_type_node, gnu_cond, NULL_TREE,
 			build1 (GOTO_EXPR, void_type_node, gnu_end_label));
+
+            TREE_USED (gnu_end_label) = 1;
 	  }
 
 	/* Set to emit the statements of the loop.  */
@@ -9541,8 +9547,9 @@  gnat_gimplify_stmt (tree *stmt_p)
 	   end label if there's a top condition, then the update if it's at
 	   the top, then the body of the loop, then a conditional jump to
 	   the end label if there's a bottom condition, then the update if
-	   it's at the bottom, and finally a jump to the start label and the
-	   definition of the end label.  */
+	   it's at the bottom, and finally a jump to the start label and if
+	   there's a top or bottom condition, the definition of the end
+	   label.  */
 	append_to_statement_list (build1 (LABEL_EXPR, void_type_node,
 					  gnu_start_label),
 				  stmt_p);
@@ -9565,9 +9572,10 @@  gnat_gimplify_stmt (tree *stmt_p)
 	SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (gnu_end_label));
 	append_to_statement_list (t, stmt_p);
 
-	append_to_statement_list (build1 (LABEL_EXPR, void_type_node,
-					  gnu_end_label),
-				  stmt_p);
+	if (TREE_USED (gnu_end_label))
+	  append_to_statement_list (build1 (LABEL_EXPR, void_type_node,
+					    gnu_end_label),
+				    stmt_p);
 	return GS_OK;
       }