From 8cd2db265e73c55f20c05bddf23d3e0165488b2c Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Fri, 3 Oct 2025 11:04:53 -0400 Subject: [PATCH] Revert: r16-4193 ("diagnostics: generalize state graph code to use json::property instances") This reverts commit e4ab1f87805a6555bc327538d67067f3a690eddc. Patch r16-4193-ge4ab1f87805a65 seems to have broken the build with GCC 5.5 (PR bootstrap/122151). Sorry about this. Signed-off-by: David Malcolm --- contrib/gcc.doxy | 2 +- gcc/Makefile.in | 3 +- gcc/analyzer/ana-state-to-diagnostic-state.cc | 163 +++++++------- gcc/analyzer/ana-state-to-diagnostic-state.h | 23 +- gcc/analyzer/checker-event.cc | 9 +- gcc/analyzer/sm-malloc.cc | 29 +-- gcc/configure | 2 +- gcc/configure.ac | 2 +- gcc/custom-sarif-properties/digraphs.cc | 28 --- gcc/custom-sarif-properties/digraphs.h | 37 ---- gcc/custom-sarif-properties/state-graphs.cc | 157 -------------- gcc/custom-sarif-properties/state-graphs.h | 97 --------- gcc/diagnostics/diagnostics-selftests.cc | 1 + gcc/diagnostics/diagnostics-selftests.h | 1 + gcc/diagnostics/digraphs.cc | 199 ++++-------------- gcc/diagnostics/digraphs.h | 62 ++---- gcc/diagnostics/html-sink.cc | 62 ++---- gcc/diagnostics/html-sink.h | 9 +- gcc/diagnostics/output-spec.cc | 12 +- gcc/diagnostics/state-graphs-to-dot.cc | 139 ++++++------ gcc/diagnostics/state-graphs.cc | 156 ++++++++++++++ gcc/diagnostics/state-graphs.h | 108 ++++++++++ gcc/doc/invoke.texi | 8 +- gcc/json.cc | 25 --- gcc/json.h | 82 -------- .../plugin/diagnostic_plugin_test_graphs.cc | 5 +- 26 files changed, 521 insertions(+), 900 deletions(-) delete mode 100644 gcc/custom-sarif-properties/digraphs.cc delete mode 100644 gcc/custom-sarif-properties/digraphs.h delete mode 100644 gcc/custom-sarif-properties/state-graphs.cc delete mode 100644 gcc/custom-sarif-properties/state-graphs.h create mode 100644 gcc/diagnostics/state-graphs.cc diff --git a/contrib/gcc.doxy b/contrib/gcc.doxy index 56e3845d00d..15952046f25 100644 --- a/contrib/gcc.doxy +++ b/contrib/gcc.doxy @@ -478,7 +478,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = gcc gcc/analyzer gcc/custom-sarif-properties gcc/diagnostics gcc/text-art +INPUT = gcc gcc/analyzer gcc/diagnostics gcc/text-art # This tag can be used to specify the character encoding of the source files that # doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 098bafbce53..6a9d6204c86 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1852,8 +1852,6 @@ OBJS = \ # Objects in libcommon.a, potentially used by all host binaries and with # no target dependencies. OBJS-libcommon = \ - custom-sarif-properties/digraphs.o \ - custom-sarif-properties/state-graphs.o \ diagnostic-global-context.o \ diagnostics/buffering.o \ diagnostics/changes.o \ @@ -1873,6 +1871,7 @@ OBJS-libcommon = \ diagnostics/paths.o \ diagnostics/paths-output.o \ diagnostics/source-printing.o \ + diagnostics/state-graphs.o \ diagnostics/state-graphs-to-dot.o \ diagnostics/selftest-context.o \ diagnostics/selftest-logical-locations.o \ diff --git a/gcc/analyzer/ana-state-to-diagnostic-state.cc b/gcc/analyzer/ana-state-to-diagnostic-state.cc index 39acf26bdd5..996538c3785 100644 --- a/gcc/analyzer/ana-state-to-diagnostic-state.cc +++ b/gcc/analyzer/ana-state-to-diagnostic-state.cc @@ -39,55 +39,38 @@ along with GCC; see the file COPYING3. If not see namespace ana { -namespace node_properties = custom_sarif_properties::state_graphs::node; +using namespace ::diagnostics::state_graphs; static void -set_wi_attr (diagnostics::digraphs::node &state_node, - const json::string_property &property, +set_wi_attr (state_node_ref state_node, + const char *attr_name, const wide_int_ref &w, signop sgn) { pretty_printer pp; pp_wide_int (&pp, w, sgn); - state_node.set_property (property, pp_formatted_text (&pp)); + state_node.set_attr (attr_name, pp_formatted_text (&pp)); } static void -set_type_attr (diagnostics::digraphs::node &state_node, - const_tree type) +set_type_attr (state_node_ref state_node, const_tree type) { gcc_assert (type); pretty_printer pp; pp_format_decoder (&pp) = default_tree_printer; pp_printf (&pp, "%T", type); - state_node.set_property (node_properties::type, - pp_formatted_text (&pp)); + state_node.set_type (pp_formatted_text (&pp)); } static void -set_bits_attr (diagnostics::digraphs::node & state_node, +set_bits_attr (state_node_ref state_node, bit_range bits) { pretty_printer pp; bits.dump_to_pp (&pp); - state_node.set_property (node_properties::bits, - pp_formatted_text (&pp)); + state_node.set_attr ("bits", pp_formatted_text (&pp)); } -static void -set_value_attrs (diagnostics::digraphs::node &state_node, - const svalue &sval) -{ - state_node.set_property (node_properties::value, - sval.to_json ()); - pretty_printer pp; - pp_format_decoder (&pp) = default_tree_printer; - sval.dump_to_pp (&pp, true); - state_node.set_property (node_properties::value_str, - pp_formatted_text (&pp)); -} - - // class analyzer_state_graph : public diagnostics::digraphs::digraph analyzer_state_graph::analyzer_state_graph (const program_state &state, @@ -158,34 +141,34 @@ analyzer_state_graph::analyzer_state_graph (const program_state &state, /* Ensure we have a node for the dst region. This could lead to additional pending edges. */ - auto &dst_node = get_or_create_state_node (item.m_dst_reg); - add_edge (nullptr, item.m_src_node, dst_node); + auto dst_node = get_or_create_state_node (item.m_dst_reg); + add_edge (nullptr, item.m_src_node.m_node, dst_node.m_node); } } -diagnostics::digraphs::node & +state_node_ref analyzer_state_graph::get_or_create_state_node (const region ®) { auto existing = m_region_to_state_node_map.find (®); if (existing != m_region_to_state_node_map.end ()) return *existing->second; - auto &state_node = create_and_add_state_node (reg); - m_region_to_state_node_map[®] = &state_node; - return state_node; + auto ref = create_and_add_state_node (reg); + m_region_to_state_node_map[®] = &ref.m_node; + return ref; } -diagnostics::digraphs::node & +state_node_ref analyzer_state_graph::create_and_add_state_node (const region ®) { auto node = create_state_node (reg); - diagnostics::digraphs::node &result = *node; + state_node_ref result = *node; if (auto parent_reg = reg.get_parent_region ()) if (parent_reg->get_kind () != RK_ROOT) { - auto &parent_state_node = get_or_create_state_node (*parent_reg); - parent_state_node.add_child (std::move (node)); + auto parent_state_node = get_or_create_state_node (*parent_reg); + parent_state_node.m_node.add_child (std::move (node)); return result; } add_node (std::move (node)); @@ -281,18 +264,19 @@ analyzer_state_graph::make_node_id (const region ®) std::unique_ptr analyzer_state_graph:: -make_state_node (enum node_properties::kind kind, +make_state_node (diagnostics::state_graphs::node_kind kind, std::string id) { auto node = std::make_unique (*this, std::move (id)); - node->set_property (node_properties::kind, kind); + state_node_ref node_ref (*node); + node_ref.set_node_kind (kind); return node; } std::unique_ptr analyzer_state_graph:: make_memspace_state_node (const region ®, - enum node_properties::kind kind) + diagnostics::state_graphs::node_kind kind) { return make_state_node (kind, make_node_id (reg)); } @@ -312,7 +296,7 @@ analyzer_state_graph::create_state_node (const region ®) const frame_region &frame_reg = static_cast (reg); - node = make_state_node (node_properties::kind::stack_frame, + node = make_state_node (diagnostics::state_graphs::node_kind::stack_frame, make_node_id (reg)); node->set_logical_loc (m_logical_loc_mgr.key_from_tree (frame_reg.get_fndecl ())); @@ -320,59 +304,58 @@ analyzer_state_graph::create_state_node (const region ®) pretty_printer pp; pp_format_decoder (&pp) = default_tree_printer; pp_printf (&pp, "%E", frame_reg.get_fndecl ()); - node->set_property (node_properties::function, - pp_formatted_text (&pp)); + node->set_attr (STATE_NODE_PREFIX, "function", + pp_formatted_text (&pp)); } } break; case RK_GLOBALS: node = make_memspace_state_node (reg, - node_properties::kind::globals); + diagnostics::state_graphs::node_kind::globals); break; case RK_CODE: node = make_memspace_state_node (reg, - node_properties::kind::code); + diagnostics::state_graphs::node_kind::code); break; case RK_FUNCTION: node = make_memspace_state_node (reg, - node_properties::kind::function); + diagnostics::state_graphs::node_kind::function); // TODO break; case RK_STACK: node = make_memspace_state_node (reg, - node_properties::kind::stack); + diagnostics::state_graphs::node_kind::stack); break; case RK_HEAP: node = make_memspace_state_node (reg, - node_properties::kind::heap_); + diagnostics::state_graphs::node_kind::heap_); break; case RK_THREAD_LOCAL: node = make_memspace_state_node (reg, - node_properties::kind::thread_local_); + diagnostics::state_graphs::node_kind::thread_local_); break; case RK_ROOT: gcc_unreachable (); break; case RK_SYMBOLIC: node = make_memspace_state_node (reg, - node_properties::kind::other); + diagnostics::state_graphs::node_kind::other); break; case RK_DECL: { - node = make_state_node (node_properties::kind::variable, + node = make_state_node (diagnostics::state_graphs::node_kind::variable, make_node_id (reg)); const decl_region &decl_reg = static_cast (reg); - + state_node_ref node_ref (*node); { pretty_printer pp; pp_format_decoder (&pp) = default_tree_printer; pp_printf (&pp, "%E", decl_reg.get_decl ()); - node->set_property (node_properties::name, - pp_formatted_text (&pp)); + node_ref.set_name (pp_formatted_text (&pp)); } set_type_attr (*node, TREE_TYPE (decl_reg.get_decl ())); } @@ -394,14 +377,14 @@ analyzer_state_graph::create_state_node (const region ®) case RK_ERRNO: case RK_PRIVATE: case RK_UNKNOWN: - node = make_state_node (node_properties::kind::other, + node = make_state_node (diagnostics::state_graphs::node_kind::other, make_node_id (reg)); break; case RK_HEAP_ALLOCATED: case RK_ALLOCA: node = make_memspace_state_node (reg, - node_properties::kind::dynalloc_buffer); + diagnostics::state_graphs::node_kind::dynalloc_buffer); set_attr_for_dynamic_extents (reg, *node); break; } @@ -442,9 +425,9 @@ create_state_nodes_for_binding_cluster (const binding_cluster &cluster, get_or_create_state_node (*reg); } - auto &ref = get_or_create_state_node (*cluster.get_base_region ()); + auto ref = get_or_create_state_node (*cluster.get_base_region ()); - ref.add_child (create_state_node_for_conc_bindings (conc_bindings)); + ref.m_node.add_child (create_state_node_for_conc_bindings (conc_bindings)); const region *typed_reg = cluster.get_base_region (); if (!typed_reg->get_type ()) @@ -472,18 +455,23 @@ create_state_nodes_for_binding_cluster (const binding_cluster &cluster, std::unique_ptr analyzer_state_graph::create_state_node_for_conc_bindings (const concrete_bindings_t &conc_bindings) { - auto node = make_state_node (node_properties::kind::other, + auto node = make_state_node (diagnostics::state_graphs::node_kind::other, make_node_id ("concrete-bindings")); for (auto iter : conc_bindings) { const bit_range bits = iter.first; const svalue *sval = iter.second; auto binding_state_node - = make_state_node (node_properties::kind::other, + = make_state_node (diagnostics::state_graphs::node_kind::other, make_node_id ("binding")); set_bits_attr (*binding_state_node, bits); - gcc_assert (sval); - set_value_attrs (*binding_state_node, *sval); + { + pretty_printer pp; + pp_format_decoder (&pp) = default_tree_printer; + sval->dump_to_pp (&pp, true); + binding_state_node->set_attr (STATE_NODE_PREFIX, "value", + pp_formatted_text (&pp)); + } node->add_child (std::move (binding_state_node)); } return node; @@ -508,28 +496,27 @@ analyzer_state_graph::get_bit_range_within_base_region (const region ®, void analyzer_state_graph:: -populate_state_node_for_typed_region (diagnostics::digraphs::node &state_node, +populate_state_node_for_typed_region (state_node_ref node, const region ®, const concrete_bindings_t &conc_bindings, bool create_all) { const_tree reg_type = reg.get_type (); gcc_assert (reg_type); - set_type_attr (state_node, reg_type); + set_type_attr (node, reg_type); bit_range bits (0, 0); if (get_bit_range_within_base_region (reg, bits)) { - set_bits_attr (state_node, bits); + set_bits_attr (node, bits); auto search = conc_bindings.find (bits); if (search != conc_bindings.end ()) { const svalue *bound_sval = search->second; - gcc_assert (bound_sval); - set_value_attrs (state_node, *bound_sval); + node.set_json_attr ("value", bound_sval->to_json ()); if (const region *dst_reg = bound_sval->maybe_get_region ()) - m_pending_edges.push_back ({state_node, *dst_reg}); + m_pending_edges.push_back ({node, *dst_reg}); } } @@ -568,10 +555,9 @@ populate_state_node_for_typed_region (diagnostics::digraphs::node &state_node, { auto child_state_node = make_state_node - (node_properties::kind::element, + (diagnostics::state_graphs::node_kind::element, make_node_id (*child_reg)); - set_wi_attr (*child_state_node, - node_properties::index, idx, UNSIGNED); + set_wi_attr (*child_state_node, "index", idx, UNSIGNED); // Recurse: gcc_assert (element_type); @@ -579,7 +565,7 @@ populate_state_node_for_typed_region (diagnostics::digraphs::node &state_node, *child_reg, conc_bindings, create_all); - state_node.add_child (std::move (child_state_node)); + node.m_node.add_child (std::move (child_state_node)); } } } @@ -601,12 +587,11 @@ populate_state_node_for_typed_region (diagnostics::digraphs::node &state_node, { auto child_state_node = make_state_node - (node_properties::kind::padding, + (diagnostics::state_graphs::node_kind::padding, make_node_id (*child_reg)); - set_wi_attr (*child_state_node, - node_properties::num_bits, + set_wi_attr (*child_state_node, "num_bits", item.m_bit_range.m_size_in_bits, SIGNED); - state_node.add_child (std::move (child_state_node)); + node.m_node.add_child (std::move (child_state_node)); } } else @@ -615,27 +600,27 @@ populate_state_node_for_typed_region (diagnostics::digraphs::node &state_node, = m_mgr.get_field_region (®, const_cast (item.m_field)); if (show_child_state_node_for_child_region_p (*child_reg, - conc_bindings, - create_all)) + conc_bindings, + create_all)) { auto child_state_node = make_state_node - (node_properties::kind::field, + (diagnostics::state_graphs::node_kind::field, make_node_id (*child_reg)); { pretty_printer pp; pp_format_decoder (&pp) = default_tree_printer; pp_printf (&pp, "%D", item.m_field); - child_state_node->set_property (node_properties::name, - pp_formatted_text (&pp)); + child_state_node->set_attr (STATE_NODE_PREFIX, "name", + pp_formatted_text (&pp)); } // Recurse: populate_state_node_for_typed_region (*child_state_node, - *child_reg, - conc_bindings, - create_all); - state_node.add_child (std::move (child_state_node)); + *child_reg, + conc_bindings, + create_all); + node.m_node.add_child (std::move (child_state_node)); } } } @@ -645,9 +630,8 @@ populate_state_node_for_typed_region (diagnostics::digraphs::node &state_node, } void -analyzer_state_graph:: -set_attr_for_dynamic_extents (const region ®, - diagnostics::digraphs::node &state_node) +analyzer_state_graph::set_attr_for_dynamic_extents (const region ®, + state_node_ref node_ref) { const svalue *sval = m_state.m_region_model->get_dynamic_extents (®); if (sval) @@ -658,16 +642,15 @@ set_attr_for_dynamic_extents (const region ®, pp_wide_int (&pp, wi::to_wide (cst), UNSIGNED); else sval->dump_to_pp (&pp, true); - state_node.set_property (state_node_properties::dynamic_extents, - pp_formatted_text (&pp)); + node_ref.set_attr ("dynamic-extents", pp_formatted_text (&pp)); } } bool analyzer_state_graph:: show_child_state_node_for_child_region_p (const region ®, - const concrete_bindings_t &conc_bindings, - bool create_all) + const concrete_bindings_t &conc_bindings, + bool create_all) { if (create_all) return true; diff --git a/gcc/analyzer/ana-state-to-diagnostic-state.h b/gcc/analyzer/ana-state-to-diagnostic-state.h index eec3d56b301..3a5ccc1b430 100644 --- a/gcc/analyzer/ana-state-to-diagnostic-state.h +++ b/gcc/analyzer/ana-state-to-diagnostic-state.h @@ -23,38 +23,34 @@ along with GCC; see the file COPYING3. If not see #include "diagnostics/state-graphs.h" #include "tree-logical-location.h" -#include "custom-sarif-properties/state-graphs.h" namespace ana { -namespace state_node_properties = custom_sarif_properties::state_graphs::node; - class analyzer_state_graph : public diagnostics::digraphs::digraph { public: analyzer_state_graph (const program_state &state, const extrinsic_state &ext_state); - diagnostics::digraphs::node & + diagnostics::state_graphs::state_node_ref get_or_create_state_node (const region ®); private: - struct pending_edge { - diagnostics::digraphs::node & m_src_node; + diagnostics::state_graphs::state_node_ref m_src_node; const region &m_dst_reg; }; - - diagnostics::digraphs::node & + + diagnostics::state_graphs::state_node_ref create_and_add_state_node (const region ®); std::unique_ptr - make_state_node (enum state_node_properties::kind kind, + make_state_node (diagnostics::state_graphs::node_kind kind, std::string id); std::unique_ptr make_memspace_state_node (const region ®, - enum state_node_properties::kind kind); + enum diagnostics::state_graphs::node_kind kind); std::unique_ptr create_state_node (const region ®); @@ -75,14 +71,14 @@ private: bit_range &out); void - populate_state_node_for_typed_region (diagnostics::digraphs::node &, + populate_state_node_for_typed_region (diagnostics::state_graphs::state_node_ref, const region ®, const concrete_bindings_t &conc_bindings, bool create_all); void set_attr_for_dynamic_extents (const region ®, - diagnostics::digraphs::node &); + diagnostics::state_graphs::state_node_ref); bool show_child_state_node_for_child_region_p (const region ®, @@ -99,8 +95,7 @@ private: const program_state &m_state; const extrinsic_state &m_ext_state; region_model_manager &m_mgr; - std::map m_region_to_state_node_map; + std::map m_region_to_state_node_map; std::map m_types_for_untyped_regions; unsigned m_next_id; std::vector m_pending_edges; diff --git a/gcc/analyzer/checker-event.cc b/gcc/analyzer/checker-event.cc index 790ebc71438..4eac9450469 100644 --- a/gcc/analyzer/checker-event.cc +++ b/gcc/analyzer/checker-event.cc @@ -29,7 +29,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-logical-location.h" #include "diagnostics/sarif-sink.h" #include "diagnostics/state-graphs.h" -#include "custom-sarif-properties/state-graphs.h" #include "analyzer/analyzer-logging.h" #include "analyzer/sm.h" @@ -243,11 +242,9 @@ checker_event::maybe_make_diagnostic_state_graph (bool debug) const pretty_printer pp; text_art::theme *theme = global_dc->get_diagram_theme (); text_art::dump_to_pp (*state, theme, &pp); - const json::string_property program_state_property - (custom_sarif_properties::state_graphs::graph::prefix, - "analyzer/program_state/"); - result->set_property (program_state_property, - pp_formatted_text (&pp)); + result->set_attr (STATE_GRAPH_PREFIX, + "analyzer/program_state/", + pp_formatted_text (&pp)); } return result; diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc index b25e2adf015..a6b14219068 100644 --- a/gcc/analyzer/sm-malloc.cc +++ b/gcc/analyzer/sm-malloc.cc @@ -2735,7 +2735,7 @@ malloc_state_machine::transition_ptr_sval_non_null (region_model *model, smap->set_state (model, new_ptr_sval, m_free.m_nonnull, nullptr, ext_state); } -static enum custom_sarif_properties::state_graphs::node::dynalloc_state +static enum diagnostics::state_graphs::node_dynalloc_state get_dynalloc_state_for_state (enum resource_state rs) { switch (rs) @@ -2746,17 +2746,17 @@ get_dynalloc_state_for_state (enum resource_state rs) case RS_NULL: case RS_NON_HEAP: case RS_STOP: - return state_node_properties::dynalloc_state::unknown; + return diagnostics::state_graphs::node_dynalloc_state::unknown; case RS_ASSUMED_NON_NULL: - return state_node_properties::dynalloc_state::nonnull; + return diagnostics::state_graphs::node_dynalloc_state::nonnull; case RS_UNCHECKED: - return state_node_properties::dynalloc_state::unchecked; + return diagnostics::state_graphs::node_dynalloc_state::unchecked; case RS_NONNULL: - return state_node_properties::dynalloc_state::nonnull; + return diagnostics::state_graphs::node_dynalloc_state::nonnull; case RS_FREED: - return state_node_properties::dynalloc_state::freed; + return diagnostics::state_graphs::node_dynalloc_state::freed; } } @@ -2768,23 +2768,24 @@ add_state_to_state_graph (analyzer_state_graph &out_state_graph, { if (const region *reg = sval.maybe_get_region ()) { - auto ®_node = out_state_graph.get_or_create_state_node (*reg); + auto reg_node = out_state_graph.get_or_create_state_node (*reg); auto alloc_state = as_a_allocation_state (state); gcc_assert (alloc_state); - reg_node.set_property (state_node_properties::dynalloc_state, - get_dynalloc_state_for_state (alloc_state->m_rs)); - + reg_node.set_dynalloc_state + (get_dynalloc_state_for_state (alloc_state->m_rs)); if (alloc_state->m_deallocators) { pretty_printer pp; alloc_state->m_deallocators->dump_to_pp (&pp); - reg_node.set_property (state_node_properties::expected_deallocators, - pp_formatted_text (&pp)); + reg_node.m_node.set_attr (STATE_NODE_PREFIX, + "expected-deallocators", + pp_formatted_text (&pp)); } if (alloc_state->m_deallocator) - reg_node.set_property (state_node_properties::deallocator, - alloc_state->m_deallocator->m_name); + reg_node.m_node.set_attr (STATE_NODE_PREFIX, + "deallocator", + alloc_state->m_deallocator->m_name); } } diff --git a/gcc/configure b/gcc/configure index a742ad7e64c..38d8cd919cb 100755 --- a/gcc/configure +++ b/gcc/configure @@ -36868,7 +36868,7 @@ $as_echo "$as_me: executing $ac_file commands" >&6;} "depdir":C) $SHELL $ac_aux_dir/mkinstalldirs $DEPDIR ;; "gccdepdir":C) ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs build/$DEPDIR - for lang in $subdirs c-family common analyzer custom-sarif-properties diagnostics text-art rtl-ssa sym-exec + for lang in $subdirs c-family common analyzer diagnostics text-art rtl-ssa sym-exec do ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs $lang/$DEPDIR done ;; diff --git a/gcc/configure.ac b/gcc/configure.ac index 253d3ff28e9..19975fa5be5 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -1368,7 +1368,7 @@ AC_CHECK_HEADERS(ext/hash_map) ZW_CREATE_DEPDIR AC_CONFIG_COMMANDS([gccdepdir],[ ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs build/$DEPDIR - for lang in $subdirs c-family common analyzer custom-sarif-properties diagnostics text-art rtl-ssa sym-exec + for lang in $subdirs c-family common analyzer diagnostics text-art rtl-ssa sym-exec do ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs $lang/$DEPDIR done], [subdirs="$subdirs" ac_aux_dir=$ac_aux_dir DEPDIR=$DEPDIR]) diff --git a/gcc/custom-sarif-properties/digraphs.cc b/gcc/custom-sarif-properties/digraphs.cc deleted file mode 100644 index 30ca2b6cdd0..00000000000 --- a/gcc/custom-sarif-properties/digraphs.cc +++ /dev/null @@ -1,28 +0,0 @@ -/* Extra properties for digraphs in SARIF property bags. - Copyright (C) 2025 Free Software Foundation, Inc. - Contributed by David Malcolm . - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "json.h" -#include "custom-sarif-properties/digraphs.h" - -const json::string_property custom_sarif_properties::digraphs::digraph::kind - ("gcc/digraphs/graph/kind"); diff --git a/gcc/custom-sarif-properties/digraphs.h b/gcc/custom-sarif-properties/digraphs.h deleted file mode 100644 index 93817ed97bd..00000000000 --- a/gcc/custom-sarif-properties/digraphs.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Extra properties for digraphs in SARIF property bags. - Copyright (C) 2025 Free Software Foundation, Inc. - Contributed by David Malcolm . - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -. */ - -#ifndef GCC_CUSTOM_SARIF_PROPERTIES_DIGRAPHS_H -#define GCC_CUSTOM_SARIF_PROPERTIES_DIGRAPHS_H - -/* SARIF property names relating to digraphs. */ - -namespace custom_sarif_properties { - namespace digraphs { - namespace digraph { - /* A hint about the kind of graph we have, - and thus what kinds of nodes and edges to expect. */ - extern const json::string_property kind; - // string; values: "cfg" - } - } -} - -#endif /* ! GCC_CUSTOM_SARIF_PROPERTIES_DIGRAPHS_H */ diff --git a/gcc/custom-sarif-properties/state-graphs.cc b/gcc/custom-sarif-properties/state-graphs.cc deleted file mode 100644 index 3e0e58a4216..00000000000 --- a/gcc/custom-sarif-properties/state-graphs.cc +++ /dev/null @@ -1,157 +0,0 @@ -/* Properties for capturing state graphs in SARIF property bags. - Copyright (C) 2025 Free Software Foundation, Inc. - Contributed by David Malcolm . - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "json.h" -#include "custom-sarif-properties/state-graphs.h" - -/* graph. */ -namespace graph = custom_sarif_properties::state_graphs::graph; -#define STATE_GRAPH_PREFIX "gcc/diagnostic_state_graph/" -const char *const graph::prefix = STATE_GRAPH_PREFIX; -#undef STATE_GRAPH_PREFIX - -/* node. */ -namespace node = custom_sarif_properties::state_graphs::node; -#define STATE_NODE_PREFIX "gcc/diagnostic_state_node/" - -const json::enum_property node::kind - (STATE_NODE_PREFIX "kind"); - -const json::string_property node::function (STATE_NODE_PREFIX "function"); - -const json::string_property node::dynamic_extents - (STATE_NODE_PREFIX "dynamic-extents"); - -const json::string_property node::name (STATE_NODE_PREFIX "name"); -const json::string_property node::type (STATE_NODE_PREFIX "type"); -const json::json_property node::value (STATE_NODE_PREFIX "value"); -const json::string_property node::value_str (STATE_NODE_PREFIX "value_str"); - -const json::string_property node::index (STATE_NODE_PREFIX "index"); - -const json::string_property node::bits (STATE_NODE_PREFIX "bits"); - -const json::string_property node::num_bits (STATE_NODE_PREFIX "num_bits"); - -const json::string_property node::deallocator (STATE_NODE_PREFIX "deallocator"); - -const json::string_property node::expected_deallocators - (STATE_NODE_PREFIX "expected-deallocators"); - -const json::enum_property node::dynalloc_state - (STATE_NODE_PREFIX "dynalloc-state"); - -#undef STATE_NODE_PREFIX - - -/* edge. */ -namespace edge_props = custom_sarif_properties::state_graphs::edge; -#define STATE_EDGE_PREFIX "gcc/diagnostic_state_edge/" -extern const char *const edge_props::prefix = STATE_EDGE_PREFIX; -#undef STATE_EDGE_PREFIX - -// Traits for enum node:kind - -template<> -enum node::kind -json::enum_traits::get_unknown_value () -{ - return node::kind::other; -} - -static const char * const node_kind_strs[] = { - "globals", - "code", - "function", - "stack", - "stack-frame", - "heap", - "thread-local", - "dynalloc-buffer", - "variable", - "field", - "padding", - "element", - "other", -}; - -template<> -bool -json::enum_traits:: -maybe_get_value_from_string (const char *str, - enum_t &out) -{ - for (size_t i = 0; i < ARRAY_SIZE (node_kind_strs); ++i) - if (!strcmp (node_kind_strs[i], str)) - { - out = static_cast (i); - return true; - } - return false; -} - -template<> -const char * -json::enum_traits::get_string_for_value (enum_t value) -{ - return node_kind_strs[static_cast (value)]; -} - -// Traits for enum node:dynalloc_state - -template<> -enum node::dynalloc_state -json::enum_traits::get_unknown_value () -{ - return node::dynalloc_state::unknown; -} - -static const char * const dynalloc_state_strs[] = { - "unknown", - "nonnull", - "unchecked", - "freed" -}; - -template<> -bool -json::enum_traits:: -maybe_get_value_from_string (const char *str, - enum_t &out) -{ - for (size_t i = 0; i < ARRAY_SIZE (dynalloc_state_strs); ++i) - if (!strcmp (dynalloc_state_strs[i], str)) - { - out = static_cast (i); - return true; - } - return false; -} - -template<> -const char * -json::enum_traits:: -get_string_for_value (enum_t value) -{ - return dynalloc_state_strs[static_cast (value)]; -} diff --git a/gcc/custom-sarif-properties/state-graphs.h b/gcc/custom-sarif-properties/state-graphs.h deleted file mode 100644 index 6ae9ad89135..00000000000 --- a/gcc/custom-sarif-properties/state-graphs.h +++ /dev/null @@ -1,97 +0,0 @@ -/* Properties for capturing state graphs in SARIF property bags. - Copyright (C) 2025 Free Software Foundation, Inc. - Contributed by David Malcolm . - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -. */ - -#include "json.h" - -#ifndef GCC_DIAGNOSTICS_SARIF_PROPERTIES_STATE_GRAPHS_H -#define GCC_DIAGNOSTICS_SARIF_PROPERTIES_STATE_GRAPHS_H - -/* SARIF property names relating to GCC's CFGs. */ - -namespace custom_sarif_properties { - namespace state_graphs { - namespace graph { - extern const char *const prefix; - } - namespace node { - - enum class kind - { - // Memory regions - globals, - code, - function, // code within a particular function - stack, - stack_frame, - heap_, - thread_local_, - - /* Dynamically-allocated buffer, - on heap or stack (depending on parent). */ - dynalloc_buffer, - - variable, - - field, // field within a struct or union - padding, // padding bits in a struct or union - element, // element within an array - - other // anything else - }; - - enum class dynalloc_state - { - unknown, - nonnull, - unchecked, - freed - }; - - extern const json::enum_property kind; - - extern const json::string_property function; - extern const json::string_property dynamic_extents; - extern const json::string_property name; - extern const json::string_property type; - /* The value of a memory region, expressed as a json::value. */ - extern const json::json_property value; - /* The value of a memory region, expressed as a string. */ - extern const json::string_property value_str; - - /* For element nodes, the index within the array. */ - extern const json::string_property index; - - /* The range of bits or bytes within the base region. */ - extern const json::string_property bits; - - /* The size of a padding region. */ - extern const json::string_property num_bits; - - extern const json::string_property deallocator; - extern const json::string_property expected_deallocators; - extern const json::enum_property dynalloc_state; - } - namespace edge { - extern const char *const prefix; - } - } -} - -#endif /* ! GCC_DIAGNOSTICS_SARIF_PROPERTIES_STATE_GRAPHS_H */ diff --git a/gcc/diagnostics/diagnostics-selftests.cc b/gcc/diagnostics/diagnostics-selftests.cc index 757655bb172..94a212a6c93 100644 --- a/gcc/diagnostics/diagnostics-selftests.cc +++ b/gcc/diagnostics/diagnostics-selftests.cc @@ -46,6 +46,7 @@ run_diagnostics_selftests () sarif_sink_cc_tests (); digraphs_cc_tests (); output_spec_cc_tests (); + state_graphs_cc_tests (); lazy_paths_cc_tests (); paths_output_cc_tests (); changes_cc_tests (); diff --git a/gcc/diagnostics/diagnostics-selftests.h b/gcc/diagnostics/diagnostics-selftests.h index 5a68a049d3e..994ebad5280 100644 --- a/gcc/diagnostics/diagnostics-selftests.h +++ b/gcc/diagnostics/diagnostics-selftests.h @@ -44,6 +44,7 @@ extern void paths_output_cc_tests (); extern void sarif_sink_cc_tests (); extern void selftest_logical_locations_cc_tests (); extern void source_printing_cc_tests (); +extern void state_graphs_cc_tests (); } /* end of namespace diagnostics::selftest. */ diff --git a/gcc/diagnostics/digraphs.cc b/gcc/diagnostics/digraphs.cc index 60d3e8ccfc7..4a2ea4fca3c 100644 --- a/gcc/diagnostics/digraphs.cc +++ b/gcc/diagnostics/digraphs.cc @@ -30,15 +30,13 @@ along with GCC; see the file COPYING3. If not see #include "graphviz.h" #include "diagnostics/digraphs.h" #include "diagnostics/sarif-sink.h" -#include "custom-sarif-properties/digraphs.h" -using digraph_object = diagnostics::digraphs::object; +#include "selftest.h" + using digraph = diagnostics::digraphs::digraph; using digraph_node = diagnostics::digraphs::node; using digraph_edge = diagnostics::digraphs::edge; -namespace properties = custom_sarif_properties::digraphs; - namespace { class conversion_to_dot @@ -173,145 +171,66 @@ conversion_to_dot::has_edges_p (const digraph_node &input_node) // class object -/* String properties. */ - const char * -digraph_object::get_property (const json::string_property &property) const +diagnostics::digraphs::object:: +get_attr (const char *key_prefix, const char *key) const { if (!m_property_bag) return nullptr; - if (json::value *jv = m_property_bag->get (property.m_key.get ())) + std::string prefixed_key = std::string (key_prefix) + key; + if (json::value *jv = m_property_bag->get (prefixed_key.c_str ())) if (json::string *jstr = jv->dyn_cast_string ()) return jstr->get_string (); return nullptr; } void -digraph_object::set_property (const json::string_property &property, - const char *utf8_value) -{ - auto &bag = ensure_property_bag (); - bag.set_string (property.m_key.get (), utf8_value); -} - -/* Integer properties. */ - -bool -digraph_object::maybe_get_property (const json::integer_property &property, - long &out_value) const -{ - if (!m_property_bag) - return false; - if (json::value *jv = m_property_bag->get (property.m_key.get ())) - if (json::integer_number *jnum = jv->dyn_cast_integer_number ()) - { - out_value = jnum->get (); - return true; - } - return false; -} - -void -digraph_object::set_property (const json::integer_property &property, long value) -{ - auto &bag = ensure_property_bag (); - bag.set_integer (property.m_key.get (), value); -} - -/* Bool properties. */ -void -digraph_object::set_property (const json::bool_property &property, bool value) -{ - auto &bag = ensure_property_bag (); - bag.set_bool (property.m_key.get (), value); -} - -tristate -digraph_object:: -get_property_as_tristate (const json::bool_property &property) const -{ - if (m_property_bag) - { - if (json::value *jv = m_property_bag->get (property.m_key.get ())) - switch (jv->get_kind ()) - { - default: - break; - case json::JSON_TRUE: - return tristate (true); - case json::JSON_FALSE: - return tristate (false); - } - } - return tristate::unknown (); -} - -/* Array-of-string properties. */ -json::array * -digraph_object::get_property (const json::array_of_string_property &property) const +diagnostics::digraphs::object:: +set_attr (const char *key_prefix, const char *key, const char *value) { - if (m_property_bag) - if (json::value *jv = m_property_bag->get (property.m_key.get ())) - if (json::array *arr = jv->dyn_cast_array ()) - return arr; - return nullptr; -} - -/* json::value properties. */ -const json::value * -digraph_object::get_property (const json::json_property &property) const -{ - if (m_property_bag) - return m_property_bag->get (property.m_key.get ()); - return nullptr; + set_json_attr (key_prefix, key, std::make_unique (value)); } void -digraph_object::set_property (const json::json_property &property, - std::unique_ptr value) -{ - auto &bag = ensure_property_bag (); - bag.set (property.m_key.get (), std::move (value)); -} - -json::object & -digraph_object::ensure_property_bag () +diagnostics::digraphs::object:: +set_json_attr (const char *key_prefix, const char *key, std::unique_ptr value) { + std::string prefixed_key = std::string (key_prefix) + key; if (!m_property_bag) - m_property_bag = std::make_unique ( ); - return *m_property_bag; + m_property_bag = std::make_unique (); + m_property_bag->set (prefixed_key.c_str (), std::move (value)); } // class digraph DEBUG_FUNCTION void -digraph::dump () const +diagnostics::digraphs::digraph::dump () const { make_json_sarif_graph ()->dump (); } std::unique_ptr -digraph::make_json_sarif_graph () const +diagnostics::digraphs::digraph::make_json_sarif_graph () const { return make_sarif_graph (*this, nullptr, nullptr); } std::unique_ptr -digraph::make_dot_graph () const +diagnostics::digraphs::digraph::make_dot_graph () const { - conversion_to_dot converter; - return converter.make_dot_graph_from_diagnostic_graph (*this); + conversion_to_dot to_dot; + return to_dot.make_dot_graph_from_diagnostic_graph (*this); } -std::unique_ptr -digraph::clone () const +std::unique_ptr +diagnostics::digraphs::digraph::clone () const { auto result = std::make_unique (); if (get_property_bag ()) result->set_property_bag (get_property_bag ()->clone_as_object ()); - std::map node_mapping; + std::map node_mapping; for (auto &iter : m_nodes) result->add_node (iter->clone (*result, node_mapping)); @@ -322,10 +241,10 @@ digraph::clone () const } void -digraph::add_edge (const char *id, - node &src_node, - node &dst_node, - const char *label) +diagnostics::digraphs::digraph::add_edge (const char *id, + node &src_node, + node &dst_node, + const char *label) { auto e = std::make_unique (*this, id, @@ -344,7 +263,7 @@ digraph::add_edge (const char *id, to edges by id (SARIF 2.1.0's §3.43.2 edgeId property). */ std::string -digraph::make_edge_id (const char *edge_id) +diagnostics::digraphs::digraph::make_edge_id (const char *edge_id) { /* If we have an id, use it. */ if (edge_id) @@ -365,38 +284,27 @@ digraph::make_edge_id (const char *edge_id) } } -const char * -digraph::get_graph_kind () const -{ - return get_property (properties::digraph::kind); -} - -void -digraph::set_graph_kind (const char *kind) -{ - set_property (properties::digraph::kind, kind); -} - // class node DEBUG_FUNCTION void -digraph_node::dump () const +diagnostics::digraphs::node::dump () const { to_json_sarif_node ()->dump (); } std::unique_ptr -digraph_node::to_json_sarif_node () const +diagnostics::digraphs::node::to_json_sarif_node () const { return make_sarif_node (*this, nullptr, nullptr); } -std::unique_ptr -digraph_node::clone (digraph &new_graph, - std::map &node_mapping) const +std::unique_ptr +diagnostics::digraphs::node::clone (digraph &new_graph, + std::map &node_mapping) const { auto result - = std::make_unique (new_graph, get_id ()); + = std::make_unique (new_graph, + get_id ()); node_mapping.insert ({const_cast (this), result.get ()}); result->set_logical_loc (m_logical_loc); @@ -445,9 +353,6 @@ diagnostics::digraphs::edge::to_json_sarif_edge () const #if CHECKING_P -#include "selftest.h" -#include "custom-sarif-properties/state-graphs.h" - namespace diagnostics { namespace selftest { @@ -486,17 +391,16 @@ test_simple_graph () #define KEY_PREFIX "/placeholder/" auto g = std::make_unique (); g->set_description ("test graph"); - g->set_property (json::string_property (KEY_PREFIX, "date"), "1066"); + g->set_attr (KEY_PREFIX, "date", "1066"); auto a = std::make_unique (*g, "a"); auto b = std::make_unique (*g, "b"); - b->set_property (json::string_property (KEY_PREFIX, "color"), "red"); + b->set_attr (KEY_PREFIX, "color", "red"); auto c = std::make_unique (*g, "c"); c->set_label ("I am a node label"); auto e = std::make_unique (*g, nullptr, *a, *c); - e->set_property (json::string_property (KEY_PREFIX, "status"), - "copacetic"); + e->set_attr (KEY_PREFIX, "status", "copacetic"); e->set_label ("I am an edge label"); g->add_edge (std::move (e)); @@ -545,34 +449,6 @@ test_simple_graph () } } -static void -test_property_objects () -{ - namespace state_node_properties = custom_sarif_properties::state_graphs::node; - - digraph g; - digraph_node node (g, "a"); - - ASSERT_EQ (node.get_property (state_node_properties::kind), - state_node_properties::kind::other); - node.set_property (state_node_properties::kind, - state_node_properties::kind::stack); - ASSERT_EQ (node.get_property (state_node_properties::kind), - state_node_properties::kind::stack); - - ASSERT_EQ (node.get_property (state_node_properties::dynalloc_state), - state_node_properties::dynalloc_state::unknown); - node.set_property (state_node_properties::dynalloc_state, - state_node_properties::dynalloc_state::freed); - ASSERT_EQ (node.get_property (state_node_properties::dynalloc_state), - state_node_properties::dynalloc_state::freed); - - ASSERT_EQ (node.get_property (state_node_properties::type), nullptr); - node.set_property (state_node_properties::type, "const char *"); - ASSERT_STREQ (node.get_property (state_node_properties::type), - "const char *"); -} - /* Run all of the selftests within this file. */ void @@ -580,7 +456,6 @@ digraphs_cc_tests () { test_empty_graph (); test_simple_graph (); - test_property_objects (); } } // namespace diagnostics::selftest diff --git a/gcc/diagnostics/digraphs.h b/gcc/diagnostics/digraphs.h index 485a18917ca..7193ee48c3f 100644 --- a/gcc/diagnostics/digraphs.h +++ b/gcc/diagnostics/digraphs.h @@ -22,7 +22,6 @@ along with GCC; see the file COPYING3. If not see #define GCC_DIAGNOSTICS_DIGRAPHS_H #include "json.h" -#include "tristate.h" #include "diagnostics/logical-locations.h" class graphviz_out; @@ -56,57 +55,23 @@ class edge; class object { public: - /* String properties. */ - const char *get_property (const json::string_property &property) const; - void set_property (const json::string_property &property, - const char *utf8_value); - - /* Integer properties. */ - bool maybe_get_property (const json::integer_property &property, long &out) const; - void set_property (const json::integer_property &property, long value); - - /* Bool properties. */ - tristate - get_property_as_tristate (const json::bool_property &property) const; - void set_property (const json::bool_property &property, bool value); - - /* Array-of-string properties. */ - json::array * - get_property (const json::array_of_string_property &property) const; - - /* enum properties. */ - template - EnumType - get_property (const json::enum_property &property) const - { - if (m_property_bag) - { - EnumType result; - if (m_property_bag->maybe_get_enum (property, result)) - return result; - } - return json::enum_traits::get_unknown_value (); - } - template + const char * + get_attr (const char *key_prefix, + const char *key) const; + void - set_property (const json::enum_property &property, - EnumType value) - { - auto &bag = ensure_property_bag (); - bag.set_enum (property, value); - } + set_attr (const char *key_prefix, + const char *key, + const char *value); - /* json::value properties. */ - const json::value *get_property (const json::json_property &property) const; - void set_property (const json::json_property &property, - std::unique_ptr value); + void + set_json_attr (const char *key_prefix, + const char *key, + std::unique_ptr value); json::object * get_property_bag () const { return m_property_bag.get (); } - json::object & - ensure_property_bag (); - void set_property_bag (std::unique_ptr property_bag) { @@ -223,9 +188,6 @@ class digraph : public object std::unique_ptr clone () const; - const char *get_graph_kind () const; - void set_graph_kind (const char *); - private: void add_node_id (std::string node_id, node &new_node) @@ -338,7 +300,7 @@ class node : public object clone (digraph &new_graph, std::map &node_mapping) const; -private: + private: std::string m_id; std::unique_ptr m_label; std::vector> m_children; diff --git a/gcc/diagnostics/html-sink.cc b/gcc/diagnostics/html-sink.cc index 99d3b9d5dab..d3fb107e614 100644 --- a/gcc/diagnostics/html-sink.cc +++ b/gcc/diagnostics/html-sink.cc @@ -57,8 +57,8 @@ html_generation_options::html_generation_options () : m_css (true), m_javascript (true), m_show_state_diagrams (false), - m_show_graph_sarif (false), - m_show_graph_dot_src (false) + m_show_state_diagrams_sarif (false), + m_show_state_diagrams_dot_src (false) { } @@ -68,8 +68,8 @@ html_generation_options::dump (FILE *outfile, int indent) const DIAGNOSTICS_DUMPING_EMIT_BOOL_FIELD (m_css); DIAGNOSTICS_DUMPING_EMIT_BOOL_FIELD (m_javascript); DIAGNOSTICS_DUMPING_EMIT_BOOL_FIELD (m_show_state_diagrams); - DIAGNOSTICS_DUMPING_EMIT_BOOL_FIELD (m_show_graph_sarif); - DIAGNOSTICS_DUMPING_EMIT_BOOL_FIELD (m_show_graph_dot_src); + DIAGNOSTICS_DUMPING_EMIT_BOOL_FIELD (m_show_state_diagrams_sarif); + DIAGNOSTICS_DUMPING_EMIT_BOOL_FIELD (m_show_state_diagrams_dot_src); } class html_builder; @@ -640,7 +640,7 @@ html_builder::maybe_make_state_diagram (const paths::event &event) the debug version. */ auto state_graph = event.maybe_make_diagnostic_state_graph - (m_html_gen_opts.m_show_graph_sarif); + (m_html_gen_opts.m_show_state_diagrams_sarif); if (!state_graph) return nullptr; @@ -652,7 +652,7 @@ html_builder::maybe_make_state_diagram (const paths::event &event) auto wrapper = std::make_unique ("div", false); xml::printer xp (*wrapper); - if (m_html_gen_opts.m_show_graph_sarif) + if (m_html_gen_opts.m_show_state_diagrams_sarif) { // For debugging, show the SARIF src inline: pretty_printer pp; @@ -660,7 +660,7 @@ html_builder::maybe_make_state_diagram (const paths::event &event) print_pre_source (xp, pp_formatted_text (&pp)); } - if (m_html_gen_opts.m_show_graph_dot_src) + if (m_html_gen_opts.m_show_state_diagrams_dot_src) { // For debugging, show the dot src inline: pretty_printer pp; @@ -1278,41 +1278,21 @@ void html_builder::add_graph (const digraphs::digraph &dg, xml::element &parent_element) { - auto div = std::make_unique ("div", false); - div->set_attr ("class", "gcc-directed-graph"); - xml::printer xp (*div); - - if (m_html_gen_opts.m_show_graph_sarif) - { - // For debugging, show the SARIF src inline: - pretty_printer pp; - dg.make_json_sarif_graph ()->print (&pp, true); - print_pre_source (xp, pp_formatted_text (&pp)); - } - if (auto dot_graph = dg.make_dot_graph ()) - { - if (m_html_gen_opts.m_show_graph_dot_src) - { - // For debugging, show the dot src inline: - pretty_printer pp; - dot::writer w (pp); - dot_graph->print (w); - print_pre_source (xp, pp_formatted_text (&pp)); - } - - if (auto svg_element = dot::make_svg_from_graph (*dot_graph)) - { - if (const char *description = dg.get_description ()) - { - xp.push_tag ("h2", true); - xp.add_text (description); - xp.pop_tag ("h2"); - } - xp.append (std::move (svg_element)); - parent_element.add_child (std::move (div)); - } - } + if (auto svg_element = dot::make_svg_from_graph (*dot_graph)) + { + auto div = std::make_unique ("div", false); + div->set_attr ("class", "gcc-directed-graph"); + xml::printer xp (*div); + if (const char *description = dg.get_description ()) + { + xp.push_tag ("h2", true); + xp.add_text (description); + xp.pop_tag ("h2"); + } + xp.append (std::move (svg_element)); + parent_element.add_child (std::move (div)); + } } void diff --git a/gcc/diagnostics/html-sink.h b/gcc/diagnostics/html-sink.h index ad68e6fa3a6..d25ceea4b83 100644 --- a/gcc/diagnostics/html-sink.h +++ b/gcc/diagnostics/html-sink.h @@ -40,12 +40,11 @@ struct html_generation_options // If true, attempt to show state diagrams at events bool m_show_state_diagrams; - /* If true, show the SARIF form of the state with such diagrams, - and of other graphs. */ - bool m_show_graph_sarif; + // If true, show the SARIF form of the state with such diagrams + bool m_show_state_diagrams_sarif; - // If true, show the .dot source used for such graphs - bool m_show_graph_dot_src; + // If true, show the .dot source used for the diagram + bool m_show_state_diagrams_dot_src; }; extern diagnostics::output_file diff --git a/gcc/diagnostics/output-spec.cc b/gcc/diagnostics/output-spec.cc index f7cce0acce8..dfde7f0bdf3 100644 --- a/gcc/diagnostics/output-spec.cc +++ b/gcc/diagnostics/output-spec.cc @@ -650,12 +650,12 @@ html_scheme_handler::maybe_handle_kv (const context &ctxt, if (key == "show-state-diagrams") return parse_bool_value (ctxt, key, value, m_html_gen_opts.m_show_state_diagrams); - if (key == "show-graph-dot-src") + if (key == "show-state-diagrams-dot-src") return parse_bool_value (ctxt, key, value, - m_html_gen_opts.m_show_graph_dot_src); - if (key == "show-graph-sarif") + m_html_gen_opts.m_show_state_diagrams_dot_src); + if (key == "show-state-diagrams-sarif") return parse_bool_value (ctxt, key, value, - m_html_gen_opts.m_show_graph_sarif); + m_html_gen_opts.m_show_state_diagrams_sarif); return result::unrecognized; } @@ -666,8 +666,8 @@ html_scheme_handler::get_keys (auto_vec &out) const out.safe_push ("file"); out.safe_push ("javascript"); out.safe_push ("show-state-diagrams"); - out.safe_push ("show-graph-dot-src"); - out.safe_push ("show-graph-sarif"); + out.safe_push ("show-state-diagrams-dot-src"); + out.safe_push ("show-state-diagrams-sarif"); } } // namespace output_spec diff --git a/gcc/diagnostics/state-graphs-to-dot.cc b/gcc/diagnostics/state-graphs-to-dot.cc index 8a3ad246d1a..2d80e6b283f 100644 --- a/gcc/diagnostics/state-graphs-to-dot.cc +++ b/gcc/diagnostics/state-graphs-to-dot.cc @@ -27,7 +27,6 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" -#include "custom-sarif-properties/state-graphs.h" #include "diagnostics/state-graphs.h" #include "graphviz.h" #include "xml.h" @@ -37,8 +36,6 @@ along with GCC; see the file COPYING3. If not see using namespace diagnostics; using namespace diagnostics::state_graphs; -namespace state_node_properties = custom_sarif_properties::state_graphs::node; - static int get_depth (const digraphs::node &n) { @@ -50,28 +47,28 @@ get_depth (const digraphs::node &n) } static const char * -get_color_for_dynalloc_state (enum state_node_properties::dynalloc_state dynalloc_st) +get_color_for_dynalloc_state (enum node_dynalloc_state dynalloc_st) { switch (dynalloc_st) { default: gcc_unreachable (); break; - case state_node_properties::dynalloc_state::unknown: - case state_node_properties::dynalloc_state::nonnull: + case node_dynalloc_state::unknown: + case node_dynalloc_state::nonnull: return nullptr; - case state_node_properties::dynalloc_state::unchecked: + case node_dynalloc_state::unchecked: return "#ec7a08"; // pf-orange-400 - case state_node_properties::dynalloc_state::freed: + case node_dynalloc_state::freed: return "#cc0000"; // pf-red-100 } } static void set_color_for_dynalloc_state (dot::attr_list &attrs, - enum state_node_properties::dynalloc_state state) + enum node_dynalloc_state state) { if (const char *color = get_color_for_dynalloc_state (state)) attrs.add (dot::id ("color"), dot::id (color)); @@ -109,7 +106,7 @@ public: = std::make_unique (dot::id ("cluster_memory_regions")); for (size_t i = 0; i < input_state_graph.get_num_nodes (); ++i) on_input_state_node (*root_cluster, - input_state_graph.get_node (i)); + state_node_ref (input_state_graph.get_node (i))); add_stmt (std::move (root_cluster)); /* Now create dot edges for edges in input_stage_graph. */ @@ -129,8 +126,7 @@ public: auto e = std::make_unique (src_port_id->second, dst_port_id->second); set_color_for_dynalloc_state - (e->m_attrs, - dst_node.get_property (state_node_properties::dynalloc_state)); + (e->m_attrs, state_node_ref (dst_node).get_dynalloc_state ()); add_stmt (std::move (e)); } @@ -151,9 +147,9 @@ private: } dot::id - make_id (const diagnostics::digraphs::node &state_node, bool cluster) + make_id (state_node_ref state_node, bool cluster) { - std::string input_node_id = state_node.get_id (); + std::string input_node_id = state_node.m_node.get_id (); if (cluster) return std::string ("cluster_") + input_node_id; else @@ -161,44 +157,44 @@ private: } bool - starts_node_p (const diagnostics::digraphs::node &state_node) + starts_node_p (state_node_ref state_node) { - switch (state_node.get_property (state_node_properties::kind)) + switch (state_node.get_node_kind ()) { default: return false; - case state_node_properties::kind::stack: + case node_kind::stack: /* We want all frames in the stack in the same table, so they are grouped. */ - case state_node_properties::kind::dynalloc_buffer: - case state_node_properties::kind::variable: + case node_kind::dynalloc_buffer: + case node_kind::variable: return true; } } const char * - get_label_for_node (const diagnostics::digraphs::node &state_node) + get_label_for_node (state_node_ref state_node) { - switch (state_node.get_property (state_node_properties::kind)) + switch (state_node.get_node_kind ()) { default: return nullptr; - case state_node_properties::kind::globals: + case node_kind::globals: return _("Globals"); - case state_node_properties::kind::code: + case node_kind::code: return _("Code"); - case state_node_properties::kind::stack: + case node_kind::stack: return _("Stack"); - case state_node_properties::kind::heap_: + case node_kind::heap_: return _("Heap"); } } void on_input_state_node (dot::subgraph &parent_subgraph, - const diagnostics::digraphs::node &state_node) + state_node_ref state_node) { dot::id sg_id = make_id (state_node, true); @@ -211,7 +207,7 @@ private: xp.set_attr ("cellborder", "1"); xp.set_attr ("cellspacing", "0"); - const int max_depth = get_depth (state_node); + const int max_depth = get_depth (state_node.m_node); const int num_columns = max_depth + 2; dot::id id_of_dot_node = make_id (state_node, false); @@ -237,9 +233,9 @@ private: child_subgraph->add_attr (dot::id ("label"), dot::id (label)); // recurse: - for (size_t i = 0; i < state_node.get_num_children (); ++i) + for (size_t i = 0; i < state_node.m_node.get_num_children (); ++i) on_input_state_node (*child_subgraph, - state_node.get_child (i)); + state_node.m_node.get_child (i)); parent_subgraph.m_stmt_list.add_stmt (std::move (child_subgraph)); } } @@ -250,10 +246,10 @@ private: add_title_tr (const dot::id &id_of_dot_node, xml::printer &xp, int num_columns, - const diagnostics::digraphs::node &state_node, + state_node_ref state_node, std::string heading, enum style styl, - enum state_node_properties::dynalloc_state dynalloc_state) + enum node_dynalloc_state dynalloc_state) { xp.push_tag ("tr", true); xp.push_tag ("td", false); @@ -302,49 +298,48 @@ private: void on_node_in_table (const dot::id &id_of_dot_node, xml::printer &xp, - const diagnostics::digraphs::node &state_node, + state_node_ref state_node, int max_depth, int depth, int num_columns) { bool recurse = true; - auto input_node_kind = state_node.get_property (state_node_properties::kind); + auto input_node_kind = state_node.get_node_kind (); switch (input_node_kind) { - case state_node_properties::kind::padding: - case state_node_properties::kind::other: + case node_kind::padding: + case node_kind::other: return; - case state_node_properties::kind::stack: + case node_kind::stack: add_title_tr (id_of_dot_node, xp, num_columns, state_node, "Stack", style::h1, - state_node_properties::dynalloc_state::unknown); + node_dynalloc_state::unknown); break; - case state_node_properties::kind::stack_frame: + case node_kind::stack_frame: if (auto logical_loc = state_node.get_logical_loc ()) if (const char *function = m_logical_loc_mgr.get_short_name (logical_loc)) add_title_tr (id_of_dot_node, xp, num_columns, state_node, std::string ("Frame: ") + function, style::h2, - state_node_properties::dynalloc_state::unknown); + node_dynalloc_state::unknown); break; - case state_node_properties::kind::dynalloc_buffer: + case node_kind::dynalloc_buffer: { - enum state_node_properties::dynalloc_state dynalloc_st - = state_node.get_property (state_node_properties::dynalloc_state); - const char *extents - = state_node.get_property (state_node_properties::dynamic_extents); - const char *type = state_node.get_property (state_node_properties::type); + enum node_dynalloc_state dynalloc_st + = state_node.get_dynalloc_state (); + const char *extents = state_node.get_dynamic_extents (); + const char *type = state_node.get_type (); pretty_printer pp; switch (dynalloc_st) { default: gcc_unreachable (); - case state_node_properties::dynalloc_state::unknown: - case state_node_properties::dynalloc_state::nonnull: + case node_dynalloc_state::unknown: + case node_dynalloc_state::nonnull: if (type) { if (extents) @@ -361,7 +356,7 @@ private: } break; - case state_node_properties::dynalloc_state::unchecked: + case node_dynalloc_state::unchecked: if (type) { if (extents) @@ -376,7 +371,7 @@ private: } break; - case state_node_properties::dynalloc_state::freed: + case node_dynalloc_state::freed: // TODO: show deallocator // TODO: show deallocation event pp_printf (&pp, "Freed buffer"); @@ -409,10 +404,9 @@ private: { default: break; - case state_node_properties::kind::variable: + case node_kind::variable: { - const char *name - = state_node.get_property (state_node_properties::name); + const char *name = state_node.get_name (); gcc_assert (name); xp.push_tag ("td", false); maybe_add_dst_port (id_of_dot_node, xp, state_node); @@ -422,10 +416,9 @@ private: xp.pop_tag ("td"); } break; - case state_node_properties::kind::element: + case node_kind::element: { - const char *index - = state_node.get_property (state_node_properties::index); + const char *index = state_node.get_index (); gcc_assert (index); xp.push_tag ("td", false); maybe_add_dst_port (id_of_dot_node, xp, state_node); @@ -437,10 +430,9 @@ private: xp.pop_tag ("td"); } break; - case state_node_properties::kind::field: + case node_kind::field: { - const char *name - = state_node.get_property (state_node_properties::name); + const char *name = state_node.get_name (); gcc_assert (name); xp.push_tag ("td", false); maybe_add_dst_port (id_of_dot_node, xp, state_node); @@ -453,8 +445,7 @@ private: break; } - if (const char *type - = state_node.get_property (state_node_properties::type)) + if (const char *type = state_node.get_type ()) { xp.push_tag ("td", false); xp.set_attr ("align", "right"); @@ -464,8 +455,7 @@ private: xp.pop_tag ("td"); } - if (const char *value - = state_node.get_property (state_node_properties::value_str)) + if (const char *value = state_node.get_value ()) { xp.push_tag ("td", false); xp.set_attr ("align", "left"); @@ -476,16 +466,15 @@ private: xp.pop_tag ("td"); recurse = false; } - xp.pop_tag ("tr"); } break; } if (recurse) - for (size_t i = 0; i < state_node.get_num_children (); ++i) + for (size_t i = 0; i < state_node.m_node.get_num_children (); ++i) on_node_in_table (id_of_dot_node, xp, - state_node.get_child (i), + state_node.m_node.get_child (i), max_depth, depth + 1, num_columns); } @@ -508,9 +497,9 @@ private: void maybe_add_src_port (const dot::id &id_of_dot_node, xml::printer &xp, - const diagnostics::digraphs::node &state_node) + state_node_ref state_node) { - auto iter = m_src_nodes.find (&state_node); + auto iter = m_src_nodes.find (&state_node.m_node); if (iter == m_src_nodes.end ()) return; @@ -518,7 +507,7 @@ private: dot::node_id node_id (id_of_dot_node, dot::port (src_id, dot::compass_pt::e)); - m_src_node_to_port_id.insert ({&state_node, node_id}); + m_src_node_to_port_id.insert ({&state_node.m_node, node_id}); xp.set_attr ("port", src_id.m_str); } @@ -528,9 +517,9 @@ private: void maybe_add_dst_port (const dot::id &id_of_dot_node, xml::printer &xp, - const diagnostics::digraphs::node &state_node) + state_node_ref state_node) { - auto iter = m_dst_nodes.find (&state_node); + auto iter = m_dst_nodes.find (&state_node.m_node); if (iter == m_dst_nodes.end ()) return; @@ -538,7 +527,7 @@ private: dot::node_id node_id (id_of_dot_node, dot::port (dst_id/*, dot::compass_pt::w*/)); - m_dst_node_to_port_id.insert ({&state_node, node_id}); + m_dst_node_to_port_id.insert ({&state_node.m_node, node_id}); xp.set_attr ("port", dst_id.m_str); } @@ -546,11 +535,11 @@ private: const logical_locations::manager &m_logical_loc_mgr; /* All nodes involved in edges (and thus will need a port). */ - std::set m_src_nodes; - std::set m_dst_nodes; + std::set m_src_nodes; + std::set m_dst_nodes; - std::map m_src_node_to_port_id; - std::map m_dst_node_to_port_id; + std::map m_src_node_to_port_id; + std::map m_dst_node_to_port_id; }; std::unique_ptr diff --git a/gcc/diagnostics/state-graphs.cc b/gcc/diagnostics/state-graphs.cc new file mode 100644 index 00000000000..5941c413821 --- /dev/null +++ b/gcc/diagnostics/state-graphs.cc @@ -0,0 +1,156 @@ +/* Extensions to diagnostics::digraphs to support state graphs. + Copyright (C) 2025 Free Software Foundation, Inc. + Contributed by David Malcolm . + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#define INCLUDE_ALGORITHM +#define INCLUDE_MAP +#define INCLUDE_SET +#define INCLUDE_STRING +#define INCLUDE_VECTOR +#include "config.h" +#include "system.h" +#include "coretypes.h" + +#include "diagnostics/state-graphs.h" +#include "selftest.h" + +using namespace diagnostics::state_graphs; + +const char * const node_kind_strs[] = { + "globals", + "code", + "function", + "stack", + "stack-frame", + "heap", + "thread-local", + "dynalloc-buffer", + "variable", + "field", + "padding", + "element", + "other", +}; + +const char * +diagnostics::state_graphs::node_kind_to_str (enum node_kind k) +{ + return node_kind_strs[static_cast (k)]; +} + +// struct state_node_ref + +enum node_kind +state_node_ref::get_node_kind () const +{ + const char *value = get_attr ("kind"); + if (!value) + return node_kind::other; + + for (size_t i = 0; i < ARRAY_SIZE (node_kind_strs); ++i) + if (!strcmp (node_kind_strs[i], value)) + return static_cast (i); + + return node_kind::other; +} + +void +state_node_ref::set_node_kind (enum node_kind k) +{ + set_attr ("kind", node_kind_to_str (k)); +} + +const char * const dynalloc_state_strs[] = { + "unknown", + "nonnull", + "unchecked", + "freed" +}; + +enum node_dynalloc_state +state_node_ref::get_dynalloc_state () const +{ + const char *value = get_attr ("dynalloc-state"); + if (!value) + return node_dynalloc_state::unknown; + + for (size_t i = 0; i < ARRAY_SIZE (dynalloc_state_strs); ++i) + if (!strcmp (dynalloc_state_strs[i], value)) + return static_cast (i); + + return node_dynalloc_state::unknown; +} + +void +state_node_ref::set_dynalloc_state (enum node_dynalloc_state s) const +{ + set_attr ("dynalloc-state", + dynalloc_state_strs[static_cast (s)]); +} + +const char * +state_node_ref::get_dynamic_extents () const +{ + return m_node.get_attr (STATE_NODE_PREFIX, "dynamic-extents"); +} + +void +state_node_ref::set_json_attr (const char *key, + std::unique_ptr value) const +{ + m_node.set_json_attr (STATE_NODE_PREFIX, key, std::move (value)); +} + +#if CHECKING_P + +namespace diagnostics { +namespace selftest { + +static void +test_node_attrs () +{ + digraphs::digraph g; + digraphs::node n (g, "a"); + state_node_ref node_ref (n); + + ASSERT_EQ (node_ref.get_node_kind (), node_kind::other); + node_ref.set_node_kind (node_kind::stack); + ASSERT_EQ (node_ref.get_node_kind (), node_kind::stack); + + ASSERT_EQ (node_ref.get_dynalloc_state (), node_dynalloc_state::unknown); + node_ref.set_dynalloc_state (node_dynalloc_state::freed); + ASSERT_EQ (node_ref.get_dynalloc_state (), node_dynalloc_state::freed); + + ASSERT_EQ (node_ref.get_type (), nullptr); + node_ref.set_type ("const char *"); + ASSERT_STREQ (node_ref.get_type (), "const char *"); +} + +/* Run all of the selftests within this file. */ + +void +state_graphs_cc_tests () +{ + test_node_attrs (); +} + +} // namespace diagnostics::selftest +} // namespace diagnostics + +#endif /* CHECKING_P */ diff --git a/gcc/diagnostics/state-graphs.h b/gcc/diagnostics/state-graphs.h index 21aded03ff6..ad18f82b5b7 100644 --- a/gcc/diagnostics/state-graphs.h +++ b/gcc/diagnostics/state-graphs.h @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see #define GCC_DIAGNOSTICS_STATE_GRAPHS_H #include "diagnostics/digraphs.h" +#include "diagnostics/logical-locations.h" /* diagnostics::digraphs provides support for directed graphs. @@ -33,11 +34,118 @@ along with GCC; see the file COPYING3. If not see in these nodes to stash extra properties (e.g. what kind of memory region a node is e.g. stack vs heap). */ +class sarif_graph; namespace dot { class graph; } namespace diagnostics { namespace state_graphs { +enum class node_kind +{ + // Memory regions + globals, + code, + function, // code within a particular function + stack, + stack_frame, + heap_, + thread_local_, + + /* Dynamically-allocated buffer, + on heap or stack (depending on parent). */ + dynalloc_buffer, + + variable, + + field, // field within a struct or union + padding, // padding bits in a struct or union + element, // element within an array + + other // anything else +}; + +extern const char * +node_kind_to_str (enum node_kind); + +enum class node_dynalloc_state +{ + unknown, + nonnull, + unchecked, + freed +}; + +/* Prefixes to use in SARIF property bags. */ +#define STATE_GRAPH_PREFIX "gcc/diagnostic_state_graph/" +#define STATE_NODE_PREFIX "gcc/diagnostic_state_node/" +#define STATE_EDGE_PREFIX "gcc/diagnostic_state_edge/" + +/* A wrapper around a node that gets/sets attributes, using + the node's property bag for storage, so that the data roundtrips + through SARIF. */ + +struct state_node_ref +{ + state_node_ref (diagnostics::digraphs::node &node) + : m_node (node) + {} + + enum node_kind + get_node_kind () const; + void + set_node_kind (enum node_kind); + + // For node_kind::stack_frame, this will be the function + logical_locations::key + get_logical_loc () const + { + return m_node.get_logical_loc (); + } + + // For node_kind::dynalloc_buffer + enum node_dynalloc_state + get_dynalloc_state () const; + + void + set_dynalloc_state (enum node_dynalloc_state) const; + + const char * + get_dynamic_extents () const; + + const char * + get_name () const { return get_attr ("name"); } + void + set_name (const char *name) const { set_attr ("name", name); } + + const char * + get_type () const { return get_attr ("type"); } + void + set_type (const char *type) const { set_attr ("type", type); } + + const char * + get_value () const { return get_attr ("value"); } + + const char * + get_index () const { return get_attr ("index"); } + + const char * + get_attr (const char *key) const + { + return m_node.get_attr (STATE_NODE_PREFIX, key); + } + + void + set_attr (const char *key, const char *value) const + { + return m_node.set_attr (STATE_NODE_PREFIX, key, value); + } + + void + set_json_attr (const char *key, std::unique_ptr value) const; + + diagnostics::digraphs::node &m_node; +}; + extern std::unique_ptr make_dot_graph (const diagnostics::digraphs::digraph &state_graph, const logical_locations::manager &logical_loc_mgr); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 81a495b416f..492ca291432 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -6271,16 +6271,16 @@ These are visible by pressing ``j'' and ``k'' to single-step forward and backward through events. Enabling this option will slow down HTML generation. -@item show-graph-dot-src=@r{[}yes@r{|}no@r{]} +@item show-state-diagrams-dot-src=@r{[}yes@r{|}no@r{]} This is a debugging feature and defaults to @code{no}. -If @code{show-graph-dot-src=yes} +If @code{show-state-diagrams-dot-src=yes} then if @code{show-state-diagrams=yes}, the generated state diagrams will also show the .dot source input to GraphViz used for the diagram. -@item show-graph-sarif=@r{[}yes@r{|}no@r{]} +@item show-state-diagrams-sarif=@r{[}yes@r{|}no@r{]} This is a debugging feature and defaults to @code{no}. -If @code{show-graph-sarif=yes} +If @code{show-state-diagrams-sarif=yes} then if @code{show-state-diagrams=yes}, the generated state diagrams will also show a SARIF representation of the state. diff --git a/gcc/json.cc b/gcc/json.cc index 14ff76bd036..7153f087a00 100644 --- a/gcc/json.cc +++ b/gcc/json.cc @@ -394,31 +394,6 @@ object::set_bool (const char *key, bool v) set (key, new json::literal (v)); } -void -object::set_string (const string_property &property, const char *utf8_value) -{ - set_string (property.m_key.get (), utf8_value); -} - -void -object::set_integer (const integer_property &property, long value) -{ - set_integer (property.m_key.get (), value); -} - -void -object::set_bool (const bool_property &property, bool value) -{ - set_bool (property.m_key.get (), value); -} - -void -object::set_array_of_string (const array_of_string_property &property, - std::unique_ptr value) -{ - set (property.m_key.get (), std::move (value)); -} - /* Subroutine of json::compare for comparing a pairs of objects. */ int diff --git a/gcc/json.h b/gcc/json.h index c53715ecb2c..c706f2a4fe9 100644 --- a/gcc/json.h +++ b/gcc/json.h @@ -21,8 +21,6 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_JSON_H #define GCC_JSON_H -#include "label-text.h" - /* Implementation of JSON, a lightweight data-interchange format. See http://www.json.org/ @@ -118,41 +116,6 @@ struct token } // namespace json::pointer -/* Typesafe way to work with properties in JSON objects. */ - -template -struct property -{ - explicit property (const char *key) - : m_key (label_text::borrow (key)) - {} - - explicit property (const char *key_prefix, const char *key) - : m_key (label_text::take (concat (key_prefix, key, nullptr))) - {} - - label_text m_key; -}; - -using string_property = property; -using integer_property = property; -using bool_property = property; -using json_property = property; -using array_of_string_property = property; - -template -struct enum_traits -{ - typedef EnumType enum_t; - - static enum_t get_unknown_value (); - static bool maybe_get_value_from_string (const char *, enum_t &out); - static const char *get_string_for_value (enum_t value); -}; - -template -using enum_property = property>; - /* Base class of JSON value. */ class value @@ -167,8 +130,6 @@ class value void DEBUG_FUNCTION dump () const; virtual object *dyn_cast_object () { return nullptr; } - virtual array *dyn_cast_array () { return nullptr; } - virtual integer_number *dyn_cast_integer_number () { return nullptr; } virtual string *dyn_cast_string () { return nullptr; } static int compare (const json::value &val_a, const json::value &val_b); @@ -222,19 +183,6 @@ class object : public value /* Set to literal true/false. */ void set_bool (const char *key, bool v); - /* Typesafe access to properties by name (such as from a schema). */ - void set_string (const string_property &property, const char *utf8_value); - void set_integer (const integer_property &property, long value); - void set_bool (const bool_property &property, bool value); - void set_array_of_string (const array_of_string_property &property, - std::unique_ptr value); - template - bool maybe_get_enum (const enum_property &property, - EnumType &out) const; - template - void set_enum (const enum_property &property, - EnumType value); - static int compare (const json::object &obj_a, const json::object &obj_b); size_t get_num_keys () const { return m_keys.length (); } @@ -262,8 +210,6 @@ class array : public value void print (pretty_printer *pp, bool formatted) const final override; std::unique_ptr clone () const final override; - array *dyn_cast_array () final override { return this; } - void append (value *v); void append_string (const char *utf8_value); @@ -323,8 +269,6 @@ class integer_number : public value void print (pretty_printer *pp, bool formatted) const final override; std::unique_ptr clone () const final override; - integer_number *dyn_cast_integer_number () final override { return this; } - long get () const { return m_value; } private: @@ -373,32 +317,6 @@ class literal : public value enum kind m_kind; }; - -template -inline bool -object::maybe_get_enum (const enum_property &property, - EnumType &out) const -{ - if (value *jv = get (property.m_key.get ())) - if (string *jstr = jv->dyn_cast_string ()) - { - if (enum_traits::maybe_get_value_from_string - (jstr->get_string (), out)) - return true; - } - return false; -} - -template -inline void -object::set_enum (const enum_property &property, - EnumType value) -{ - const char *str - = json::enum_traits::get_string_for_value (value); - set_string (property.m_key.get (), str); -} - } // namespace json template <> diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_graphs.cc b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_graphs.cc index 8ba576ec81c..7398a290825 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_graphs.cc +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_graphs.cc @@ -210,8 +210,9 @@ report_diag_with_graphs (location_t loc) g->set_description (desc); auto a = std::make_unique (*g, "a"); auto b = std::make_unique (*g, "b"); - const json::string_property color ("/placeholder-prefix/color"); - b->set_property (color, "red"); +#define KEY_PREFIX "/placeholder-prefix/" + b->set_attr (KEY_PREFIX, "color", "red"); +#undef KEY_PREFIX auto c = std::make_unique (*g, "c"); c->set_label ("I am a node label"); -- 2.47.3