m_inner (inner)
{}
+ diagnostic_file *get_file () const;
+
diagnostic_manager *m_mgr;
location_t m_inner;
};
return file;
}
+ diagnostic_file *
+ get_file_by_name (const char *name)
+ {
+ if (diagnostic_file **slot = m_str_to_file_map.get (name))
+ return *slot;
+ return nullptr;
+ }
+
const diagnostic_physical_location *
new_location_from_file_and_line (const diagnostic_file *file,
diagnostic_line_num_t line_num)
fc.add_buffered_content (m_name.get_str (), buf, sz);
}
+// struct diagnostic_physical_location
+
+diagnostic_file *
+diagnostic_physical_location::get_file () const
+{
+ m_mgr->set_line_table_global ();
+ const char *filename = LOCATION_FILE (m_inner);
+ if (!filename)
+ return nullptr;
+ return m_mgr->get_file_by_name (filename);
+}
+
/* class impl_diagnostic_client_data_hooks. */
const client_version_info *
diag->get_manager ().emit (*diag, gmsgid, args);
delete diag;
}
+
+/* Public entrypoint. */
+
+diagnostic_file *
+diagnostic_physical_location_get_file (const diagnostic_physical_location *physical_loc)
+{
+ if (!physical_loc)
+ return nullptr;
+
+ return physical_loc->get_file ();
+}
ValueType m_value;
};
+/* A class for recording annotations seen in locations (§3.28.6) that
+ should be emitted as secondary locations on diagnostics. */
+
+class annotation
+{
+public:
+ annotation (libgdiagnostics::physical_location phys_loc,
+ label_text label)
+ : m_phys_loc (phys_loc),
+ m_label (std::move (label))
+ {
+ }
+
+ libgdiagnostics::physical_location m_phys_loc;
+ label_text m_label;
+};
+
class sarif_replayer
{
public:
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);
+ libgdiagnostics::logical_location &out_logical_loc,
+ std::vector<annotation> *out_annotations);
// "physicalLocation" object (§3.29)
enum status
level_values, ARRAY_SIZE (level_values));
}
+static void
+add_any_annotations (libgdiagnostics::diagnostic &diag,
+ const std::vector<annotation> &annotations)
+{
+ for (auto &annotation : annotations)
+ if (annotation.m_label.get ())
+ diag.add_location_with_label (annotation.m_phys_loc,
+ annotation.m_label.get ());
+ else
+ diag.add_location (annotation.m_phys_loc);
+}
+
/* Process a result object (SARIF v2.1.0 section 3.27).
Known limitations:
- doesn't yet handle "ruleIndex" property (§3.27.6)
= get_required_property<json::array> (result_obj, locations_prop);
if (!locations_arr)
return status::err_invalid_sarif;
+ std::vector<annotation> annotations;
if (locations_arr->length () > 0)
{
/* Only look at the first, if there's more than one. */
return status::err_invalid_sarif;
enum status s = handle_location_object (*location_obj, run_obj,
physical_loc,
- logical_loc);
+ logical_loc,
+ &annotations);
if (s != status::ok)
return s;
}
}
err.set_location (physical_loc);
err.set_logical_location (logical_loc);
+ add_any_annotations (err, annotations);
if (path.m_inner)
err.take_execution_path (std::move (path));
err.finish ("%s", text.get ());
prop_related_locations);
if (!location_obj)
return status::err_invalid_sarif;
+ std::vector<annotation> annotations;
enum status s = handle_location_object (*location_obj, run_obj,
physical_loc,
- logical_loc);
+ logical_loc,
+ &annotations);
if (s != status::ok)
return s;
auto note (m_output_mgr.begin_diagnostic (DIAGNOSTIC_LEVEL_NOTE));
note.set_location (physical_loc);
note.set_logical_location (logical_loc);
+ add_any_annotations (note, annotations);
note.finish ("%s", text.get ());
}
}
{
/* location object (§3.28). */
enum status s = handle_location_object (*location_obj, run_obj,
- physical_loc, logical_loc);
+ physical_loc, logical_loc,
+ nullptr);
if (s != status::ok)
return s;
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)
+ libgdiagnostics::logical_location &out_logical_loc,
+ std::vector<annotation> *out_annotations)
{
// §3.28.3 "physicalLocation" property
{
}
}
+ // §3.28.6 "annotations" property
+ {
+ const property_spec_ref annotations_prop
+ ("location", "annotations", "3.28.6");
+ if (const json::array *annotations_arr
+ = get_optional_property<json::array> (location_obj,
+ annotations_prop))
+ for (auto element : *annotations_arr)
+ {
+ const json::object *annotation_obj
+ = require_object_for_element (*element, annotations_prop);
+ if (!annotation_obj)
+ return status::err_invalid_sarif;
+ libgdiagnostics::file file = out_physical_loc.get_file ();
+ if (!file.m_inner)
+ return report_invalid_sarif
+ (*annotation_obj, annotations_prop,
+ "cannot find artifact for %qs property",
+ annotations_prop.get_property_name ());
+ libgdiagnostics::physical_location phys_loc;
+ enum status s = handle_region_object (*annotation_obj,
+ file,
+ phys_loc);
+ if (s != status::ok)
+ return s;
+
+ label_text label;
+
+ // §3.30.14 message property
+ {
+ const property_spec_ref message_prop
+ ("region", "message", "3.30.14");
+
+ if (const json::object *message_obj
+ = get_optional_property<json::object> (*annotation_obj,
+ message_prop))
+ label = make_plain_text_within_result_message (nullptr,
+ *message_obj,
+ nullptr);
+ }
+
+ if (out_annotations)
+ out_annotations->push_back ({phys_loc, std::move (label)});
+ }
+ }
+
return status::ok;
}
--- /dev/null
+{"$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": "bad-binary-ops-highlight-colors.c"},
+ "sourceLanguage": "c",
+ "contents": {"text": "/* Verify that colorization affects both text within diagnostic messages\n and underlined ranges of quoted source, and that the types we use\n match up between them.\n Also implicitly verify that -fdiagnostics-show-highlight-colors is\n on by default. */\n\n\n\nstruct s {};\nstruct t {};\ntypedef struct s S;\ntypedef struct t T;\n\nextern S callee_4a (void);\nextern T callee_4b (void);\n\nint test_4 (void)\n{\n return callee_4a () + callee_4b ();\n}\n"},
+ "roles": ["analysisTarget"]}],
+ "results": [{"ruleId": "error",
+ "level": "error",
+ "message": {"text": "invalid operands to binary + (have ‘S’ {{aka ‘struct s’}} and ‘T’ {{aka ‘struct t’}})"},
+ "locations": [{"physicalLocation": {"artifactLocation": {"uri": "bad-binary-ops-highlight-colors.c",
+ "uriBaseId": "PWD"},
+ "region": {"startLine": 19,
+ "startColumn": 23,
+ "endColumn": 24},
+ "contextRegion": {"startLine": 19,
+ "snippet": {"text": " return callee_4a () + callee_4b ();\n"}}},
+ "logicalLocations": [{"name": "test_4",
+ "fullyQualifiedName": "test_4",
+ "decoratedName": "test_4",
+ "kind": "function"}],
+ "annotations": [{"startLine": 19,
+ "startColumn": 10,
+ "endColumn": 22,
+ "message": {"text": "S {{aka struct s}}"}},
+ {"startLine": 19,
+ "startColumn": 25,
+ "endColumn": 37,
+ "message": {"text": "T {{aka struct t}}"}}]}]}]}]}
+
+/* Verify that we underline and label the ranges for the
+ "annotations" above. */
+/* { dg-begin-multiline-output "" }
+bad-binary-ops-highlight-colors.c:19:23: error: invalid operands to binary + (have ‘S’ {aka ‘struct s’} and ‘T’ {aka ‘struct t’}) [error]
+ 19 | return callee_4a () + callee_4b ();
+ | ~~~~~~~~~~~~ ^ ~~~~~~~~~~~~
+ | | |
+ | | T {aka struct t}
+ | S {aka struct s}
+ { dg-end-multiline-output "" } */
+// TODO: trailing [error]