[pushed:,r15-7317] sarif-replay: support "cached" logical locations [§3.33.3]

Message ID 20250201134511.472000-1-dmalcolm@redhat.com
State New
Headers
Series [pushed:,r15-7317] sarif-replay: support "cached" logical locations [§3.33.3] |

Checks

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

Commit Message

David Malcolm Feb. 1, 2025, 1:45 p.m. UTC
  Some SARIF files offload most of the properties within logical locations
in the results to an array of "cached" instances in
theRun.logicalLocations, so the information can be consolidated (and to
support the "parentIndex" property, which is PR 116176).

Support such files in sarif-replay.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r15-7317-gcf24c0fa53870d.

gcc/ChangeLog:
	* libsarifreplay.cc (sarif_replayer::handle_run_obj): Pass run to
	handle_result_obj.
	(sarif_replayer::handle_result_obj): Add run_obj param and pass it
	to handle_location_object and handle_thread_flow_object.
	(sarif_replayer::handle_thread_flow_object): Add run_obj param and
	pass it to handle_thread_flow_location_object.
	(sarif_replayer::handle_thread_flow_location_object): Add run_obj
	param and pass it to handle_location_object.
	(sarif_replayer::handle_location_object): Add run_obj param and
	pass it to handle_logical_location_object.
	(sarif_replayer::handle_logical_location_object): Add run_obj
	param.  If the run_obj is non-null and has "logicalLocations",
	then use these "cached" logical locations if we see an "index"
	property, as per §3.33.3

gcc/testsuite/ChangeLog:
	* sarif-replay.dg/2.1.0-invalid/3.33.3-index-out-of-range.sarif:
	New test.
	* sarif-replay.dg/2.1.0-valid/spec-example-4.sarif: Update expected
	output to reflect that we now find the function name for the
	events in the path.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/libsarifreplay.cc                         | 70 +++++++++++++++++--
 .../3.33.3-index-out-of-range.sarif           | 32 +++++++++
 .../2.1.0-valid/spec-example-4.sarif          |  2 +-
 3 files changed, 96 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/sarif-replay.dg/2.1.0-invalid/3.33.3-index-out-of-range.sarif
  

Patch

diff --git a/gcc/libsarifreplay.cc b/gcc/libsarifreplay.cc
index eb829064194d..61d9565588ed 100644
--- a/gcc/libsarifreplay.cc
+++ b/gcc/libsarifreplay.cc
@@ -277,6 +277,7 @@  private:
   // "result" object (§3.27)
   enum status
   handle_result_obj (const json::object &result_obj,
+		     const json::object &run_obj,
 		     const json::object &tool_obj);
   json::result<enum diagnostic_level, enum status>
   get_level_from_level_str (const json::string &level_str);
@@ -284,6 +285,7 @@  private:
   // "location" object (§3.28)
   enum status
   handle_location_object (const json::object &location_obj,
+			  const json::object &run_obj,
 			  libgdiagnostics::physical_location &out_physical_loc,
 			  libgdiagnostics::logical_location &out_logical_loc);
 
@@ -301,16 +303,19 @@  private:
   // "logicalLocation" object (§3.33)
   enum status
   handle_logical_location_object (const json::object &logical_loc_obj,
+				  const json::object *run_obj,
 				  libgdiagnostics::logical_location &out);
 
   // "threadFlow" object (§3.37)
   enum status
   handle_thread_flow_object (const json::object &thread_flow_obj,
+			     const json::object &run_obj,
 			     libgdiagnostics::execution_path &out);
 
   // "threadFlowLocation" object (§3.38)
   enum status
   handle_thread_flow_location_object (const json::object &tflow_loc_obj,
+				      const json::object &run_obj,
 				      libgdiagnostics::execution_path &out);
 
   // reportingDescriptor lookup (§3.52.3)
@@ -806,7 +811,9 @@  sarif_replayer::handle_run_obj (const json::object &run_obj)
 		= require_object_for_element (*element, prop_results);
 	      if (!result_obj)
 		return status::err_invalid_sarif;
-	      enum status s = handle_result_obj (*result_obj, *tool_obj);
+	      enum status s = handle_result_obj (*result_obj,
+						 run_obj,
+						 *tool_obj);
 	      if (s != status::ok)
 		return s;
 	    }
@@ -974,6 +981,7 @@  sarif_replayer::get_level_from_level_str (const json::string &level_str)
 
 enum status
 sarif_replayer::handle_result_obj (const json::object &result_obj,
+				   const json::object &run_obj,
 				   const json::object &tool_obj)
 {
   const json::object *rule_obj = nullptr;
@@ -1025,7 +1033,7 @@  sarif_replayer::handle_result_obj (const json::object &result_obj,
 	= require_object_for_element (*locations_arr->get (0), locations_prop);
       if (!location_obj)
 	return status::err_invalid_sarif;
-      enum status s = handle_location_object (*location_obj,
+      enum status s = handle_location_object (*location_obj, run_obj,
 					      physical_loc,
 					      logical_loc);
       if (s != status::ok)
@@ -1059,7 +1067,7 @@  sarif_replayer::handle_result_obj (const json::object &result_obj,
 						  prop_thread_flows);
 		  if (!thread_flow_obj)
 		    return status::err_invalid_sarif;
-		  handle_thread_flow_object (*thread_flow_obj, path);
+		  handle_thread_flow_object (*thread_flow_obj, run_obj, path);
 		}
 	    }
 	}
@@ -1104,7 +1112,7 @@  sarif_replayer::handle_result_obj (const json::object &result_obj,
 					  prop_related_locations);
 	  if (!location_obj)
 	    return status::err_invalid_sarif;
-	  enum status s = handle_location_object (*location_obj,
+	  enum status s = handle_location_object (*location_obj, run_obj,
 						  physical_loc,
 						  logical_loc);
 	  if (s != status::ok)
@@ -1438,6 +1446,7 @@  lookup_plain_text_within_result_message (const json::object *tool_component_obj,
 
 enum status
 sarif_replayer::handle_thread_flow_object (const json::object &thread_flow_obj,
+					   const json::object &run_obj,
 					   libgdiagnostics::execution_path &out)
 {
   const property_spec_ref locations ("threadFlow", "locations", "3.37.6");
@@ -1454,7 +1463,7 @@  sarif_replayer::handle_thread_flow_object (const json::object &thread_flow_obj,
 	= require_object_for_element (*location, locations);
       if (!tflow_loc_obj)
 	return status::err_invalid_sarif;
-      handle_thread_flow_location_object (*tflow_loc_obj, out);
+      handle_thread_flow_location_object (*tflow_loc_obj, run_obj, out);
     }
 
   return status::ok;
@@ -1466,6 +1475,7 @@  sarif_replayer::handle_thread_flow_object (const json::object &thread_flow_obj,
 enum status
 sarif_replayer::
 handle_thread_flow_location_object (const json::object &tflow_loc_obj,
+				    const json::object &run_obj,
 				    libgdiagnostics::execution_path &path)
 {
   libgdiagnostics::physical_location physical_loc;
@@ -1479,8 +1489,8 @@  handle_thread_flow_location_object (const json::object &tflow_loc_obj,
 							       location_prop))
     {
       /* location object (§3.28).  */
-      enum status s
-	= handle_location_object (*location_obj, physical_loc, logical_loc);
+      enum status s = handle_location_object (*location_obj, run_obj,
+					      physical_loc, logical_loc);
       if (s != status::ok)
 	return s;
 
@@ -1552,6 +1562,7 @@  handle_thread_flow_location_object (const json::object &tflow_loc_obj,
 enum status
 sarif_replayer::
 handle_location_object (const json::object &location_obj,
+			const json::object &run_obj,
 			libgdiagnostics::physical_location &out_physical_loc,
 			libgdiagnostics::logical_location &out_logical_loc)
 {
@@ -1586,6 +1597,7 @@  handle_location_object (const json::object &location_obj,
 	  if (!logical_loc_obj)
 	    return status::err_invalid_sarif;
 	  enum status s = handle_logical_location_object (*logical_loc_obj,
+							  &run_obj,
 							  out_logical_loc);
 	  if (s != status::ok)
 	    return s;
@@ -1743,6 +1755,10 @@  handle_region_object (const json::object &region_obj,
 }
 
 /* Handle a "logicalLocation" object (§3.33), using it to populate OUT.
+
+   If RUN_OBJ is non-null, and has "logicalLocations", then use it if we
+   see an "index" property.
+
    Known limitations:
    - doesn't yet handle "parentIndex" property (§3.33.8)
 */
@@ -1750,8 +1766,48 @@  handle_region_object (const json::object &region_obj,
 enum status
 sarif_replayer::
 handle_logical_location_object (const json::object &logical_loc_obj,
+				const json::object *run_obj,
 				libgdiagnostics::logical_location &out)
 {
+  if (run_obj)
+    {
+      const property_spec_ref name_prop ("logicalLocation", "index", "3.33.3");
+      if (auto index_js_int
+	    = get_optional_property<json::integer_number> (logical_loc_obj,
+							   name_prop))
+	{
+	  const long index = index_js_int->get ();
+	  /* If "index" is present, then there must be theRun.logicalLocations
+	     and it must have a cached object at that index.  */
+	  const property_spec_ref run_logical_locs_prop
+	    ("run", "logicalLocations", "3.14.17");
+	  if (auto logical_locs_arr
+		= get_required_property<json::array> (*run_obj,
+						      run_logical_locs_prop))
+	    {
+	      /* "index" must be in range */
+	      if (index < 0 || index >= (long)logical_locs_arr->length ())
+		return report_invalid_sarif (*index_js_int, name_prop,
+					     "index value %li is out of range"
+					     " for theRun.logicalLocations",
+					     index);
+
+	      json::value *element = logical_locs_arr->get (index);
+
+	      if (const json::object *obj
+		    = require_object (*element,run_logical_locs_prop))
+		{
+		  /* Use this "cached" object instead.
+		     Pass nullptr for the run object so that we
+		     don't recurse.  */
+		  return handle_logical_location_object (*obj, nullptr, out);
+		}
+	    }
+	}
+    }
+
+  // Otherwise use the properties from LOGICAL_LOC_OBJ.
+
   const property_spec_ref name_prop ("logicalLocation", "name", "3.33.4");
   const char *short_name = nullptr;
   if (auto name_jstr = get_optional_property<json::string> (logical_loc_obj,
diff --git a/gcc/testsuite/sarif-replay.dg/2.1.0-invalid/3.33.3-index-out-of-range.sarif b/gcc/testsuite/sarif-replay.dg/2.1.0-invalid/3.33.3-index-out-of-range.sarif
new file mode 100644
index 000000000000..ef22614776c5
--- /dev/null
+++ b/gcc/testsuite/sarif-replay.dg/2.1.0-invalid/3.33.3-index-out-of-range.sarif
@@ -0,0 +1,32 @@ 
+{
+    "version": "2.1.0",
+    "runs": [
+	{
+	    "tool": {
+		"driver": {
+		    "name": "placeholder"
+		}
+	    },
+	    "results": [
+		{
+		    "message": {"text": "placeholder"},
+		    "locations": [
+			{
+			    "logicalLocations": [
+				{
+				    "index": 42 // { dg-error "index value 42 is out of range for theRun.logicalLocations \\\[SARIF v2.1.0 §3.33.3\\\]" }
+				}
+			    ]
+			}
+		    ]
+		}
+	    ],
+	    "logicalLocations": []
+	}
+    ]
+}
+
+/* { dg-begin-multiline-output "" }
+   17 |                                     "index": 42
+      |                                              ^~
+   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/sarif-replay.dg/2.1.0-valid/spec-example-4.sarif b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/spec-example-4.sarif
index 27a0767bd0ef..c0f0fd50e0e9 100644
--- a/gcc/testsuite/sarif-replay.dg/2.1.0-valid/spec-example-4.sarif
+++ b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/spec-example-4.sarif
@@ -749,7 +749,7 @@ 
 /* { dg-begin-multiline-output "" }
 In function 'collections::list::add':
 collections/list.h:15:9: error: Variable "ptr" was used without being initialized. It was declared here. [C2001]
-  events 1-3
+  'add': events 1-3
 ......
    { dg-end-multiline-output "" } */
 /* { dg-begin-multiline-output "" }