diff mbox

[Ada] Clear column information on EH cleanup cond branch instructions

Message ID 201308132144.39593.ebotcazou@adacore.com
State New
Headers show

Commit Message

Eric Botcazou Aug. 13, 2013, 7:44 p.m. UTC
This change ensures that conditional branch instructions that are generated
as part of the exception handling circuitry for cleanup actions are marked 
specially, more precisely by clearing the column number.  This makes it 
possible for coverage analysis tools to properly ignore them, and ensures they 
are not mistaken for conditional branches associated with source decisions.

Tested on x86_64-suse-linux, applied on the mainline.


2013-08-13  Thomas Quinot  <quinot@adacore.com>

	* gcc-interface/trans.c (Handled_Sequence_Of_Statements_to_gnu): If
	there is no End_Label, attach cleanup actions to the sloc of the HSS
	node instead.
	(Exception_Handler_to_gnu_zcx): Associate cleanup actions with the sloc
	of the handler itself.
	(add_cleanup): Clear column information in sloc of cleanup actions.
	(Sloc_to_locus1): New static function.
	(Sloc_to_locus): Call it.
	(set_expr_location_from_node1): New static function.
	(set_expr_location_from_node): Call it.
diff mbox

Patch

Index: gcc-interface/trans.c
===================================================================
--- gcc-interface/trans.c	(revision 201700)
+++ gcc-interface/trans.c	(working copy)
@@ -257,6 +257,8 @@  static tree pos_to_constructor (Node_Id,
 static void validate_unchecked_conversion (Node_Id);
 static tree maybe_implicit_deref (tree);
 static void set_expr_location_from_node (tree, Node_Id);
+static void set_expr_location_from_node1 (tree, Node_Id, bool);
+static bool Sloc_to_locus1 (Source_Ptr, location_t *, bool);
 static bool set_end_locus_from_node (tree, Node_Id);
 static void set_gnu_expr_location_from_node (tree, Node_Id);
 static int lvalue_required_p (Node_Id, tree, bool, bool, bool);
@@ -4471,6 +4473,10 @@  Handled_Sequence_Of_Statements_to_gnu (N
   tree gnu_result;
   tree gnu_expr;
   Node_Id gnat_temp;
+  /* Node providing the sloc for the cleanup actions.  */
+  Node_Id gnat_cleanup_loc_node = (Present (End_Label (gnat_node)) ?
+                                   End_Label (gnat_node) :
+                                   gnat_node);
 
   /* The GCC exception handling mechanism can handle both ZCX and SJLJ schemes
      and we have our own SJLJ mechanism.  To call the GCC mechanism, we call
@@ -4520,7 +4526,7 @@  Handled_Sequence_Of_Statements_to_gnu (N
 
       /* When we exit this block, restore the saved value.  */
       add_cleanup (build_call_n_expr (set_jmpbuf_decl, 1, gnu_jmpsave_decl),
-		   End_Label (gnat_node));
+		   gnat_cleanup_loc_node);
     }
 
   /* If we are to call a function when exiting this block, add a cleanup
@@ -4528,7 +4534,7 @@  Handled_Sequence_Of_Statements_to_gnu (N
      so we must register this cleanup after the EH cleanup just above.  */
   if (at_end)
     add_cleanup (build_call_n_expr (gnat_to_gnu (At_End_Proc (gnat_node)), 0),
-		 End_Label (gnat_node));
+		 gnat_cleanup_loc_node);
 
   /* Now build the tree for the declarations and statements inside this block.
      If this is SJLJ, set our jmp_buf as the current buffer.  */
@@ -4641,14 +4647,18 @@  Handled_Sequence_Of_Statements_to_gnu (N
       /* Now make the TRY_CATCH_EXPR for the block.  */
       gnu_result = build2 (TRY_CATCH_EXPR, void_type_node,
 			   gnu_inner_block, gnu_handlers);
-      /* Set a location.  We need to find a uniq location for the dispatching
+      /* Set a location.  We need to find a unique location for the dispatching
 	 code, otherwise we can get coverage or debugging issues.  Try with
 	 the location of the end label.  */
       if (Present (End_Label (gnat_node))
 	  && Sloc_to_locus (Sloc (End_Label (gnat_node)), &locus))
 	SET_EXPR_LOCATION (gnu_result, locus);
       else
-	set_expr_location_from_node (gnu_result, gnat_node);
+        /* Clear column information so that the exception handler of an
+           implicit transient block does not incorrectly inherit the slocs
+           of a decision, which would otherwise confuse control flow based
+           coverage analysis tools.  */
+	set_expr_location_from_node1 (gnu_result, gnat_node, True);
     }
   else
     gnu_result = gnu_inner_block;
@@ -4843,9 +4853,10 @@  Exception_Handler_to_gnu_zcx (Node_Id gn
   add_stmt_with_node (build_call_n_expr (begin_handler_decl, 1,
 					 gnu_incoming_exc_ptr),
 		      gnat_node);
-  /* ??? We don't seem to have an End_Label at hand to set the location.  */
+  /* We don't have an End_Label at hand to set the location of the cleanup
+     actions, so we use that of the exception handler itself instead.  */
   add_cleanup (build_call_n_expr (end_handler_decl, 1, gnu_incoming_exc_ptr),
-	       Empty);
+	       gnat_node);
   add_stmt_list (Statements (gnat_node));
   gnat_poplevel ();
 
@@ -7397,13 +7408,15 @@  mark_visited (tree t)
 }
 
 /* Add GNU_CLEANUP, a cleanup action, to the current code group and
-   set its location to that of GNAT_NODE if present.  */
+   set its location to that of GNAT_NODE if present, but with column info
+   cleared so that conditional branches generated as part of the cleanup
+   code do not interfere with coverage analysis tools.  */
 
 static void
 add_cleanup (tree gnu_cleanup, Node_Id gnat_node)
 {
   if (Present (gnat_node))
-    set_expr_location_from_node (gnu_cleanup, gnat_node);
+    set_expr_location_from_node1 (gnu_cleanup, gnat_node, True);
   append_to_statement_list (gnu_cleanup, &current_stmt_group->cleanups);
 }
 
@@ -9018,10 +9031,11 @@  maybe_implicit_deref (tree exp)
 
 /* Convert SLOC into LOCUS.  Return true if SLOC corresponds to a source code
    location and false if it doesn't.  In the former case, set the Gigi global
-   variable REF_FILENAME to the simple debug file name as given by sinput.  */
+   variable REF_FILENAME to the simple debug file name as given by sinput.
+   If clear_column is True, set column information to 0.  */
 
-bool
-Sloc_to_locus (Source_Ptr Sloc, location_t *locus)
+static bool
+Sloc_to_locus1 (Source_Ptr Sloc, location_t *locus, bool clear_column)
 {
   if (Sloc == No_Location)
     return false;
@@ -9035,7 +9049,7 @@  Sloc_to_locus (Source_Ptr Sloc, location
     {
       Source_File_Index file = Get_Source_File_Index (Sloc);
       Logical_Line_Number line = Get_Logical_Line_Number (Sloc);
-      Column_Number column = Get_Column_Number (Sloc);
+      Column_Number column = (clear_column ? 0 : Get_Column_Number (Sloc));
       struct line_map *map = LINEMAPS_ORDINARY_MAP_AT (line_table, file - 1);
 
       /* We can have zero if pragma Source_Reference is in effect.  */
@@ -9054,20 +9068,36 @@  Sloc_to_locus (Source_Ptr Sloc, location
   return true;
 }
 
+/* Similar to the above, not clearing the column information.  */
+
+bool
+Sloc_to_locus (Source_Ptr Sloc, location_t *locus)
+{
+  return Sloc_to_locus1 (Sloc, locus, False);
+}
+
 /* Similar to set_expr_location, but start with the Sloc of GNAT_NODE and
    don't do anything if it doesn't correspond to a source location.  */
 
 static void
-set_expr_location_from_node (tree node, Node_Id gnat_node)
+set_expr_location_from_node1 (tree node, Node_Id gnat_node, bool clear_column)
 {
   location_t locus;
 
-  if (!Sloc_to_locus (Sloc (gnat_node), &locus))
+  if (!Sloc_to_locus1 (Sloc (gnat_node), &locus, clear_column))
     return;
 
   SET_EXPR_LOCATION (node, locus);
 }
 
+/* Similar to the above, not clearing the column information.  */
+
+static void
+set_expr_location_from_node (tree node, Node_Id gnat_node)
+{
+  set_expr_location_from_node1 (node, gnat_node, False);
+}
+
 /* More elaborate version of set_expr_location_from_node to be used in more
    general contexts, for example the result of the translation of a generic
    GNAT node.  */