]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Revert: r16-4193 ("diagnostics: generalize state graph code to use json::property...
authorDavid Malcolm <dmalcolm@redhat.com>
Fri, 3 Oct 2025 15:04:53 +0000 (11:04 -0400)
committerDavid Malcolm <dmalcolm@redhat.com>
Fri, 3 Oct 2025 15:17:31 +0000 (11:17 -0400)
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 <dmalcolm@redhat.com>
26 files changed:
contrib/gcc.doxy
gcc/Makefile.in
gcc/analyzer/ana-state-to-diagnostic-state.cc
gcc/analyzer/ana-state-to-diagnostic-state.h
gcc/analyzer/checker-event.cc
gcc/analyzer/sm-malloc.cc
gcc/configure
gcc/configure.ac
gcc/custom-sarif-properties/digraphs.cc [deleted file]
gcc/custom-sarif-properties/digraphs.h [deleted file]
gcc/custom-sarif-properties/state-graphs.cc [deleted file]
gcc/custom-sarif-properties/state-graphs.h [deleted file]
gcc/diagnostics/diagnostics-selftests.cc
gcc/diagnostics/diagnostics-selftests.h
gcc/diagnostics/digraphs.cc
gcc/diagnostics/digraphs.h
gcc/diagnostics/html-sink.cc
gcc/diagnostics/html-sink.h
gcc/diagnostics/output-spec.cc
gcc/diagnostics/state-graphs-to-dot.cc
gcc/diagnostics/state-graphs.cc [new file with mode: 0644]
gcc/diagnostics/state-graphs.h
gcc/doc/invoke.texi
gcc/json.cc
gcc/json.h
gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_graphs.cc

index 56e3845d00d4a6ea2fad8a0e8d45a687e048836f..15952046f25658c2363698f1ee57c4c5d31ea48f 100644 (file)
@@ -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 
index 098bafbce537515720b16892994be2e13ed9fdeb..6a9d6204c8693353abdc7a721a63d747ecfe01da 100644 (file)
@@ -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 \
index 39acf26bdd50b0030623dab71da6c996b91c3aa2..996538c378529a75ad76e9406830c3803b6fe72f 100644 (file)
@@ -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 &reg)
 {
   auto existing = m_region_to_state_node_map.find (&reg);
   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[&reg] = &state_node;
-  return state_node;
+  auto ref = create_and_add_state_node (reg);
+  m_region_to_state_node_map[&reg] = &ref.m_node;
+  return ref;
 }
 
-diagnostics::digraphs::node &
+state_node_ref
 analyzer_state_graph::create_and_add_state_node (const region &reg)
 {
   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 &reg)
 
 std::unique_ptr<diagnostics::digraphs::node>
 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<diagnostics::digraphs::node> (*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<diagnostics::digraphs::node>
 analyzer_state_graph::
 make_memspace_state_node (const region &reg,
-                         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 &reg)
        const frame_region &frame_reg
          = static_cast<const frame_region &> (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 &reg)
          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<const decl_region &> (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 &reg)
     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<diagnostics::digraphs::node>
 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 &reg,
 
 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 &reg,
                                      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 (&reg,
                                            const_cast<tree> (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 &reg,
-                             diagnostics::digraphs::node &state_node)
+analyzer_state_graph::set_attr_for_dynamic_extents (const region &reg,
+                                                   state_node_ref node_ref)
 {
   const svalue *sval = m_state.m_region_model->get_dynamic_extents (&reg);
   if (sval)
@@ -658,16 +642,15 @@ set_attr_for_dynamic_extents (const region &reg,
        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 &reg,
-                                         const concrete_bindings_t &conc_bindings,
-                                         bool create_all)
+                                      const concrete_bindings_t &conc_bindings,
+                                      bool create_all)
 {
   if (create_all)
     return true;
index eec3d56b3011d5ecb31ebb44716cfb6ac30f2b72..3a5ccc1b4306b27984e0a0e8366134ab82e18a3f 100644 (file)
@@ -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 &reg);
 
 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 &reg);
 
   std::unique_ptr<diagnostics::digraphs::node>
-  make_state_node (enum state_node_properties::kind kind,
+  make_state_node (diagnostics::state_graphs::node_kind kind,
                   std::string id);
 
   std::unique_ptr<diagnostics::digraphs::node>
   make_memspace_state_node (const region &reg,
-                           enum state_node_properties::kind kind);
+                           enum diagnostics::state_graphs::node_kind kind);
 
   std::unique_ptr<diagnostics::digraphs::node>
   create_state_node (const region &reg);
@@ -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 &reg,
                                        const concrete_bindings_t &conc_bindings,
                                        bool create_all);
 
   void
   set_attr_for_dynamic_extents (const region &reg,
-                               diagnostics::digraphs::node &);
+                               diagnostics::state_graphs::state_node_ref);
 
   bool
   show_child_state_node_for_child_region_p (const region &reg,
@@ -99,8 +95,7 @@ private:
   const program_state &m_state;
   const extrinsic_state &m_ext_state;
   region_model_manager &m_mgr;
-  std::map<const region *,
-          diagnostics::digraphs::node *> m_region_to_state_node_map;
+  std::map<const region *, diagnostics::digraphs::node *> m_region_to_state_node_map;
   std::map<const region *, tree> m_types_for_untyped_regions;
   unsigned m_next_id;
   std::vector<pending_edge> m_pending_edges;
index 790ebc714380060d416aa015afe359a673b46770..4eac9450469f97b3fa2a6e4952c11fabcafab07c 100644 (file)
@@ -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;
index b25e2adf015e196ebd71e78db9693d253a1316e3..a6b14219068af249a41f24ed5a1b35d66bfa6f6f 100644 (file)
@@ -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 &reg_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);
     }
 }
 
index a742ad7e64cb9cf122032532f835992fde1ce606..38d8cd919cba81accca9cf86ad17f15d9a8a1dd5 100755 (executable)
@@ -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 ;;
index 253d3ff28e9be18c11e945bbcfaca1e0bd28784b..19975fa5be5b200b62f10a1ed7e02cca6dc7f76f 100644 (file)
@@ -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 (file)
index 30ca2b6..0000000
+++ /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 <dmalcolm@redhat.com>.
-
-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
-<http://www.gnu.org/licenses/>.  */
-
-#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 (file)
index 93817ed..0000000
+++ /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 <dmalcolm@redhat.com>.
-
-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
-<http://www.gnu.org/licenses/>.  */
-
-#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 (file)
index 3e0e58a..0000000
+++ /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 <dmalcolm@redhat.com>.
-
-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
-<http://www.gnu.org/licenses/>.  */
-
-#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<enum node::kind> 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<enum node::dynalloc_state> 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<enum node::kind>::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<enum node::kind>::
-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<enum_t> (i);
-       return true;
-      }
-  return false;
-}
-
-template<>
-const char *
-json::enum_traits<enum node::kind>::get_string_for_value (enum_t value)
-{
-  return node_kind_strs[static_cast<int> (value)];
-}
-
-// Traits for enum node:dynalloc_state
-
-template<>
-enum node::dynalloc_state
-json::enum_traits<enum node::dynalloc_state>::get_unknown_value ()
-{
-  return node::dynalloc_state::unknown;
-}
-
-static const char * const dynalloc_state_strs[] = {
-  "unknown",
-  "nonnull",
-  "unchecked",
-  "freed"
-};
-
-template<>
-bool
-json::enum_traits<enum node::dynalloc_state>::
-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<enum_t> (i);
-       return true;
-      }
-  return false;
-}
-
-template<>
-const char *
-json::enum_traits<enum node::dynalloc_state>::
-get_string_for_value (enum_t value)
-{
-  return dynalloc_state_strs[static_cast <size_t> (value)];
-}
diff --git a/gcc/custom-sarif-properties/state-graphs.h b/gcc/custom-sarif-properties/state-graphs.h
deleted file mode 100644 (file)
index 6ae9ad8..0000000
+++ /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 <dmalcolm@redhat.com>.
-
-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
-<http://www.gnu.org/licenses/>.  */
-
-#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<enum kind> 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<enum dynalloc_state> dynalloc_state;
-    }
-    namespace edge {
-      extern const char *const prefix;
-    }
-  }
-}
-
-#endif /* ! GCC_DIAGNOSTICS_SARIF_PROPERTIES_STATE_GRAPHS_H */
index 757655bb1728196629942eb21068410a25c4ea7b..94a212a6c93a376199d23748e9e1fd8f14afad28 100644 (file)
@@ -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 ();
index 5a68a049d3e98f0bcacbc497a06bd1bc53098470..994ebad5280499528b6a89a03e771afe3be91479 100644 (file)
@@ -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.  */
 
index 60d3e8ccfc7a4b8370061a753904d1024e27b429..4a2ea4fca3c7dd8e9fc9f01b633cc8141f6131aa 100644 (file)
@@ -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<json::string> (value));
 }
 
 void
-digraph_object::set_property (const json::json_property &property,
-                             std::unique_ptr<json::value> 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<json::value> value)
 {
+  std::string prefixed_key = std::string (key_prefix) + key;
   if (!m_property_bag)
-    m_property_bag = std::make_unique<sarif_property_bag> ( );
-  return *m_property_bag;
+    m_property_bag = std::make_unique<json::object> ();
+  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<json::object>
-digraph::make_json_sarif_graph () const
+diagnostics::digraphs::digraph::make_json_sarif_graph () const
 {
   return make_sarif_graph (*this, nullptr, nullptr);
 }
 
 std::unique_ptr<dot::graph>
-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>
-digraph::clone () const
+std::unique_ptr<diagnostics::digraphs::digraph>
+diagnostics::digraphs::digraph::clone () const
 {
   auto result = std::make_unique<diagnostics::digraphs::digraph> ();
 
   if (get_property_bag ())
     result->set_property_bag (get_property_bag ()->clone_as_object ());
 
-  std::map<digraph_node *, digraph_node *> node_mapping;
+  std::map<diagnostics::digraphs::node *, diagnostics::digraphs::node *> 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<digraph_edge> (*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<json::object>
-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>
-digraph_node::clone (digraph &new_graph,
-                    std::map<node *, node *> &node_mapping) const
+std::unique_ptr<diagnostics::digraphs::node>
+diagnostics::digraphs::node::clone (digraph &new_graph,
+                                   std::map<node *, node *> &node_mapping) const
 {
   auto result
-    = std::make_unique<digraph_node> (new_graph, get_id ());
+    = std::make_unique<diagnostics::digraphs::node> (new_graph,
+                                                    get_id ());
   node_mapping.insert ({const_cast <node *> (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<digraph> ();
   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<digraph_node> (*g, "a");
   auto b = std::make_unique<digraph_node> (*g, "b");
-  b->set_property (json::string_property (KEY_PREFIX, "color"), "red");
+  b->set_attr (KEY_PREFIX, "color", "red");
   auto c = std::make_unique<digraph_node> (*g, "c");
   c->set_label ("I am a node label");
 
   auto e = std::make_unique<digraph_edge> (*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
index 485a18917ca0af8a9de5a45c178b64c5f6977c8d..7193ee48c3fa71bd29436c285b659f5c3899855c 100644 (file)
@@ -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 <typename EnumType>
-  EnumType
-  get_property (const json::enum_property<EnumType> &property) const
-  {
-    if (m_property_bag)
-      {
-       EnumType result;
-       if (m_property_bag->maybe_get_enum<EnumType> (property, result))
-         return result;
-      }
-    return json::enum_traits<EnumType>::get_unknown_value ();
-  }
-  template <typename EnumType>
+  const char *
+  get_attr (const char *key_prefix,
+           const char *key) const;
+
   void
-  set_property (const json::enum_property<EnumType> &property,
-               EnumType value)
-  {
-    auto &bag = ensure_property_bag ();
-    bag.set_enum<EnumType> (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<json::value> value);
+  void
+  set_json_attr (const char *key_prefix,
+                const char *key,
+                std::unique_ptr<json::value> value);
 
   json::object *
   get_property_bag () const { return m_property_bag.get (); }
 
-  json::object &
-  ensure_property_bag ();
-
   void
   set_property_bag (std::unique_ptr<json::object> property_bag)
   {
@@ -223,9 +188,6 @@ class digraph : public object
 
   std::unique_ptr<digraph> 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 *, node *> &node_mapping) const;
 
-private:
+ private:
   std::string m_id;
   std::unique_ptr<std::string> m_label;
   std::vector<std::unique_ptr<node>> m_children;
index 99d3b9d5dab54f9adae65f2d0df2606627a26aa8..d3fb107e61454ca4a456b202f396ab9efa67dbf3 100644 (file)
@@ -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<xml::element> ("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<xml::element> ("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<xml::element> ("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
index ad68e6fa3a673d3d688e0be980fd071c6a3d42cf..d25ceea4b832410314ec5f2755a52670029a9cb3 100644 (file)
@@ -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
index f7cce0acce845e281d713b1a053f4d9d5a5f63fc..dfde7f0bdf3038b981018b16e195f226a7b872d9 100644 (file)
@@ -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<const char *> &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
index 8a3ad246d1aaae6e6b7c2ab15c30a970ec12d66a..2d80e6b283f6c3a3e722455256dc0066824e495c 100644 (file)
@@ -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::subgraph> (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<dot::edge_stmt> (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<const digraphs::node *> m_src_nodes;
-  std::set<const digraphs::node *> m_dst_nodes;
+  std::set<digraphs::node *> m_src_nodes;
+  std::set<digraphs::node *> m_dst_nodes;
 
-  std::map<const digraphs::node *, dot::node_id> m_src_node_to_port_id;
-  std::map<const digraphs::node *, dot::node_id> m_dst_node_to_port_id;
+  std::map<digraphs::node *, dot::node_id> m_src_node_to_port_id;
+  std::map<digraphs::node *, dot::node_id> m_dst_node_to_port_id;
 };
 
 std::unique_ptr<dot::graph>
diff --git a/gcc/diagnostics/state-graphs.cc b/gcc/diagnostics/state-graphs.cc
new file mode 100644 (file)
index 0000000..5941c41
--- /dev/null
@@ -0,0 +1,156 @@
+/* Extensions to diagnostics::digraphs to support state graphs.
+   Copyright (C) 2025 Free Software Foundation, Inc.
+   Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+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
+<http://www.gnu.org/licenses/>.  */
+
+#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<int> (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<enum node_kind> (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<enum node_dynalloc_state> (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 <size_t> (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<json::value> 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 */
index 21aded03ff6bc4349e6d4f4e81e842bc024aa163..ad18f82b5b73a43f78c6380e121752596282627c 100644 (file)
@@ -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<json::value> value) const;
+
+  diagnostics::digraphs::node &m_node;
+};
+
 extern std::unique_ptr<dot::graph>
 make_dot_graph (const diagnostics::digraphs::digraph &state_graph,
                const logical_locations::manager &logical_loc_mgr);
index 81a495b416f0b0f4c32a17f4bd280d2071cc21c9..492ca2914323f0a2d771322e47991acc6ae02727 100644 (file)
@@ -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.
 
index 14ff76bd03665b7c24fd6127e3fe8e0f4575d928..7153f087a0011c60c6a088ecee5860e9f60aaf8d 100644 (file)
@@ -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<json::array> value)
-{
-  set<array> (property.m_key.get (), std::move (value));
-}
-
 /* Subroutine of json::compare for comparing a pairs of objects.  */
 
 int
index c53715ecb2ca00997cedc7964a34814c6a8a86f0..c706f2a4fe9fa14c159b6eafdb745717b56fad60 100644 (file)
@@ -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 <typename Traits>
-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<string>;
-using integer_property = property<integer_number>;
-using bool_property = property<literal>;
-using json_property = property<value>;
-using array_of_string_property = property<array>;
-
-template <typename EnumType>
-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 <typename EnumType>
-using enum_property = property<enum_traits<EnumType>>;
-
 /* 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<json::array> value);
-  template <typename EnumType>
-  bool maybe_get_enum (const enum_property<EnumType> &property,
-                      EnumType &out) const;
-  template <typename EnumType>
-  void set_enum (const enum_property<EnumType> &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<value> 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<value> 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 <typename EnumType>
-inline bool
-object::maybe_get_enum (const enum_property<EnumType> &property,
-                       EnumType &out) const
-{
-  if (value *jv = get (property.m_key.get ()))
-    if (string *jstr = jv->dyn_cast_string ())
-      {
-       if (enum_traits<EnumType>::maybe_get_value_from_string
-           (jstr->get_string (), out))
-         return true;
-      }
-  return false;
-}
-
-template <typename EnumType>
-inline void
-object::set_enum (const enum_property<EnumType> &property,
-                 EnumType value)
-{
-  const char *str
-    = json::enum_traits<EnumType>::get_string_for_value (value);
-  set_string (property.m_key.get (), str);
-}
-
 } // namespace json
 
 template <>
index 8ba576ec81c4f5025545bc5815242873967299cc..7398a2908258451fca882369f23a2c48a66e2fc5 100644 (file)
@@ -210,8 +210,9 @@ report_diag_with_graphs (location_t loc)
       g->set_description (desc);
       auto a = std::make_unique<diagnostic_node> (*g, "a");
       auto b = std::make_unique<diagnostic_node> (*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<diagnostic_node> (*g, "c");
       c->set_label ("I am a node label");