aboutsummaryrefslogtreecommitdiff
path: root/gcc/doc/libgdiagnostics
AgeCommit message (Collapse)AuthorFilesLines
2025-08-04diagnostics: improve support for nesting levels [PR116253]David Malcolm2-0/+25
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>
2025-07-15libgdiagnostics: add diagnostic_message_buffer [PR120792]David Malcolm10-5/+498
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>
2025-07-11diagnostics: add support for directed graphs; use them for state graphsDavid Malcolm3-0/+229
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>
2025-07-11libgdiagnostics: doc fixesDavid Malcolm4-21/+25
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>
2025-06-23libgdiagnostics: sarif-replay: add extra sinks via -fdiagnostics-add-output= ↵David Malcolm2-0/+51
[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>
2025-05-06diagnostics: support XML and JSON kinds of logical locationsDavid Malcolm1-0/+28
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>
2025-05-06libgdiagnostics: add accessors for diagnostic_logical_location ↵David Malcolm3-0/+205
[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>
2025-02-15sarif-replay: display annotations as labelled ranges (§3.28.6) [PR118881]David Malcolm1-0/+5
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>
2025-01-02Update copyright years.Jakub Jelinek22-22/+22
2025-01-02Use u'' instead of '' in libgdiagnostics/conf.pyJakub Jelinek1-2/+2
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.
2024-12-16libgdiagnostics: consolidate logical locationsDavid Malcolm1-0/+6
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>
2024-12-16sarif-replay: quote source from artifact contents [PR117943]David Malcolm2-4/+4
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>
2024-12-04libgdiagnostics: documentation tweaksDavid Malcolm7-8/+9
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>
2024-12-03libgdiagnostics: fix docs metadataDavid Malcolm1-2/+1
gcc/ChangeLog: * doc/libgdiagnostics/conf.py: Remove "author". Change "copyright" field to the FSF. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2024-12-02libgdiagnostics: fix a missing rename in the docsDavid Malcolm1-1/+1
gcc/ChangeLog: * doc/libgdiagnostics/tutorial/01-hello-world.rst: Update linker command for renaming. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
2024-11-29Rename "libdiagnostics" to "libgdiagnostics"David Malcolm26-0/+2433
"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>