aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2025-02-15 08:18:19 -0500
committerDavid Malcolm <dmalcolm@redhat.com>2025-02-15 08:18:19 -0500
commitd0d5204afff226ffc5d329b8e4734dda081dd9b4 (patch)
tree90882fdfefc055a2fb554b245cc1e6357da8aadb /gcc
parentd022a068e0c8587b2570147b738cb2781242f162 (diff)
downloadgcc-d0d5204afff226ffc5d329b8e4734dda081dd9b4.zip
gcc-d0d5204afff226ffc5d329b8e4734dda081dd9b4.tar.gz
gcc-d0d5204afff226ffc5d329b8e4734dda081dd9b4.tar.bz2
sarif-replay: handle the 'fixes' property (§3.27.30)
This adds support to sarif-replay to display fix-it hints stored in GCC's SARIF output. gcc/ChangeLog: * libsarifreplay.cc (sarif_replayer::handle_result_obj): Call handle_fix_object if we see a single-element "fixes" array. (sarif_replayer::handle_fix_object): New. (sarif_replayer::handle_artifact_change_object): New. gcc/testsuite/ChangeLog: * sarif-replay.dg/2.1.0-valid/3.27.30-fixes-1.sarif: New test. * sarif-replay.dg/2.1.0-valid/3.27.30-fixes-2.sarif: New test. * sarif-replay.dg/2.1.0-valid/3.27.30-fixes-3.sarif: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/libsarifreplay.cc117
-rw-r--r--gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.27.30-fixes-1.sarif55
-rw-r--r--gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.27.30-fixes-2.sarif39
-rw-r--r--gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.27.30-fixes-3.sarif39
4 files changed, 248 insertions, 2 deletions
diff --git a/gcc/libsarifreplay.cc b/gcc/libsarifreplay.cc
index 21d8e6c..cc051dc 100644
--- a/gcc/libsarifreplay.cc
+++ b/gcc/libsarifreplay.cc
@@ -346,6 +346,16 @@ private:
lookup_rule_by_id_in_component (const char *rule_id,
const json::object &tool_component_obj);
+ // "fix" object (§3.55)
+ enum status
+ handle_fix_object (libgdiagnostics::diagnostic &diag,
+ const json::object &fix_obj);
+
+ // "artifactChange" object (§3.56)
+ enum status
+ handle_artifact_change_object (libgdiagnostics::diagnostic &diag,
+ const json::object &change_obj);
+
/* Support functions. */
/* Report an error to m_control_mgr about JV violating REF,
@@ -1012,7 +1022,6 @@ should_add_rule_p (const char *rule_id_str, const char *url)
- doesn't yet handle "taxa" property (§3.27.8)
- handling of "level" property (§3.27.10) doesn't yet support the
full logic for when "level" is absent.
- - doesn't yet handle "fixes" property (§3.27.30)
- doesn't yet support multithreaded flows (§3.36.3)
*/
@@ -1200,6 +1209,17 @@ sarif_replayer::handle_result_obj (const json::object &result_obj,
}
}
+ // §3.27.30 "fixes" property
+ const property_spec_ref prop_fixes ("result", "fixes", "3.27.30");
+ if (auto fixes_arr
+ = get_optional_property<json::array> (result_obj, prop_fixes))
+ {
+ // We only support a single fix
+ if (fixes_arr->length () == 1)
+ if (auto fix_obj = require_object (*fixes_arr->get (0), prop_fixes))
+ handle_fix_object (err, *fix_obj);
+ }
+
err.finish ("%s", text.get ());
// Flush any notes
@@ -1211,7 +1231,6 @@ sarif_replayer::handle_result_obj (const json::object &result_obj,
}
return status::ok;
-
}
/* If ITER_SRC starts with a placeholder as per §3.11.5, advance ITER_SRC
@@ -2049,6 +2068,100 @@ lookup_rule_by_id_in_component (const char *rule_id,
return nullptr;
}
+// "fix" object (§3.55)
+
+enum status
+sarif_replayer::handle_fix_object (libgdiagnostics::diagnostic &diag,
+ const json::object &fix_obj)
+{
+ const property_spec_ref changes ("fix", "artifactChanges", "3.55.3");
+ auto changes_arr = get_required_property<json::array> (fix_obj, changes);
+ if (!changes_arr)
+ return status::err_invalid_sarif;
+
+ for (auto element : *changes_arr)
+ {
+ const json::object *change_obj
+ = require_object_for_element (*element, changes);
+ if (!change_obj)
+ return status::err_invalid_sarif;
+ enum status s = handle_artifact_change_object (diag, *change_obj);
+ if (s != status::ok)
+ return s;
+ }
+ return status::ok;
+}
+
+// "artifactChange" object (§3.56)
+
+enum status
+sarif_replayer::
+handle_artifact_change_object (libgdiagnostics::diagnostic &diag,
+ const json::object &change_obj)
+{
+ const property_spec_ref location
+ ("artifactChange", "artifactLocation", "3.56.2");
+ auto artifact_loc_obj
+ = get_required_property<json::object> (change_obj, location);
+ if (!artifact_loc_obj)
+ return status::err_invalid_sarif;
+
+ libgdiagnostics::file file;
+ enum status s = handle_artifact_location_object (*artifact_loc_obj, file);
+ if (s != status::ok)
+ return s;
+
+ const property_spec_ref replacements
+ ("artifactChange", "replacements", "3.56.3");
+ auto replacements_arr
+ = get_required_property<json::array> (change_obj, replacements);
+ if (!replacements_arr)
+ return status::err_invalid_sarif;
+ for (auto element : *replacements_arr)
+ {
+ // 3.57 replacement object
+ const json::object *replacement_obj
+ = require_object_for_element (*element, replacements);
+ if (!replacement_obj)
+ return status::err_invalid_sarif;
+
+ // 3.57.3 deletedRegion property
+ const property_spec_ref deleted_region
+ ("replacement", "deletedRegion", "3.57.3");
+ auto deleted_region_obj
+ = get_required_property<json::object> (*replacement_obj,
+ deleted_region);
+ if (!deleted_region_obj)
+ return status::err_invalid_sarif;
+
+ libgdiagnostics::physical_location phys_loc;
+ enum status s = handle_region_object (*deleted_region_obj,
+ file,
+ phys_loc);
+ if (s != status::ok)
+ return s;
+
+ // 3.57.4 insertedContent property
+ const property_spec_ref inserted_content
+ ("replacement", "insertedContent", "3.57.4");
+ const char *inserted_text = "";
+ if (auto inserted_content_obj
+ = get_optional_property<json::object> (*replacement_obj,
+ inserted_content))
+ {
+ const property_spec_ref prop_text
+ ("artifactContent", "text", "3.3.2");
+ if (auto text_jstr
+ = get_optional_property<json::string> (*inserted_content_obj,
+ prop_text))
+ inserted_text = text_jstr->get_string ();
+ }
+
+ diag.add_fix_it_hint_replace (phys_loc, inserted_text);
+ }
+ return status::ok;
+}
+
} // anonymous namespace
/* Error-checking at the API boundary. */
diff --git a/gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.27.30-fixes-1.sarif b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.27.30-fixes-1.sarif
new file mode 100644
index 0000000..c37411a
--- /dev/null
+++ b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.27.30-fixes-1.sarif
@@ -0,0 +1,55 @@
+/* Example of GCC SARIF output for a replacement fix-it hint. */
+
+{"$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json",
+ "version": "2.1.0",
+ "runs": [{"tool": {"driver": {"name": "GNU C23",
+ "fullName": "GNU C23 (GCC) version 15.0.1 20250203 (experimental) (x86_64-pc-linux-gnu)",
+ "version": "15.0.1 20250203 (experimental)",
+ "informationUri": "https://gcc.gnu.org/gcc-15/",
+ "rules": [{"id": "-Wformat=",
+ "helpUri": "https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wformat"}]}},
+ "invocations": [{"executionSuccessful": true,
+ "toolExecutionNotifications": []}],
+ "originalUriBaseIds": {"PWD": {"uri": "file:///this/path/does/not/exist/"}},
+ "artifacts": [{"location": {"uri": "/this/path/does/not/exist/diagnostic-ranges.c",
+ "uriBaseId": "PWD"},
+ "sourceLanguage": "c",
+ "contents": {"text": "#include <stdio.h>\n\nvoid test_mismatching_types (const char *msg)\n{\n printf(\"hello %i\", msg);\n}\n"},
+ "roles": ["analysisTarget"]}],
+ "results": [{"ruleId": "-Wformat=",
+ "level": "warning",
+ "message": {"text": "format '%i' expects argument of type 'int', but argument 2 has type 'const char *'"},
+ "locations": [{"physicalLocation": {"artifactLocation": {"uri": "/this/path/does/not/exist/diagnostic-ranges.c",
+ "uriBaseId": "PWD"},
+ "region": {"startLine": 5,
+ "startColumn": 17,
+ "endColumn": 19},
+ "contextRegion": {"startLine": 5,
+ "snippet": {"text": " printf(\"hello %i\", msg);\n"}}},
+ "logicalLocations": [{"name": "test_mismatching_types",
+ "fullyQualifiedName": "test_mismatching_types",
+ "decoratedName": "test_mismatching_types",
+ "kind": "function"}],
+ "annotations": [{"startLine": 5,
+ "startColumn": 17,
+ "endColumn": 19,
+ "message": {"text": "int"}},
+ {"startLine": 5,
+ "startColumn": 22,
+ "endColumn": 25,
+ "message": {"text": "const char *"}}]}],
+ "fixes": [{"artifactChanges": [{"artifactLocation": {"uri": "/this/path/does/not/exist/diagnostic-ranges.c",
+ "uriBaseId": "PWD"},
+ "replacements": [{"deletedRegion": {"startLine": 5,
+ "startColumn": 17,
+ "endColumn": 19},
+ "insertedContent": {"text": "%s"}}]}]}]}]}]}
+
+/* { dg-begin-multiline-output "" }
+/this/path/does/not/exist/diagnostic-ranges.c:5:17: warning: format '%i' expects argument of type 'int', but argument 2 has type 'const char *' [-Wformat=]
+ 5 | printf("hello %i", msg);
+ | ^~ ~~~
+ | | |
+ | int const char *
+ | %s
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.27.30-fixes-2.sarif b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.27.30-fixes-2.sarif
new file mode 100644
index 0000000..0334885
--- /dev/null
+++ b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.27.30-fixes-2.sarif
@@ -0,0 +1,39 @@
+/* Example of GCC SARIF output for a deletion fix-it hint. */
+
+{"$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json",
+ "version": "2.1.0",
+ "runs": [{"tool": {"driver": {"name": "GNU C++17",
+ "fullName": "GNU C++17 (GCC) version 15.0.1 20250203 (experimental) (x86_64-pc-linux-gnu)",
+ "version": "15.0.1 20250203 (experimental)",
+ "informationUri": "https://gcc.gnu.org/gcc-15/",
+ "rules": []}},
+ "invocations": [{"executionSuccessful": false,
+ "toolExecutionNotifications": []}],
+ "artifacts": [{"location": {"uri": "t.cc",
+ "uriBaseId": "PWD"},
+ "sourceLanguage": "cplusplus",
+ "contents": {"text": "unsigned unsigned int i;\n"},
+ "roles": ["analysisTarget"]}],
+ "results": [{"ruleId": "error",
+ "level": "error",
+ "message": {"text": "duplicate 'unsigned'"},
+ "locations": [{"physicalLocation": {"artifactLocation": {"uri": "t.cc",
+ "uriBaseId": "PWD"},
+ "region": {"startLine": 1,
+ "startColumn": 10,
+ "endColumn": 18},
+ "contextRegion": {"startLine": 1,
+ "snippet": {"text": "unsigned unsigned int i;\n"}}}}],
+ "fixes": [{"artifactChanges": [{"artifactLocation": {"uri": "t.cc",
+ "uriBaseId": "PWD"},
+ "replacements": [{"deletedRegion": {"startLine": 1,
+ "startColumn": 10,
+ "endColumn": 18},
+ "insertedContent": {"text": ""}}]}]}]}]}]}
+
+/* { dg-begin-multiline-output "" }
+t.cc:1:10: error: duplicate 'unsigned'
+ 1 | unsigned unsigned int i;
+ | ^~~~~~~~
+ | --------
+ { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.27.30-fixes-3.sarif b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.27.30-fixes-3.sarif
new file mode 100644
index 0000000..d4e7d37
--- /dev/null
+++ b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/3.27.30-fixes-3.sarif
@@ -0,0 +1,39 @@
+/* Example of GCC SARIF output for an insertion fix-it hint. */
+
+{"$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json",
+ "version": "2.1.0",
+ "runs": [{"tool": {"driver": {"name": "GNU C23",
+ "fullName": "GNU C23 (GCC) version 15.0.1 20250203 (experimental) (x86_64-pc-linux-gnu)",
+ "version": "15.0.1 20250203 (experimental)",
+ "informationUri": "https://gcc.gnu.org/gcc-15/",
+ "rules": []}},
+ "invocations": [{"executionSuccessful": false,
+ "toolExecutionNotifications": []}],
+ "artifacts": [{"location": {"uri": "t.c",
+ "uriBaseId": "PWD"},
+ "sourceLanguage": "c",
+ "contents": {"text": "struct foo {};\n\nfoo *ptr;\n"},
+ "roles": ["analysisTarget"]}],
+ "results": [{"ruleId": "error",
+ "level": "error",
+ "message": {"text": "unknown type name 'foo'; use 'struct' keyword to refer to the type"},
+ "locations": [{"physicalLocation": {"artifactLocation": {"uri": "t.c",
+ "uriBaseId": "PWD"},
+ "region": {"startLine": 3,
+ "startColumn": 1,
+ "endColumn": 4},
+ "contextRegion": {"startLine": 3,
+ "snippet": {"text": "foo *ptr;\n"}}}}],
+ "fixes": [{"artifactChanges": [{"artifactLocation": {"uri": "t.c",
+ "uriBaseId": "PWD"},
+ "replacements": [{"deletedRegion": {"startLine": 3,
+ "startColumn": 1,
+ "endColumn": 1},
+ "insertedContent": {"text": "struct "}}]}]}]}]}]}
+
+/* { dg-begin-multiline-output "" }
+t.c:3:1: error: unknown type name 'foo'; use 'struct' keyword to refer to the type
+ 3 | foo *ptr;
+ | ^~~
+ | struct
+ { dg-end-multiline-output "" } */