Age | Commit message (Collapse) | Author | Files | Lines |
|
This patch adds support to sarif-replay for "nestingLevel"
from "P3358R0 SARIF for Structured Diagnostics"
https://wg21.link/P3358R0
Doing so revealed a bug where libgdiagnostics was always
creating new location_t values (and thus also
diagnostic_physical_location instances), rather than reusing
existing location_t values, leading to excess source printing.
The patch also fixes this bug, adding a new flag to libgdiagnostics
for debugging physical locations, and exposing this in sarif-replay
via a new "-fdebug-physical-locations" maintainer option.
Finally, the patch adds test coverage for the HTML sink's output
of nested diagnostics (both from a GCC plugin, and from sarif-replay).
gcc/ChangeLog:
PR diagnostics/116253
* diagnostics/context.cc (context::set_nesting_level): New.
* diagnostics/context.h (context::set_nesting_level): New decl.
* doc/libgdiagnostics/topics/compatibility.rst
(LIBGDIAGNOSTICS_ABI_5): New.
* doc/libgdiagnostics/topics/physical-locations.rst
(diagnostic_manager_set_debug_physical_locations): New.
* libgdiagnostics++.h (manager::set_debug_physical_locations):
New.
* libgdiagnostics-private.h
(private_diagnostic_set_nesting_level): New decl.
* libgdiagnostics.cc (diagnostic_manager::diagnostic_manager):
Initialize m_debug_physical_locations.
(diagnostic_manager::new_location_from_file_and_line): Add debug
printing.
(diagnostic_manager::new_location_from_file_line_column):
Likewise.
(diagnostic_manager::new_location_from_range): Likewise.
(diagnostic_manager::set_debug_physical_locations): New.
(diagnostic_manager::ensure_linemap_for_file_and_line): Avoid
redundant calls to linemap_add.
(diagnostic_manager::new_location): Add debug printing.
(diagnostic_manager::m_debug_physical_locations): New field.
(diagnostic::diagnostic): Initialize m_nesting_level.
(diagnostic::get_nesting_level): New accessor.
(diagnostic::set_nesting_level): New.
(diagnostic::m_nesting_level): New field.
(diagnostic_manager::emit_va): Set and reset the nesting level
of the context from that of the diagnostic.
(diagnostic_manager_set_debug_physical_locations): New.
(private_diagnostic_set_nesting_level): New.
* libgdiagnostics.h
(diagnostic_manager_set_debug_physical_locations): New decl.
* libgdiagnostics.map (LIBGDIAGNOSTICS_ABI_5): New.
* libsarifreplay.cc (sarif_replayer::handle_result_obj): Support
the "nestingLevel" property.
* libsarifreplay.h (replay_options::m_debug_physical_locations):
New field.
* sarif-replay.cc: Add -fdebug-physical-locations.
gcc/testsuite/ChangeLog:
PR diagnostics/116253
* gcc.dg/plugin/diagnostic-test-nesting-html.c: New test.
* gcc.dg/plugin/diagnostic-test-nesting-html.py: New test script.
* gcc.dg/plugin/plugin.exp: Add it.
* libgdiagnostics.dg/test-multiple-lines.c: Update expected output
to show fix-it hint.
* sarif-replay.dg/2.1.0-valid/nested-diagnostics-1.sarif: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
This patch extends libgdiagnostics to provide a way to capture
the pp tokens making up a message string, so that SARIF and
HTML sinks can retain information such as event IDs and URLs.
As well as richer output, this improves the round-tripping of such
information through sarif-replay.
This also allows diagnostic messages to be built up in pieces,
with a drop-in replacement for fprintf, which I've found useful when
attempting to port "ld" to use libgdiagnostics.
gcc/ChangeLog:
PR sarif-replay/120792
* auto-obstack.h: New file, based on material taken from
pretty-print.cc.
* diagnostic-digraphs.h
(diagnostics::digraphs::digraph::set_description): New.
(diagnostics::digraphs::node::set_label): New.
* doc/libgdiagnostics/topics/compatibility.rst: Add
LIBGDIAGNOSTICS_ABI_4.
* doc/libgdiagnostics/topics/diagnostics.rst
(diagnostic_finish_via_msg_buf): Document new entrypoint.
* doc/libgdiagnostics/topics/execution-paths.rst
(diagnostic_execution_path_add_event_via_msg_buf): Document new
entrypoint.
* doc/libgdiagnostics/topics/index.rst: Add message-buffers.rst.
* doc/libgdiagnostics/topics/message-buffers.rst: New file.
* doc/libgdiagnostics/topics/message-formatting.rst: Add note
about message buffers.
* doc/libgdiagnostics/topics/physical-locations.rst
(diagnostic_add_location_with_label_via_msg_buf): Add.
* doc/libgdiagnostics/tutorial/07-execution-paths.rst: Link to
next section.
* doc/libgdiagnostics/tutorial/08-message-buffers.rst: New file.
* doc/libgdiagnostics/tutorial/index.rst: Add
08-message-buffers.rst.
* libgdiagnostics++.h (libgdiagnostics::message_buffer): New
class.
(libgdiagnostics::execution_path::add_event_via_msg_buf): New.
(libgdiagnostics::diagnostic::add_location_with_label): New.
(libgdiagnostics::diagnostic::finish_via_msg_buf): New.
(libgdiagnostics::graph::set_description): New overload.
(libgdiagnostics::graph::add_edge): New overload.
(libgdiagnostics::node::set_label): New overload.
* libgdiagnostics-private.h
(private_diagnostic_execution_path_add_event_2): Drop decl.
(private_diagnostic_execution_path_add_event_3): New decl.
* libgdiagnostics.cc: Include "pretty-print-format-impl.h",
"pretty-print-markup.h", and "auto-obstack.h".
(class copying_token_printer): New.
(struct diagnostic_message_buffer): New.
(class pp_element_message_buffer): New.
(libgdiagnostics_path_event::libgdiagnostics_path_event): Replace
params "gmsgid" and "args" with "msg_buf".
(libgdiagnostics_path_event::print_desc): Reimplement using
pp_element_message_buffer to replay m_msg_buf into "pp".
(libgdiagnostics_path_event::m_desc_uncolored): Drop field.
(libgdiagnostics_path_event::m_desc_colored): Drop field.
(libgdiagnostics_path_event::msg_buf): New field.
(diagnostic_execution_path::add_event_va): Reimplement.
(diagnostic_execution_path::add_event_via_msg_buf): New.
(diagnostic::add_location_with_label): New overload, using
msg_buf.
(diagnostic_manager::emit): Reimplement with...
(diagnostic_manager::emit_va): ...this.
(diagnostic_manager::emit_msg_buf): New.
(FAIL_IF_NULL): Rename "p" to "ptr_arg".
(diagnostic_finish_va): Update to use diagnostic_manager::emit_va.
(diagnostic_graph::add_node_with_id): Rename "id" to "node_id".
(diagnostic_graph_add_node): Likewise.
(diagnostic_graph_add_edge): Rename "id" to "edge_id".
(diagnostic_graph_get_node_by_id): Rename "id" to "node_id".
(diagnostic_graph_get_edge_by_id): Rename "id" to "edge_id".
(private_diagnostic_execution_path_add_event_2): Delete.
(diagnostic_message_buffer_new): New public entrypoint.
(diagnostic_message_buffer_release): Likewise.
(diagnostic_message_buffer_append_str): Likewise.
(diagnostic_message_buffer_append_text): Likewise.
(diagnostic_message_buffer_append_byte): Likewise.
(diagnostic_message_buffer_append_printf): Likewise.
(diagnostic_message_buffer_append_event_id): Likewise.
(diagnostic_message_buffer_begin_url): Likewise.
(diagnostic_message_buffer_end_url): Likewise.
(diagnostic_message_buffer_begin_quote): Likewise.
(diagnostic_message_buffer_end_quote): Likewise.
(diagnostic_message_buffer_begin_color): Likewise.
(diagnostic_message_buffer_end_color): Likewise.
(diagnostic_message_buffer_dump): Likewise.
(diagnostic_finish_via_msg_buf): Likewise.
(diagnostic_add_location_with_label_via_msg_buf): Likewise.
(diagnostic_execution_path_add_event_via_msg_buf): Likewise.
(diagnostic_graph_set_description_via_msg_buf): Likewise.
(diagnostic_graph_add_edge_via_msg_buf): Likewise.
(diagnostic_node_set_label_via_msg_buf): Likewise.
(private_diagnostic_execution_path_add_event_3): New private
entrypoint.
* libgdiagnostics.h (LIBGDIAGNOSTICS_PARAM_FORMAT_STRING): New macro.
(LIBGDIAGNOSTICS_PARAM_PRINTF_FORMAT_STRING): New macro.
(diagnostic_message_buffer): New typedef.
(LIBDIAGNOSTICS_HAVE_diagnostic_message_buffer): New define.
(diagnostic_message_buffer_new): New decl.
(diagnostic_message_buffer_release): New decl.
(diagnostic_message_buffer_append_str): New decl.
(diagnostic_message_buffer_append_text): New decl.
(diagnostic_message_buffer_append_byte): New decl.
(diagnostic_message_buffer_append_printf): New decl.
(diagnostic_message_buffer_append_event_id): New decl.
(diagnostic_message_buffer_begin_url): New decl.
(diagnostic_message_buffer_end_url): New decl.
(diagnostic_message_buffer_begin_quote): New decl.
(diagnostic_message_buffer_end_quote): New decl.
(diagnostic_message_buffer_begin_color): New decl.
(diagnostic_message_buffer_end_color): New decl.
(diagnostic_message_buffer_dump): New decl.
(diagnostic_finish_via_msg_buf): New decl.
(diagnostic_add_location_with_label_via_msg_buf): New decl.
(diagnostic_execution_path_add_event_via_msg_buf): New decl.
(diagnostic_graph_set_description_via_msg_buf): New decl.
(diagnostic_graph_add_edge_via_msg_buf): New decl.
(diagnostic_node_set_label_via_msg_buf): New decl.
* libgdiagnostics.map (LIBGDIAGNOSTICS_ABI_3): Drop
private_diagnostic_execution_path_add_event_2.
(LIBGDIAGNOSTICS_ABI_4): New.
* libsarifreplay.cc (class annotation): Use
libgdiagnostics::message_buffer rather than label_text.
(add_any_annotations): Likewise.
(sarif_replayer::handle_result_obj): Likewise.
(make_plain_text_within_result_message): Likewise.
(handle_thread_flow_location_object): Likewise.
(handle_location_object): Likewise.
(sarif_replayer::handle_graph_object): Likewise.
(sarif_replayer::handle_node_object): Likewise.
(sarif_replayer::handle_edge_object): Likewise.
* pretty-print-format-impl.h (pp_token_list::push_back_byte): New
decl.
* pretty-print-markup.h (pp_markup::context::begin_url): New decl.
(pp_markup::context::end_url): New decl.
(pp_markup::context::add_event_id): New decl.
* pretty-print.cc: Include "auto-obstack.h".
(pp_token_list::push_back_byte): New.
(struct auto_obstack): Move to auto-obstack.h.
(default_token_printer): Make non-static.
(pp_markup::context::begin_url): New.
(pp_markup::context::end_url): New.
(pp_markup::context::add_event_id): New.
gcc/testsuite/ChangeLog:
PR sarif-replay/120792
* libgdiagnostics.dg/sarif.py: Delete duplicate script.
* libgdiagnostics.dg/test-message-buffer-c.py: New test script.
* libgdiagnostics.dg/test-message-buffer.c: New test.
* libgdiagnostics.dg/test-warning-with-path-c.py: Update expected
output to reflect that SARIF for event messages now contains JSON
pointers when referring to other events by ID.
* sarif-replay.dg/2.1.0-valid/3.11.6-embedded-links.sarif: Add
HTML and SARIF output, and call out to Python scripts to verify
the output. Add example of a result with a link in its message.
* sarif-replay.dg/2.1.0-valid/embedded-links-check-html.py: New
test script.
* sarif-replay.dg/2.1.0-valid/embedded-links-check-sarif-roundtrip.py:
New test script.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
In r16-1631-g2334d30cd8feac I added support for capturing state
information from -fanalyzer in XML form, and adding a way to visualize
these states in HTML output. The data was optionally captured in SARIF
output (with "xml-state=yes"), stashing the XML in string form in
a property bag.
This worked, but there was no way to round-trip the stored data back
from SARIF without adding an XML parser to GCC, which I don't want to
do.
SARIF supports capturing directed graphs, so this patch:
(a) adds a new namespace diagnostics::digraphs, with classes digraph,
node, and edge, representing directed graphs in a form similar to
what SARIF can serialize
(b) adds support to GCC's diagnostic subsystem for reporting graphs,
either "globally" or as part of a diagnostic. An example in a testsuite
plugin emits an error that has a couple of dummy graphs associated with
it, and captures the optimization passes as a digraph "globally".
Graphs are ignored by text sinks, but are captured by sarif sinks,
and the "experimental-html" sink gains SVG-based rendering of any graphs
using dot. This HTML output is rather crude; an example can be seen
here:
https://dmalcolm.fedorapeople.org/gcc/2025-07-10/diagnostic-test-graphs-html.c.html
(c) adds support to libgdiagnostics for the above
(d) adds support to sarif-replay for the above (round-tripping any
graph information)
(e) replaces the XML representation of state with a representation
based on the above directed graphs, using property bags to stash
additional information (e.g. "this is an on-stack buffer")
(f) implements round-tripping of this information in sarif-replay
To summarize:
- previously we could generate HTML diagrams for debugging
-fanalyzer directly from gcc, but not from stored .sarif output.
- with this patch, we can generate such HTML diagrams both directly
*and* from stored .sarif output (provided the SARIF sink was created
with "state-graphs=yes")
Examples of HTML output can be seen here:
https://dmalcolm.fedorapeople.org/gcc/2025-07-10/
where as before j/k can be used to cycle through the events.
which is almost identical to the output from the old XML-based
implementation seen at:
https://dmalcolm.fedorapeople.org/gcc/2025-06-23/
gcc/ChangeLog:
* Makefile.in (OBJS-libcommon): Add diagnostic-digraphs.o and
diagnostic-state-graphs.o.
gcc/ChangeLog:
* diagnostic-format-html.cc: Include "diagnostic-format-sarif.h",
Replace include of "diagnostic-state.h" with includes of
"diagnostic-digraphs.h" and "diagnostic-state-graphs.h".
(html_generation_options::html_generation_options): Update for
field renaming.
(html_builder::m_body_element): New field.
(html_builder::html_builder): Initialize m_body_element.
(html_builder::maybe_make_state_diagram): Port from XML
implementation to state graph implementation.
(html_builder::make_element_for_diagnostic): Add any
per-diagnostic graphs.
(html_builder::add_graph): New.
(html_builder::emit_global_graph): New.
(html_output_format::report_global_digraph): New.
* diagnostic-format-html.h
(html_generation_options::m_show_state_diagram_xml): Replace
with...
(html_generation_options::m_show_state_diagrams_sarif): ...this.
(html_generation_options::m_show_state_diagram_dot_src): Rename
to...
(html_generation_options::m_show_state_diagrams_dot_src): ...this.
* diagnostic-format-sarif.cc: Include "diagnostic-digraphs.h" and
"diagnostic-state-graphs.h".
(sarif_builder::m_run_graphs): New field.
(sarif_result::on_nested_diagnostic): Update call to
make_location_object to pass arg by pointer.
(sarif_builder::sarif_builder): Initialize m_run_graphs.
(sarif_builder::report_global_digraph): New.
(sarif_builder::make_result_object): Add any graphs to
the result object.
(sarif_builder::make_locations_arr): Update call to
make_location_object to pass arg by pointer.
(sarif_builder::make_location_object): Pass param "loc_mgr" by
pointer rather than by reference so that it can be null, and
handle this case.
(copy_any_property_bag): New.
(make_sarif_graph): New.
(make_sarif_node): New.
(make_sarif_edge): New.
(sarif_property_bag::set_graph): New.
(populate_thread_flow_location_object): Port from XML
implementation to state graph implementation.
(make_run_object): Store any graphs.
(sarif_output_format::report_global_digraph): New.
(sarif_generation_options::sarif_generation_options): Rename
m_xml_state to m_state_graph.
(selftest::test_make_location_object): Update for change to
make_location_object.
* diagnostic-format-sarif.h:
(sarif_generation_options::m_xml_state): Replace with...
(sarif_generation_options::m_state_graph): ...this.
(class sarif_location_manager): Add forward decl.
(diagnostics::digraphs::digraph): New forward decl.
(diagnostics::digraphs::node): New forward decl.
(diagnostics::digraphs::edge): New forward decl.
(sarif_property_bag::set_graph): New decl.
(class sarif_graph): New.
(class sarif_node): New.
(class sarif_edge): New.
(make_sarif_graph): New decl.
(make_sarif_node): New decl.
(make_sarif_edge): New decl.
* diagnostic-format-text.h
(diagnostic_text_output_format::report_global_digraph): New.
* diagnostic-format.h
(diagnostic_output_format::report_global_digraph): New vfunc.
* diagnostic-digraphs.cc: New file.
* diagnostic-digraphs.h: New file.
* diagnostic-metadata.h (diagnostics::digraphs::lazy_digraphs):
New forward decl.
(diagnostic_metadata::diagnostic_metadata): Initialize
m_lazy_digraphs.
(diagnostic_metadata::set_lazy_digraphs): New.
(diagnostic_metadata::get_lazy_digraphs): New.
(diagnostic_metadata::m_lazy_digraphs): New field.
* diagnostic-output-spec.cc (sarif_scheme_handler::make_sink):
Update for XML to state graph changes.
(sarif_scheme_handler::make_sarif_gen_opts): Likewise.
(html_scheme_handler::make_sink): Rename "show-state-diagram-xml"
to "show-state-diagrams-sarif" and use pluralization consistently.
* diagnostic-path.cc: Replace include of "xml.h" with
"diagnostic-state-graphs.h".
(diagnostic_event::maybe_make_xml_state): Replace with...
(diagnostic_event::maybe_make_diagnostic_state_graph): ...this.
* diagnostic-path.h (diagnostics::digraphs::digraph): New forward
decl.
(diagnostic_event::maybe_make_xml_state): Replace with...
(diagnostic_event::maybe_make_diagnostic_state_graph): ...this.
* diagnostic-state-graphs.cc: New file.
* diagnostic-state-graphs.h: New file.
* diagnostic-state-to-dot.cc: Port implementation from XML to
state graphs.
* diagnostic-state.h: Deleted file.
* diagnostic.cc (diagnostic_context::report_global_digraph): New.
* diagnostic.h (diagnostics::digraphs::lazy_digraph): New forward
decl.
(diagnostic_context::report_global_digraph): New decl.
* doc/analyzer.texi (Debugging the Analyzer): Update to reflect
change from XML to state graphs.
* doc/invoke.texi ("sarif" diagnostics sink): Replace "xml-state"
with "state-graphs".
("experimental-html" diagnostics sink): Replace
"show-state-diagrams-xml" with "show-state-diagrams-sarif"
* doc/libgdiagnostics/topics/compatibility.rst
(LIBGDIAGNOSTICS_ABI_3): New.
* doc/libgdiagnostics/topics/graphs.rst: New file.
* doc/libgdiagnostics/topics/index.rst: Add graphs.rst.
* graphviz.h (node_id::operator=): New.
* json.h (json::value::dyn_cast_string): New.
(json::object::get_num_keys): New accessor.
(json::object::get_key): New accessor.
(json::string::dyn_cast_string): New.
* libgdiagnostics++.h (class libgdiagnostics::graph): New.
(class libgdiagnostics::node): New.
(class libgdiagnostics::edge): New.
(class libgdiagnostics::diagnostic::take_graph): New.
(class libgdiagnostics::manager::take_global_graph): New.
(class libgdiagnostics::graph::set_description): New.
(class libgdiagnostics::graph::get_node_by_id): New.
(class libgdiagnostics::graph::get_edge_by_id): New.
(class libgdiagnostics::graph::add_edge): New.
(class libgdiagnostics::node::set_label): New.
(class libgdiagnostics::node::set_location): New.
(class libgdiagnostics::node::set_logical_location): New.
* libgdiagnostics-private.h: New file.
* libgdiagnostics.cc: Define INCLUDE_STRING. Include
"diagnostic-digraphs.h", "diagnostic-state-graphs.h", and
"libgdiagnostics-private.h".
(struct diagnostic_graph): New.
(struct diagnostic_node): New.
(struct diagnostic_edge): New.
(libgdiagnostics_path_event::libgdiagnostics_path_event): Add
state_graph param.
(libgdiagnostics_path_event::maybe_make_diagnostic_state_graph):
New.
(libgdiagnostics_path_event::m_state_graph): New field.
(diagnostic_execution_path::add_event_va): Add state_graph param.
(class prebuilt_digraphs): New.
(diagnostic::diagnostic): Use m_graphs in m_metadata.
(diagnostic::take_graph): New.
(diagnostic::get_graphs): New accessor.
(diagnostic::m_graphs): New field.
(diagnostic_manager::take_global_graph): New.
(diagnostic_execution_path_add_event): Update for new param to
add_event_va.
(diagnostic_execution_path_add_event_va): Likewise.
(diagnostic_graph::add_node_with_id): New public entrypoint.
(diagnostic_graph::add_edge_with_label): New public entrypoint.
(diagnostic_manager_new_graph): New public entrypoint.
(diagnostic_manager_take_global_graph): New public entrypoint.
(diagnostic_take_graph): New public entrypoint.
(diagnostic_graph_release): New public entrypoint.
(diagnostic_graph_set_description): New public entrypoint.
(diagnostic_graph_add_node): New public entrypoint.
(diagnostic_graph_add_edge): New public entrypoint.
(diagnostic_graph_get_node_by_id): New public entrypoint.
(diagnostic_graph_get_edge_by_id): New public entrypoint.
(diagnostic_node_set_location): New public entrypoint.
(diagnostic_node_set_label): New public entrypoint.
(diagnostic_node_set_logical_location): New public entrypoint.
(private_diagnostic_execution_path_add_event_2): New private
entrypoint.
(private_diagnostic_graph_set_property_bag): New private
entrypoint.
(private_diagnostic_node_set_property_bag): New private
entrypoint.
(private_diagnostic_edge_set_property_bag): New private
entrypoint.
* libgdiagnostics.h (diagnostic_graph): New typedef.
(diagnostic_node): New typedef.
(diagnostic_edge): New typedef.
(diagnostic_manager_new_graph): New decl.
(diagnostic_manager_take_global_graph): New decl.
(diagnostic_take_graph): New decl.
(diagnostic_graph_release): New decl.
(diagnostic_graph_set_description): New decl.
(diagnostic_graph_add_node): New decl.
(diagnostic_graph_add_edge): New decl.
(diagnostic_graph_get_node_by_id): New decl.
(diagnostic_graph_get_edge_by_id): New decl.
(diagnostic_node_set_label): New decl.
(diagnostic_node_set_location): New decl.
(diagnostic_node_set_logical_location): New decl.
* libgdiagnostics.map (LIBGDIAGNOSTICS_ABI_3): New.
* libsarifreplay.cc: Include "libgdiagnostics-private.h".
(id_map): New "using".
(sarif_replayer::report_invalid_sarif): Update for change to
report_problem params.
(sarif_replayer::report_unhandled_sarif): Likewise.
(sarif_replayer::report_note): New.
(sarif_replayer::report_problem): Pass param "ref" by
pointer rather than reference and handle it being null.
(sarif_replayer::maybe_get_property_bag): New.
(sarif_replayer::maybe_get_property_bag_value): New.
(sarif_replayer::handle_run_obj): Handle run-level "graphs" as per
§3.14.20.
(sarif_replayer::handle_result_obj): Handle result-level "graphs"
as per §3.27.19.
(handle_thread_flow_location_object): Optionally handle graphs
stored in property "gcc/diagnostic_event/state_graph" as state
graphs.
(sarif_replayer::handle_graph_object): New.
(sarif_replayer::handle_node_object): New.
(sarif_replayer::handle_edge_object): New.
(sarif_replayer::get_graph_node_by_id_property): New.
* selftest-run-tests.cc (selftest::run_tests): Call
selftest::diagnostic_graph_cc_tests and
selftest::diagnostic_state_graph_cc_tests.
* selftest.h (selftest::diagnostic_graph_cc_tests): New decl.
(selftest::diagnostic_state_graph_cc_tests): New decl.
gcc/analyzer/ChangeLog:
* ana-state-to-diagnostic-state.cc: Reimplement, replacing
XML-based implementation with one based on state graphs.
* ana-state-to-diagnostic-state.h: Likewise.
* checker-event.cc: Replace include of "xml.h" with include of
"diagnostic-state-graphs.h".
(checker_event::maybe_make_xml_state): Replace with...
(checker_event::maybe_make_diagnostic_state_graph): ...this.
* checker-event.h: Add include of "diagnostic-digraphs.h".
(checker_event::maybe_make_xml_state): Replace decl with...
(checker_event::maybe_make_diagnostic_state_graph): ...this.
* engine.cc (exploded_node::on_stmt_pre): Replace
"_analyzer_dump_xml" with "__analyzer_dump_sarif".
* program-state.cc: Replace include of "diagnostic-state.h" with
"diagnostic-state-graphs.h".
(program_state::dump_dot): Port from XML to state graphs.
* program-state.h: Drop reduntant forward decl of xml::document.
(program_state::make_xml): Replace decl with...
(program_state::make_diagnostic_state_graph): ...this.
(program_state::dump_xml_to_pp): Drop decl.
(program_state::dump_xml_to_file): Drop decl.
(program_state::dump_xml): Drop decl.
(program_state::dump_dump_sarif): New decl.
* sm-malloc.cc (get_dynalloc_state_for_state): New.
(malloc_state_machine::add_state_to_xml): Replace with...
(malloc_state_machine::add_state_to_state_graph): ...this.
* sm.cc (state_machine::add_state_to_xml): Replace with...
(state_machine::add_state_to_state_graph): ...this.
(state_machine::add_global_state_to_xml): Replace with...
(state_machine::add_global_state_to_state_graph): ...this.
* sm.h (class xml_state): Drop forward decl.
(class analyzer_state_graph): New forward decl.
(state_machine::add_state_to_xml): Replace decl with...
(state_machine::add_state_to_state_graph): ...this.
(state_machine::add_global_state_to_xml): Replace decl with...
(state_machine::add_global_state_to_state_graph): ...this.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/state-diagram-1-sarif.py (test_xml_state):
Rename to...
(test_state_graph): ...this. Port from XML to SARIF graphs.
* gcc.dg/analyzer/state-diagram-1.c: Update sink option
from "sarif:xml-state=yes" to "sarif:state-graphs=yes".
* gcc.dg/analyzer/state-diagram-5-sarif.c: Likewise.
* gcc.dg/analyzer/state-diagram-5-sarif.py: Drop import of ET.
(test_nested_types_in_xml_state): Rename to...
(test_nested_types_in_state_graph): ...this. Port from XML to
SARIF graphs.
* gcc.dg/plugin/diagnostic-test-graphs-html.c: New test.
* gcc.dg/plugin/diagnostic-test-graphs-html.py: New test script.
* gcc.dg/plugin/diagnostic-test-graphs-sarif.c: New test.
* gcc.dg/plugin/diagnostic-test-graphs-sarif.py: New test script.
* gcc.dg/plugin/diagnostic-test-graphs.c: New test.
* gcc.dg/plugin/diagnostic_plugin_test_graphs.cc: New test plugin.
* gcc.dg/plugin/plugin.exp (plugin_test_list): Add the above.
* lib/sarif.py (get_xml_state): Delete.
(get_state_graph): New.
(def get_state_node_attr): New.
(get_state_node_kind): New.
(get_state_node_name): New.
(get_state_node_type): New.
(get_state_node_value): New.
* sarif-replay.dg/2.1.0-invalid/3.40.2-duplicate-node-id.sarif:
New test.
* sarif-replay.dg/2.1.0-invalid/3.41.4-unrecognized-node-id.sarif:
New test.
* sarif-replay.dg/2.1.0-valid/graphs-check-html.py: New test
script.
* sarif-replay.dg/2.1.0-valid/graphs-check-sarif-roundtrip.py: New
test script.
* sarif-replay.dg/2.1.0-valid/graphs.sarif: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/ChangeLog:
* doc/libgdiagnostics/topics/compatibility.rst
(_LIBGDIAGNOSTICS_ABI_2): Add missing anchor.
* doc/libgdiagnostics/topics/diagnostic-manager.rst
(diagnostic_manager_add_sink_from_spec): Add links to GCC's
documentation of "-fdiagnostics-add-output=". Fix parameter
markup.
(diagnostic_manager_set_analysis_target): Fix parameter markup.
Add link to SARIF spec.
* doc/libgdiagnostics/topics/logical-locations.rst: Markup fix.
* doc/libgdiagnostics/tutorial/02-physical-locations.rst: Clarify
wording of what "the source file" means, and that a range can't
have multiple files.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
[PR116792,PR116163]
This patch refactors the support for -fdiagnostics-add-output=SCHEME
from GCC's options parsing so that it is also available to
sarif-replay and to other clients of libgdiagnostics.
With this users of sarif-replay and other such tools can generate HTML
or SARIF as well as text output, using the same
-fdiagnostics-add-output=SCHEME
as GCC.
As a test, the patch adds support for this option to the dg-lint
script below "contrib". For example dg-lint can now generate text,
html, and sarif output via:
LD_LIBRARY_PATH=../build/gcc/ \
./contrib/dg-lint/dg-lint \
contrib/dg-lint/test-*.c \
-fdiagnostics-add-output=experimental-html:file=dg-lint-tests.html \
-fdiagnostics-add-output=sarif:file=dg-lint-tests.sarif
where the HTML output from dg-lint can be seen here:
https://dmalcolm.fedorapeople.org/gcc/2025-06-20/dg-lint-tests.html
the sarif output here:
https://dmalcolm.fedorapeople.org/gcc/2025-06-23/dg-lint-tests.sarif
and a screenshot of VS Code viewing the sarif output is here:
https://dmalcolm.fedorapeople.org/gcc/2025-06-23/vscode-viewing-dg-lint-sarif-output.png
As well as allowing sarif-replay to generate HTML, this patch allows
sarif-replay to also generate SARIF. Ideally this would faithfully
round-trip all the data, but it's not perfect (which I'm tracking as
PR sarif-replay/120792).
contrib/ChangeLog:
PR other/116792
PR testsuite/116163
PR sarif-replay/120792
* dg-lint/dg-lint: Add -fdiagnostics-add-output.
* dg-lint/libgdiagnostics.py: Add
diagnostic_manager_add_sink_from_spec.
(Manager.add_sink_from_spec): New.
gcc/ChangeLog:
PR other/116792
PR testsuite/116163
PR sarif-replay/120792
* Makefile.in (OBJS-libcommon): Add diagnostic-output-spec.o.
* diagnostic-format-html.cc (html_builder::html_builder): Ensure
title is non-empty.
* diagnostic-output-spec.cc: New file, taken from material in
opts-diagnostic.cc.
* diagnostic-output-spec.h: New file.
* diagnostic.cc (diagnostic_context::set_main_input_filename):
New.
* diagnostic.h (diagnostic_context::set_main_input_filename): New
decl.
* doc/libgdiagnostics/topics/compatibility.rst
(LIBGDIAGNOSTICS_ABI_2): New.
* doc/libgdiagnostics/topics/diagnostic-manager.rst
(diagnostic_manager_add_sink_from_spec): New.
(diagnostic_manager_set_analysis_target): New.
* libgdiagnostics++.h (manager::add_sink_from_spec): New.
(manager::set_analysis_target): New.
* libgdiagnostics.cc: Include "diagnostic-output-spec.h".
(struct spec_context): New.
(diagnostic_manager_add_sink_from_spec): New.
(diagnostic_manager_set_analysis_target): New.
* libgdiagnostics.h
(LIBDIAGNOSTICS_HAVE_diagnostic_manager_add_sink_from_spec): New
define.
(diagnostic_manager_add_sink_from_spec): New decl.
(LIBDIAGNOSTICS_HAVE_diagnostic_manager_set_analysis_target): New
define.
(diagnostic_manager_set_analysis_target): New decl.
* libgdiagnostics.map (LIBGDIAGNOSTICS_ABI_2): New.
* libsarifreplay.cc (sarif_replayer::handle_artifact_obj): Looks
for "analysisTarget" in roles and call set_analysis_target using
the artifact if found.
* opts-diagnostic.cc: Refactor, moving material to
diagnostic-output-spec.cc.
(struct opt_spec_context): New.
(handle_OPT_fdiagnostics_add_output_): Use opt_spec_context.
(handle_OPT_fdiagnostics_set_output_): Likewise.
* sarif-replay.cc: Define INCLUDE_STRING.
(struct options): Add m_extra_output_specs.
(usage_msg): Add -fdiagnostics-add-output=SCHEME.
(str_starts_with): New.
(parse_options): Add -fdiagnostics-add-output=SCHEME.
(main): Likewise.
* selftest-run-tests.cc (selftest::run_tests): Call
diagnostic_output_spec_cc_tests rather than
opts_diagnostic_cc_tests.
* selftest.h (selftest::diagnostic_output_spec_cc_tests):
Replace...
(selftest::opts_diagnostic_cc_tests): ...this.
gcc/testsuite/ChangeLog:
PR other/116792
PR testsuite/116163
PR sarif-replay/120792
* sarif-replay.dg/2.1.0-valid/signal-1-check-html.py: New test
script.
* sarif-replay.dg/2.1.0-valid/signal-1.c.sarif: Add html and sarif
generation to options. Invoke the new script to verify that HTML
and SARIF is generated.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/ChangeLog:
* diagnostic-format-sarif.cc (maybe_get_sarif_kind): Add cases for
new kinds of logical location.
* doc/libgdiagnostics/topics/logical-locations.rst: Add new kinds
of logical location for handling XML and JSON.
* libgdiagnostics.cc (impl_logical_location_manager::get_kind):
Add cases for new kinds of logical location.
(diagnostic_text_sink::text_starter): Likewise, introducing a
macro for this.
(diagnostic_manager_debug_dump_logical_location): Likewise.
* libgdiagnostics.h (enum diagnostic_logical_location_kind_t): Add
new kinds of logical location for handling XML and JSON.
* libsarifreplay.cc (handle_logical_location_object): Add entries
to "kind_values" for decoding sarif logical location kinds
relating to XML and JSON.
* logical-location.h (enum logical_location_kind): Add new kinds
of logical location for handling XML and JSON.
gcc/testsuite/ChangeLog:
* libgdiagnostics.dg/test-nested-logical-locations-json-c.py: New test.
* libgdiagnostics.dg/test-nested-logical-locations-json.c: New test.
* sarif-replay.dg/2.1.0-valid/3.33.7-json-example.sarif: New test.
* sarif-replay.dg/2.1.0-valid/3.33.7-xml-example.sarif: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
[LIBGDIAGNOSTICS_ABI_1]
For followup work I need to be able to get at data from a
diagnostic_logical_location after creating it, hence the
need to extend libgdiagnostics with accessor entrypoints.
This is the first extension to libgdiagnostics since the initial
release. The patch uses symbol versioning to add the new
entrypoints in the same way that libgccjit does.
gcc/ChangeLog:
* doc/libgdiagnostics/topics/compatibility.rst: New file, based
on gcc/jit/docs/topics/compatibility.rst.
* doc/libgdiagnostics/topics/index.rst: Add compatibility.rst.
* doc/libgdiagnostics/topics/logical-locations.rst (Accessors):
New section.
* libgdiagnostics++.h (logical_location::operator bool): New.
(logical_location::operator==): New.
(logical_location::operator!=): New.
(logical_location::get_kind): New.
(logical_location::get_parent): New.
(logical_location::get_short_name): New.
(logical_location::get_fully_qualified_name): New.
(logical_location::get_decorated_name): New.
* libgdiagnostics.cc
(diagnostic_logical_location::get_fully_qualified_name): New.
(diagnostic_logical_location_get_kind): New entrypoint.
(diagnostic_logical_location_get_parent): New entrypoint.
(diagnostic_logical_location_get_short_name): New entrypoint.
(diagnostic_logical_location_get_fully_qualified_name): New
entrypoint.
(diagnostic_logical_location_get_decorated_name): New entrypoint.
* libgdiagnostics.h
(LIBDIAGNOSTICS_HAVE_LOGICAL_LOCATION_ACCESSORS): New define.
(diagnostic_logical_location_get_kind): New entrypoint.
(diagnostic_logical_location_get_parent): New entrypoint.
(diagnostic_logical_location_get_short_name): New entrypoint.
(diagnostic_logical_location_get_fully_qualified_name): New
entrypoint.
(diagnostic_logical_location_get_decorated_name): New entrypoint.
* libgdiagnostics.map (LIBGDIAGNOSTICS_ABI_1): New.
gcc/testsuite/ChangeLog:
* libgdiagnostics.dg/test-logical-location.c: Include
<string.h>.
(main): Verify that the accessors work.
* libgdiagnostics.dg/test-logical-location.cc: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
In our .sarif output from e.g.:
bad-binary-op.c: In function ‘test_4’:
bad-binary-op.c:19:23: error: invalid operands to binary + (have ‘S’ {aka ‘struct s’} and ‘T’ {aka ‘struct t’})
19 | return callee_4a () + callee_4b ();
| ~~~~~~~~~~~~ ^ ~~~~~~~~~~~~
| | |
| | T {aka struct t}
| S {aka struct s}
the labelled ranges are captured in the 'annotations' property of the
'location' object (§3.28.6).
However sarif-replay emits just:
In function 'test_4':
bad-binary-op.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 ();
| ^
missing the labelled ranges.
This patch adds support to sarif-replay for the 'annotations' property;
with this patch we emit:
In function 'test_4':
bad-binary-op.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}
thus showing the labelled ranges.
Doing so requires adding a new entrypoint to libgdiagnostics:
diagnostic_physical_location_get_file
Given that we haven't yet released a stable version and that
sarif-replay is built together with libgdiagnostics I didn't
bother updating the ABI version.
gcc/ChangeLog:
PR sarif-replay/118881
* doc/libgdiagnostics/topics/physical-locations.rst: Add
diagnostic_physical_location_get_file.
* libgdiagnostics++.h (physical_location::get_file): New wrapper.
(diagnostic::add_location): Likewise.
* libgdiagnostics.cc (diagnostic_manager::get_file_by_name): New.
(diagnostic_physical_location::get_file): New.
(diagnostic_physical_location_get_file): New.
* libgdiagnostics.h (diagnostic_physical_location_get_file): New.
* libgdiagnostics.map (diagnostic_physical_location_get_file): New.
* libsarifreplay.cc (class annotation): New.
(add_any_annotations): New.
(sarif_replayer::handle_result_obj): Collect vectors of
annotations in the calls to handle_location_object and apply them
to "err" and to "note" as appropriate.
(sarif_replayer::handle_thread_flow_location_object): Pass nullptr
for annotations.
(sarif_replayer::handle_location_object): Handle §3.28.6
"annotations" property, using it to populate a new
"out_annotations" param.
gcc/testsuite/ChangeLog:
PR sarif-replay/118881
* sarif-replay.dg/2.1.0-valid/3.28.6-annotations-1.sarif: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
|
|
libgdiagnostics/conf.py breaks update-copyright.py --this-year,
which only accepts copyright year in u'' literals in python files,
not in ''.
2025-01-02 Jakub Jelinek <jakub@redhat.com>
* doc/libgdiagnostics/conf.py: Use u'' instead of '' in
project and copyright initialization.
|
|
This patch updates diagnostic_manager_new_logical_location so
that repeated calls with the same input values yield the same
instance of diagnostic_logical_location.
Doing so allows the path-printing logic to properly consolidate runs of
events, whereas previously it could treat each event as having a
distinct logical location, and thus require them to be printed
separately; this greatly improves the output of sarif-replay when
displaying execution paths.
gcc/ChangeLog:
* doc/libgdiagnostics/topics/logical-locations.rst
(diagnostic_manager_new_logical_location): Add note about repeated
calls.
* libgdiagnostics.cc: Define INCLUDE_MAP.
(class owned_nullable_string): Add copy ctor and move ctor.
(owned_nullable_string::operator<): New.
(diagnostic_logical_location::operator<): New.
(diagnostic_manager::new_logical_location): Use m_logical_locs to
"uniquify" instances, converting it to a std::map.
(diagnostic_manager::logical_locs_map_t): New typedef.
(diagnostic_manager::t m_logical_locs): Convert from a std::vector
to a std::map.
(diagnostic_execution_path::same_function_p): Update comment.
gcc/testsuite/ChangeLog:
* libgdiagnostics.dg/test-logical-location.c: Include <assert.h>.
Verify that creating a diagnostic_logical_location with equal
values yields the same instance.
* sarif-replay.dg/2.1.0-valid/malloc-vs-local-4.c.sarif: New test.
* sarif-replay.dg/2.1.0-valid/signal-1.c.moved.sarif: Update
expected output to show logical location and for consolidation of
events into runs.
* sarif-replay.dg/2.1.0-valid/signal-1.c.sarif: Likewise.
* sarif-replay.dg/2.1.0-valid/spec-example-4.sarif: Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
The diagnostic source-quoting machinery uses class file_cache
implemented in gcc/input.cc for (re)reading the source when
issuing diagnostics.
When sarif-replay issues a saved diagnostic it might be running
in a different path to where the .sarif file was captured, or
on an entirely different machine.
Previously such invocations would lead to the source-quoting
silently failing, even if the content of the file is recorded
in the .sarif file in the artifact "contents" property (which
gcc populates when emitting .sarif output).
This patch:
- adds the ability for slots in file_cache to be populated from memory
rather than from the filesystem
- exposes it in libgdiagnostics via a new entrypoint
- uses this in sarif-replay for any artifacts with a "contents"
property, so that source-quoting uses that rather than trying to read
from the path on the filesystem
gcc/ChangeLog:
PR sarif-replay/117943
* doc/libgdiagnostics/topics/physical-locations.rst
(diagnostic_manager_new_file): Drop "const" from return type.
* doc/libgdiagnostics/tutorial/02-physical-locations.rst: Drop
"const" from "main_file" decl.
* input.cc (file_cache::add_buffered_content): New.
(file_cache_slot::set_content): New.
(file_cache_slot::dump): Use m_file_path being null rather than
m_fp to determine empty slots. Dump m_fp.
(find_end_of_line): Drop "const" from return type and param. Add
forward decl.
(file_cache_slot::get_next_line): Fix "const"-ness.
(selftest::test_reading_source_buffer): New.
(selftest::input_cc_tests): Call it.
* input.h (file_cache::add_buffered_content): New decl.
* libgdiagnostics++.h (class file): Drop const-ness from m_inner.
(file::set_buffered_content): New.
* libgdiagnostics.cc (class content_buffer): New.
(diagnostic_file::diagnostic_file): Add "mgr" param.
(diagnostic_file::get_content): New.
(diagnostic_file::set_buffered_content): New.
(diagnostic_file::m_mgr): New.
(diagnostic_file::m_content): New.
(diagnostic_manager::new_file): Drop const-ness. Pass *this to
ctor.
(diagnostic_file::set_buffered_content): New.
(diagnostic_manager_new_file): Drop "const" from return type.
(diagnostic_file_set_buffered_content): New entrypoint.
(diagnostic_manager_debug_dump_file): Dump the content size,
if any.
* libgdiagnostics.h (diagnostic_manager_new_file): Drop "const"
from return type.
(diagnostic_file_set_buffered_content): New decl.
* libgdiagnostics.map (diagnostic_file_set_buffered_content): New
symbol.
* libsarifreplay.cc (sarif_replayer::m_artifacts_arr): Convert
from json::value to json::array.
(sarif_replayer::handle_run_obj): Call handle_artifact_obj
on all artifacts.
(sarif_replayer::handle_artifact_obj): New.
gcc/testsuite/ChangeLog:
PR sarif-replay/117943
* sarif-replay.dg/2.1.0-valid/error-with-note.sarif: Update
expected output to include quoted source code and underlines.
* sarif-replay.dg/2.1.0-valid/signal-1.c.moved.sarif: New test.
* sarif-replay.dg/2.1.0-valid/signal-1.c.sarif: Update expected
output to include quoted source code and underlines.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/ChangeLog:
* doc/libgdiagnostics/topics/execution-paths.rst: Add '§' before
references to section of SARIF spec.
* doc/libgdiagnostics/topics/fix-it-hints.rst: Likewise.
* doc/libgdiagnostics/tutorial/01-hello-world.rst: Fix typo.
* doc/libgdiagnostics/tutorial/02-physical-locations.rst: Likewise.
* doc/libgdiagnostics/tutorial/04-notes.rst: Likewise.
* doc/libgdiagnostics/tutorial/06-fix-it-hints.rst: Add link to
diagnostic_add_fix_it_hint_replace.
* doc/libgdiagnostics/tutorial/07-execution-paths.rst: Add '§'.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/ChangeLog:
* doc/libgdiagnostics/conf.py: Remove "author". Change
"copyright" field to the FSF.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
gcc/ChangeLog:
* doc/libgdiagnostics/tutorial/01-hello-world.rst: Update linker
command for renaming.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|
|
"libdiagnostics" clashes with an existing soname in Debian, as
per:
https://gcc.gnu.org/pipermail/gcc/2024-November/245175.html
Rename it to "libgdiagnostics" for uniqueness.
I am being deliberately vague about what the "g" stands for:
it could be "gnu", "gcc", or "gpl-licensed" as the reader desires.
ChangeLog:
* configure.ac: Rename "libdiagnostics" to "libgdiagnostics".
* configure: Regenerate.
gcc/ChangeLog:
* Makefile.in: Rename "libdiagnostics" to "libgdiagnostics".
* configure.ac: Likewise.
* configure: Regenerate.
* doc/install.texi: Rename "libdiagnostics" to
"libgdiagnostics".
* doc/libdiagnostics/*: Rename to doc/libgdiagnostics, renaming
"libdiagnostics" to "libgdiagnostics" throughout.
* libdiagnostics++.h: Rename to...
* libgdiagnostics++.h: ...this, renaming "libdiagnostics" to
"libgdiagnostics" throughout.
* libdiagnostics.cc: Rename to...
* libgdiagnostics.cc: ...this, renaming "libdiagnostics" to
"libgdiagnostics" throughout.
* libdiagnostics.h: Rename to...
* libgdiagnostics.h: ...this, renaming "libdiagnostics" to
"libgdiagnostics" throughout.
* libdiagnostics.map: Rename to...
* libgdiagnostics.map: ...this, renaming "libdiagnostics" to
"libgdiagnostics" throughout.
* libsarifreplay.cc: Update for renaming of "libdiagnostics"
to "libgdiagnostics".
* libsarifreplay.h: Likewise.
* sarif-replay.cc: Likewise.
gcc/testsuite/ChangeLog:
* libdiagnostics.dg/*: Rename to libgdiagnostics.dg, renaming
"libdiagnostics" to "libgdiagnostics" throughout.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
|