aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/analyzer')
-rw-r--r--gcc/analyzer/ChangeLog38
-rw-r--r--gcc/analyzer/ana-state-to-diagnostic-state.cc659
-rw-r--r--gcc/analyzer/ana-state-to-diagnostic-state.h87
-rw-r--r--gcc/analyzer/checker-event.cc12
-rw-r--r--gcc/analyzer/checker-event.h7
-rw-r--r--gcc/analyzer/engine.cc4
-rw-r--r--gcc/analyzer/program-state.cc12
-rw-r--r--gcc/analyzer/program-state.h15
-rw-r--r--gcc/analyzer/sm-malloc.cc52
-rw-r--r--gcc/analyzer/sm.cc10
-rw-r--r--gcc/analyzer/sm.h12
11 files changed, 453 insertions, 455 deletions
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog
index d31cbbc..a34fa13 100644
--- a/gcc/analyzer/ChangeLog
+++ b/gcc/analyzer/ChangeLog
@@ -1,3 +1,41 @@
+2025-07-11 David Malcolm <dmalcolm@redhat.com>
+
+ * ana-state-to-diagnostic-state.cc: Reimplement, replacing
+ XML-based implementation with one based on state graphs.
+ * ana-state-to-diagnostic-state.h: Likewise.
+ * checker-event.cc: Replace include of "xml.h" with include of
+ "diagnostic-state-graphs.h".
+ (checker_event::maybe_make_xml_state): Replace with...
+ (checker_event::maybe_make_diagnostic_state_graph): ...this.
+ * checker-event.h: Add include of "diagnostic-digraphs.h".
+ (checker_event::maybe_make_xml_state): Replace decl with...
+ (checker_event::maybe_make_diagnostic_state_graph): ...this.
+ * engine.cc (exploded_node::on_stmt_pre): Replace
+ "_analyzer_dump_xml" with "__analyzer_dump_sarif".
+ * program-state.cc: Replace include of "diagnostic-state.h" with
+ "diagnostic-state-graphs.h".
+ (program_state::dump_dot): Port from XML to state graphs.
+ * program-state.h: Drop reduntant forward decl of xml::document.
+ (program_state::make_xml): Replace decl with...
+ (program_state::make_diagnostic_state_graph): ...this.
+ (program_state::dump_xml_to_pp): Drop decl.
+ (program_state::dump_xml_to_file): Drop decl.
+ (program_state::dump_xml): Drop decl.
+ (program_state::dump_dump_sarif): New decl.
+ * sm-malloc.cc (get_dynalloc_state_for_state): New.
+ (malloc_state_machine::add_state_to_xml): Replace with...
+ (malloc_state_machine::add_state_to_state_graph): ...this.
+ * sm.cc (state_machine::add_state_to_xml): Replace with...
+ (state_machine::add_state_to_state_graph): ...this.
+ (state_machine::add_global_state_to_xml): Replace with...
+ (state_machine::add_global_state_to_state_graph): ...this.
+ * sm.h (class xml_state): Drop forward decl.
+ (class analyzer_state_graph): New forward decl.
+ (state_machine::add_state_to_xml): Replace decl with...
+ (state_machine::add_state_to_state_graph): ...this.
+ (state_machine::add_global_state_to_xml): Replace decl with...
+ (state_machine::add_global_state_to_state_graph): ...this.
+
2025-06-30 David Malcolm <dmalcolm@redhat.com>
* access-diagram.cc: Use nullptr rather than NULL where
diff --git a/gcc/analyzer/ana-state-to-diagnostic-state.cc b/gcc/analyzer/ana-state-to-diagnostic-state.cc
index b85a2f1..2701259 100644
--- a/gcc/analyzer/ana-state-to-diagnostic-state.cc
+++ b/gcc/analyzer/ana-state-to-diagnostic-state.cc
@@ -1,4 +1,4 @@
-/* Converting ana::program_state to XML state documents.
+/* Creating diagnostic state graphs from ana::program_state.
Copyright (C) 2025 Free Software Foundation, Inc.
Contributed by David Malcolm <dmalcolm@redhat.com>.
@@ -23,8 +23,8 @@ along with GCC; see the file COPYING3. If not see
#define INCLUDE_SET
#include "analyzer/common.h"
-#include "xml.h"
-#include "xml-printer.h"
+#include "diagnostic-state-graphs.h"
+#include "diagnostic-format-sarif.h"
#include "analyzer/region-model.h"
#include "analyzer/program-state.h"
@@ -39,57 +39,47 @@ along with GCC; see the file COPYING3. If not see
namespace ana {
+using namespace ::diagnostics::state_graphs;
+
static void
-set_wi_attr (xml::element &e,
+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);
- e.set_attr (attr_name, pp_formatted_text (&pp));
+ state_node.set_attr (attr_name, pp_formatted_text (&pp));
}
static void
-set_type_attr (xml::element &e, 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);
- e.set_attr ("type", pp_formatted_text (&pp));
+ state_node.set_type (pp_formatted_text (&pp));
}
static void
-set_bits_attr (xml::element &e,
+set_bits_attr (state_node_ref state_node,
bit_range bits)
{
pretty_printer pp;
bits.dump_to_pp (&pp);
- e.set_attr ("bits", pp_formatted_text (&pp));
+ state_node.set_attr ("bits", pp_formatted_text (&pp));
}
-static void
-set_region_id_attr (xml::element &e,
- const region &reg)
-{
- e.set_attr ("region_id", std::to_string (reg.get_id ()));
-}
+// class analyzer_state_graph : public diagnostics::digraphs::digraph
-// class xml_state : public xml::document
-
-xml_state::xml_state (const program_state &state,
- const extrinsic_state &ext_state)
-: xml::document (),
- m_state (state),
+analyzer_state_graph::analyzer_state_graph (const program_state &state,
+ const extrinsic_state &ext_state)
+: m_state (state),
m_ext_state (ext_state),
m_mgr (*ext_state.get_engine ()->get_model_manager ()),
- m_root (nullptr)
+ m_next_id (0)
{
- auto root = std::make_unique<xml::element> ("state-diagram", false);
- m_root = root.get ();
- add_child (std::move (root));
-
/* Find pointers to heap-allocated regions, and record their types,
so that we have a user-friendly way of showing the memory
(by field, rather than by byte offset). */
@@ -117,14 +107,14 @@ xml_state::xml_state (const program_state &state,
for (int i = state.m_region_model->get_stack_depth () - 1; i >= 0; --i)
{
const frame_region *reg = state.m_region_model->get_frame_at_index (i);
- get_or_create_element (*reg);
+ get_or_create_state_node (*reg);
}
/* Create bound memory. */
for (auto iter : *state.m_region_model->get_store ())
{
const bool create_all = false; // "true" for verbose, for debugging
- create_elements_for_binding_cluster (*iter.second, create_all);
+ create_state_nodes_for_binding_cluster (*iter.second, create_all);
}
/* TODO: Constraints. */
@@ -137,52 +127,165 @@ xml_state::xml_state (const program_state &state,
{
auto &sm = ext_state.get_sm (i);
for (const auto &iter : *smap)
- sm.add_state_to_xml (*this, *iter.first, iter.second.m_state);
+ sm.add_state_to_state_graph (*this, *iter.first, iter.second.m_state);
if (auto s = smap->get_global_state ())
- sm.add_global_state_to_xml (*this, s);
+ sm.add_global_state_to_state_graph (*this, s);
}
}
+
+ /* Process pending edges. */
+ while (m_pending_edges.size () > 0)
+ {
+ pending_edge item = m_pending_edges.back ();
+ m_pending_edges.pop_back ();
+
+ /* 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.m_node, dst_node.m_node);
+ }
}
-xml::element &
-xml_state::get_or_create_element (const region &reg)
+state_node_ref
+analyzer_state_graph::get_or_create_state_node (const region &reg)
{
- auto existing = m_region_to_element_map.find (&reg);
- if (existing != m_region_to_element_map.end ())
+ auto existing = m_region_to_state_node_map.find (&reg);
+ if (existing != m_region_to_state_node_map.end ())
return *existing->second;
- auto &e = create_and_add_element (reg);
- m_region_to_element_map[&reg] = &e;
- return e;
+ auto ref = create_and_add_state_node (reg);
+ m_region_to_state_node_map[&reg] = &ref.m_node;
+ return ref;
}
-xml::element&
-xml_state::create_and_add_element (const region &reg)
+state_node_ref
+analyzer_state_graph::create_and_add_state_node (const region &reg)
{
- auto e = create_element (reg);
- xml::element &result = *e;
+ auto node = create_state_node (reg);
+
+ 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.m_node.add_child (std::move (node));
+ return result;
+ }
+ add_node (std::move (node));
+ return result;
+}
+
+std::string
+analyzer_state_graph::make_node_id (const char *prefix)
+{
+ return std::string (prefix) + "-" + std::to_string (m_next_id++);
+}
+
+std::string
+analyzer_state_graph::make_node_id (const region &reg)
+{
+ const char *prefix = nullptr;
+ switch (reg.get_kind ())
{
- auto parent_element = &get_or_create_element (*parent_reg);
- parent_element->add_child (std::move (e));
+ case RK_ROOT:
+ default:
+ gcc_unreachable ();
+ break;
+
+ case RK_GLOBALS:
+ return "globals";
+ case RK_CODE:
+ return "code";
+ case RK_STACK:
+ return "stack";
+ case RK_HEAP:
+ return "heap";
+
+ case RK_FRAME:
+ prefix = "frame-region";
+ break;
+ case RK_FUNCTION:
+ prefix = "function-region";
+ break;
+ case RK_LABEL:
+ prefix = "label-region";
+ break;
+ case RK_THREAD_LOCAL:
+ prefix = "thread-local-region";
+ break;
+ case RK_SYMBOLIC:
+ prefix = "symbolic-region";
+ break;
+ case RK_DECL:
+ prefix = "decl-region";
+ break;
+ case RK_FIELD:
+ prefix = "field-region";
+ break;
+ case RK_ELEMENT:
+ prefix = "element-region";
+ break;
+ case RK_OFFSET:
+ prefix = "offset-region";
+ break;
+ case RK_SIZED:
+ prefix = "sized-region";
+ break;
+ case RK_CAST:
+ prefix = "cast-region";
+ break;
+ case RK_HEAP_ALLOCATED:
+ prefix = "heap-allocated-region";
+ break;
+ case RK_ALLOCA:
+ prefix = "alloca-region";
+ break;
+ case RK_STRING:
+ prefix = "string-region";
+ break;
+ case RK_BIT_RANGE:
+ prefix = "bit-range-region";
+ break;
+ case RK_VAR_ARG:
+ prefix = "var-arg-region";
+ break;
+ case RK_ERRNO:
+ prefix = "errno-region";
+ break;
+ case RK_PRIVATE:
+ prefix = "private-region";
+ break;
+ case RK_UNKNOWN:
+ prefix = "unknown-region";
+ break;
}
- else
- m_root->add_child (std::move (e));
- return result;
+ return std::string (prefix) + "-" + std::to_string (reg.get_id ());
+}
+
+std::unique_ptr<diagnostics::digraphs::node>
+analyzer_state_graph::
+make_state_node (diagnostics::state_graphs::node_kind kind,
+ std::string id)
+{
+ auto node = std::make_unique<diagnostics::digraphs::node> (*this, std::move (id));
+ state_node_ref node_ref (*node);
+ node_ref.set_node_kind (kind);
+ return node;
}
-std::unique_ptr<xml::element>
-xml_state::make_memory_space_element (const char *label)
+std::unique_ptr<diagnostics::digraphs::node>
+analyzer_state_graph::
+make_memspace_state_node (const region &reg,
+ diagnostics::state_graphs::node_kind kind)
{
- auto e = std::make_unique<xml::element> ("memory-space", false);
- e->set_attr ("label", label);
- return e;
+ return make_state_node (kind, make_node_id (reg));
}
-std::unique_ptr<xml::element>
-xml_state::create_element (const region &reg)
+std::unique_ptr<diagnostics::digraphs::node>
+analyzer_state_graph::create_state_node (const region &reg)
{
- std::unique_ptr<xml::element> e;
+ std::unique_ptr<diagnostics::digraphs::node> node;
+
switch (reg.get_kind ())
{
default:
@@ -190,110 +293,102 @@ xml_state::create_element (const region &reg)
case RK_FRAME:
{
- e = std::make_unique<xml::element> ("stack-frame", false);
const frame_region &frame_reg
= static_cast<const frame_region &> (reg);
+
+ 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 ()));
{
pretty_printer pp;
pp_format_decoder (&pp) = default_tree_printer;
pp_printf (&pp, "%E", frame_reg.get_fndecl ());
- e->set_attr ("function", pp_formatted_text (&pp));
+ node->set_attr (STATE_NODE_PREFIX, "function",
+ pp_formatted_text (&pp));
}
}
break;
+
case RK_GLOBALS:
- e = make_memory_space_element ("Globals");
+ node = make_memspace_state_node (reg,
+ diagnostics::state_graphs::node_kind::globals);
break;
case RK_CODE:
- e = make_memory_space_element ("Code");
+ node = make_memspace_state_node (reg,
+ diagnostics::state_graphs::node_kind::code);
break;
case RK_FUNCTION:
- e = std::make_unique<xml::element> ("function", false);
- // TODO
- break;
- case RK_LABEL:
- e = std::make_unique<xml::element> ("label", false);
+ node = make_memspace_state_node (reg,
+ diagnostics::state_graphs::node_kind::function);
// TODO
break;
+
case RK_STACK:
- e = std::make_unique<xml::element> ("stack", false);
+ node = make_memspace_state_node (reg,
+ diagnostics::state_graphs::node_kind::stack);
break;
case RK_HEAP:
- e = make_memory_space_element ("Heap");
+ node = make_memspace_state_node (reg,
+ diagnostics::state_graphs::node_kind::heap_);
break;
case RK_THREAD_LOCAL:
- e = make_memory_space_element ("Thread-local");
+ node = make_memspace_state_node (reg,
+ diagnostics::state_graphs::node_kind::thread_local_);
break;
case RK_ROOT:
- e = std::make_unique<xml::element> ("memory-regions", false);
+ gcc_unreachable ();
break;
case RK_SYMBOLIC:
- e = std::make_unique<xml::element> ("symbolic-region", false);
- // TODO
+ node = make_memspace_state_node (reg,
+ diagnostics::state_graphs::node_kind::other);
break;
+
case RK_DECL:
{
- e = std::make_unique<xml::element> ("variable", false);
+ 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 ());
- e->set_attr ("name", pp_formatted_text (&pp));
+ node_ref.set_name (pp_formatted_text (&pp));
}
- set_type_attr (*e, TREE_TYPE (decl_reg.get_decl ()));
+ set_type_attr (*node, TREE_TYPE (decl_reg.get_decl ()));
}
break;
+
case RK_FIELD:
- e = std::make_unique<xml::element> ("field", false);
- break;
case RK_ELEMENT:
- e = std::make_unique<xml::element> ("element", false);
+ /* These should be handled in populate_state_node_for_typed_region. */
+ gcc_unreachable ();
break;
+
+ case RK_LABEL:
case RK_OFFSET:
- e = std::make_unique<xml::element> ("offset-region", false);
- // TODO
- break;
case RK_SIZED:
- e = std::make_unique<xml::element> ("sized-region", false);
- // TODO
- break;
case RK_CAST:
- e = std::make_unique<xml::element> ("cast-region", false);
- // TODO
- break;
- case RK_HEAP_ALLOCATED:
- e = std::make_unique<xml::element> ("heap-buffer", false);
- set_attr_for_dynamic_extents (reg, *e);
- break;
- case RK_ALLOCA:
- e = std::make_unique<xml::element> ("alloca-buffer", false);
- set_attr_for_dynamic_extents (reg, *e);
- break;
case RK_STRING:
- e = std::make_unique<xml::element> ("string-region", false);
- // TODO
- break;
case RK_BIT_RANGE:
- e = std::make_unique<xml::element> ("RK_BIT_RANGE", false); // TODO
- break;
case RK_VAR_ARG:
- e = std::make_unique<xml::element> ("RK_VAR_ARG", false); // TODO
- break;
case RK_ERRNO:
- e = std::make_unique<xml::element> ("errno", false);
- break;
case RK_PRIVATE:
- e = std::make_unique<xml::element> ("RK_PRIVATE", false); // TODO
- break;
case RK_UNKNOWN:
- e = std::make_unique<xml::element> ("RK_UNKNOWN", false); // TODO
+ node = make_state_node (diagnostics::state_graphs::node_kind::other,
+ make_node_id (reg));
break;
- }
- gcc_assert (e);
- set_region_id_attr (*e, reg);
+ case RK_HEAP_ALLOCATED:
+ case RK_ALLOCA:
+ node = make_memspace_state_node (reg,
+ diagnostics::state_graphs::node_kind::dynalloc_buffer);
+ set_attr_for_dynamic_extents (reg, *node);
+ break;
+ }
+ gcc_assert (node);
if (reg.get_base_region () == &reg)
if (!reg.get_type ())
@@ -303,16 +398,17 @@ xml_state::create_element (const region &reg)
if (search != m_types_for_untyped_regions.end ())
{
tree type_to_use = search->second;
- set_type_attr (*e, type_to_use);
+ set_type_attr (*node, type_to_use);
}
}
- return e;
+ return node;
}
void
-xml_state::create_elements_for_binding_cluster (const binding_cluster &cluster,
- bool create_all)
+analyzer_state_graph::
+create_state_nodes_for_binding_cluster (const binding_cluster &cluster,
+ bool create_all)
{
/* TODO:
- symbolic bindings
@@ -326,12 +422,12 @@ xml_state::create_elements_for_binding_cluster (const binding_cluster &cluster,
if (auto conc_key = key->dyn_cast_concrete_binding ())
conc_bindings[conc_key->get_bit_range ()] = svalue;
if (const region *reg = svalue->maybe_get_region ())
- get_or_create_element (*reg);
+ get_or_create_state_node (*reg);
}
- auto &e = get_or_create_element (*cluster.get_base_region ());
+ auto ref = get_or_create_state_node (*cluster.get_base_region ());
- e.add_child (create_element_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 ())
@@ -346,44 +442,45 @@ xml_state::create_elements_for_binding_cluster (const binding_cluster &cluster,
}
if (typed_reg->get_type ())
- populate_element_for_typed_region (e,
- *typed_reg,
- conc_bindings,
- create_all);
+ populate_state_node_for_typed_region (ref,
+ *typed_reg,
+ conc_bindings,
+ create_all);
else
{
// TODO
}
}
-std::unique_ptr<xml::element>
-xml_state::create_element_for_conc_bindings (const concrete_bindings_t &conc_bindings)
+std::unique_ptr<diagnostics::digraphs::node>
+analyzer_state_graph::create_state_node_for_conc_bindings (const concrete_bindings_t &conc_bindings)
{
- auto e = std::make_unique<xml::element> ("concrete-bindings", false);
+ 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_element
- = std::make_unique<xml::element> ("binding", false);
- set_bits_attr (*binding_element, bits);
+ auto binding_state_node
+ = make_state_node (diagnostics::state_graphs::node_kind::other,
+ make_node_id ("binding"));
+ set_bits_attr (*binding_state_node, bits);
{
pretty_printer pp;
pp_format_decoder (&pp) = default_tree_printer;
sval->dump_to_pp (&pp, true);
- binding_element->set_attr ("value", pp_formatted_text (&pp));
- if (auto svalue_element = create_element_for_svalue (sval))
- binding_element->add_child (std::move (svalue_element));
+ binding_state_node->set_attr (STATE_NODE_PREFIX, "value",
+ pp_formatted_text (&pp));
}
- e->add_child (std::move (binding_element));
+ node->add_child (std::move (binding_state_node));
}
- return e;
+ return node;
}
// Try to get the bit_range of REG within its base region
bool
-xml_state::get_bit_range_within_base_region (const region &reg,
- bit_range &out)
+analyzer_state_graph::get_bit_range_within_base_region (const region &reg,
+ bit_range &out)
{
region_offset start_offset = reg.get_offset (&m_mgr);
if (!start_offset.concrete_p ())
@@ -398,30 +495,28 @@ xml_state::get_bit_range_within_base_region (const region &reg,
}
void
-xml_state::populate_element_for_typed_region (xml::element &e,
- const region &reg,
- const concrete_bindings_t &conc_bindings,
- bool create_all)
+analyzer_state_graph::
+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 (e, 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 (e, bits);
+ set_bits_attr (node, bits);
auto search = conc_bindings.find (bits);
if (search != conc_bindings.end ())
{
const svalue *bound_sval = search->second;
- if (auto svalue_element = create_element_for_svalue (bound_sval))
- {
- xml::printer xp (e);
- xp.push_tag ("value-of-region");
- xp.append (std::move (svalue_element));
- }
+ node.set_json_attr ("value", bound_sval->to_json ());
+ if (const region *dst_reg = bound_sval->maybe_get_region ())
+ m_pending_edges.push_back ({node, *dst_reg});
}
}
@@ -454,22 +549,23 @@ xml_state::populate_element_for_typed_region (xml::element &e,
= m_mgr.get_element_region (&reg,
const_cast<tree> (element_type),
sval_index);
- if (show_child_element_for_child_region_p (*child_reg,
+ if (show_child_state_node_for_child_region_p (*child_reg,
conc_bindings,
create_all))
{
- // Here "element" is in the xml sense
- auto child_element
- = std::make_unique<xml::element> ("element", false);
- set_wi_attr (*child_element, "index", idx, UNSIGNED);
- set_region_id_attr (*child_element, *child_reg);
+ auto child_state_node
+ = make_state_node
+ (diagnostics::state_graphs::node_kind::element,
+ make_node_id (*child_reg));
+ set_wi_attr (*child_state_node, "index", idx, UNSIGNED);
+
// Recurse:
gcc_assert (element_type);
- populate_element_for_typed_region (*child_element,
- *child_reg,
- conc_bindings,
- create_all);
- e.add_child (std::move (child_element));
+ populate_state_node_for_typed_region (*child_state_node,
+ *child_reg,
+ conc_bindings,
+ create_all);
+ node.m_node.add_child (std::move (child_state_node));
}
}
}
@@ -485,15 +581,17 @@ xml_state::populate_element_for_typed_region (xml::element &e,
const bit_range bits (0, item.m_bit_range.m_size_in_bits);
const region *child_reg
= m_mgr.get_bit_range (&reg, NULL_TREE, bits);
- if (show_child_element_for_child_region_p (*child_reg,
- conc_bindings,
- create_all))
+ if (show_child_state_node_for_child_region_p (*child_reg,
+ conc_bindings,
+ create_all))
{
- auto child_element
- = std::make_unique<xml::element> ("padding", false);
- set_wi_attr (*child_element, "num_bits",
+ auto child_state_node
+ = make_state_node
+ (diagnostics::state_graphs::node_kind::padding,
+ make_node_id (*child_reg));
+ set_wi_attr (*child_state_node, "num_bits",
item.m_bit_range.m_size_in_bits, SIGNED);
- e.add_child (std::move (child_element));
+ node.m_node.add_child (std::move (child_state_node));
}
}
else
@@ -501,26 +599,28 @@ xml_state::populate_element_for_typed_region (xml::element &e,
const region *child_reg
= m_mgr.get_field_region (&reg,
const_cast<tree> (item.m_field));
- if (show_child_element_for_child_region_p (*child_reg,
+ if (show_child_state_node_for_child_region_p (*child_reg,
conc_bindings,
create_all))
{
- auto child_element
- = std::make_unique<xml::element> ("field", false);
+ auto child_state_node
+ = make_state_node
+ (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_element->set_attr ("name",
- pp_formatted_text (&pp));
+ child_state_node->set_attr (STATE_NODE_PREFIX, "name",
+ pp_formatted_text (&pp));
}
- set_region_id_attr (*child_element, *child_reg);
+
// Recurse:
- populate_element_for_typed_region (*child_element,
+ populate_state_node_for_typed_region (*child_state_node,
*child_reg,
conc_bindings,
create_all);
- e.add_child (std::move (child_element));
+ node.m_node.add_child (std::move (child_state_node));
}
}
}
@@ -530,7 +630,8 @@ xml_state::populate_element_for_typed_region (xml::element &e,
}
void
-xml_state::set_attr_for_dynamic_extents (const region &reg, xml::element &e)
+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)
@@ -541,13 +642,13 @@ xml_state::set_attr_for_dynamic_extents (const region &reg, xml::element &e)
pp_wide_int (&pp, wi::to_wide (cst), UNSIGNED);
else
sval->dump_to_pp (&pp, true);
- e.set_attr ("dynamic-extents", pp_formatted_text (&pp));
+ node_ref.set_attr ("dynamic-extents", pp_formatted_text (&pp));
}
}
bool
-xml_state::
-show_child_element_for_child_region_p (const region &reg,
+analyzer_state_graph::
+show_child_state_node_for_child_region_p (const region &reg,
const concrete_bindings_t &conc_bindings,
bool create_all)
{
@@ -569,216 +670,18 @@ show_child_element_for_child_region_p (const region &reg,
return false;
}
-std::unique_ptr<xml::element>
-xml_state::create_element_for_svalue (const svalue *sval)
+std::unique_ptr<diagnostics::digraphs::digraph>
+program_state::
+make_diagnostic_state_graph (const extrinsic_state &ext_state) const
{
- if (!sval)
- return nullptr;
-
- std::unique_ptr<xml::element> result;
- switch (sval->get_kind ())
- {
- default:
- gcc_unreachable ();
- case SK_REGION:
- {
- const region_svalue *region_sval = (const region_svalue *)sval;
- result
- = std::make_unique<xml::element> ("pointer-to-region", false);
- set_region_id_attr (*result, *region_sval->get_pointee ());
- }
- break;
- case SK_CONSTANT:
- {
- const constant_svalue *constant_sval = (const constant_svalue *)sval;
- result = std::make_unique<xml::element> ("constant", false);
- pretty_printer pp;
- pp_format_decoder (&pp) = default_tree_printer;
- pp_printf (&pp, "%E", constant_sval->get_constant ());
- result->set_attr ("value", pp_formatted_text (&pp));
- }
- break;
- case SK_UNKNOWN:
- result = std::make_unique<xml::element> ("unknown", false);
- break;
- case SK_POISONED:
- {
- const poisoned_svalue *poisoned_sval = (const poisoned_svalue *)sval;
- switch (poisoned_sval->get_poison_kind ())
- {
- default:
- gcc_unreachable ();
- case poison_kind::uninit:
- result = std::make_unique<xml::element> ("uninitialized", false);
- break;
- case poison_kind::freed:
- result = std::make_unique<xml::element> ("freed", false);
- break;
- case poison_kind::deleted:
- result = std::make_unique<xml::element> ("deleted", false);
- break;
- case poison_kind::popped_stack:
- result = std::make_unique<xml::element> ("popped-stack", false);
- break;
- }
- }
- break;
- case SK_SETJMP:
- {
- //const setjmp_svalue *setjmp_sval = (const setjmp_svalue *)sval;
- result = std::make_unique<xml::element> ("setjmp-buffer", false);
- // TODO
- }
- break;
- case SK_INITIAL:
- {
- const initial_svalue *initial_sval = (const initial_svalue *)sval;
- result = std::make_unique<xml::element> ("initial-value-of", false);
- set_region_id_attr (*result, *initial_sval->get_region ());
- }
- break;
- case SK_UNARYOP:
- {
- const unaryop_svalue *unaryop_sval = (const unaryop_svalue *)sval;
- result = std::make_unique<xml::element> ("unary-op", false);
- result->set_attr ("op", get_tree_code_name (unaryop_sval->get_op ()));
- result->add_child
- (create_element_for_svalue (unaryop_sval->get_arg ()));
- }
- break;
- case SK_BINOP:
- {
- const binop_svalue *binop_sval = (const binop_svalue *)sval;
- result = std::make_unique<xml::element> ("binary-op", false);
- result->set_attr ("op", get_tree_code_name (binop_sval->get_op ()));
- result->add_child (create_element_for_svalue (binop_sval->get_arg0 ()));
- result->add_child (create_element_for_svalue (binop_sval->get_arg1 ()));
- }
- break;
- case SK_SUB:
- {
- //const sub_svalue *sub_sval = (const sub_svalue *)sval;
- result = std::make_unique<xml::element> ("subregion-value", false);
- // TODO
- }
- break;
- case SK_REPEATED:
- {
- const repeated_svalue *repeated_sval = (const repeated_svalue *)sval;
- result = std::make_unique<xml::element> ("repeated-value", false);
- result->add_child
- (create_element_for_svalue (repeated_sval->get_outer_size ()));
- result->add_child
- (create_element_for_svalue (repeated_sval->get_inner_svalue ()));
- }
- break;
- case SK_BITS_WITHIN:
- {
- const bits_within_svalue *bits_within_sval
- = (const bits_within_svalue *)sval;
- result = std::make_unique<xml::element> ("bits-within", false);
- set_bits_attr (*result, bits_within_sval->get_bits ());
- result->add_child
- (create_element_for_svalue (bits_within_sval->get_inner_svalue ()));
- }
- break;
- case SK_UNMERGEABLE:
- {
- const unmergeable_svalue *unmergeable_sval
- = (const unmergeable_svalue *)sval;
- result = std::make_unique<xml::element> ("unmergeable", false);
- result->add_child
- (create_element_for_svalue (unmergeable_sval->get_arg ()));
- }
- break;
- case SK_PLACEHOLDER:
- {
- const placeholder_svalue *placeholder_sval
- = (const placeholder_svalue *)sval;
- result = std::make_unique<xml::element> ("placeholder", false);
- result->set_attr ("name", placeholder_sval->get_name ());
- }
- break;
- case SK_WIDENING:
- {
- //const widening_svalue *widening_sval = (const widening_svalue *)sval;
- result = std::make_unique<xml::element> ("iterating-value", false);
- // TODO
- }
- break;
- case SK_COMPOUND:
- {
- //const compound_svalue *compound_sval = (const compound_svalue *)sval;
- result = std::make_unique<xml::element> ("compound-value", false);
- // TODO
- }
- break;
- case SK_CONJURED:
- {
- //const conjured_svalue *conjured_sval = (const conjured_svalue *)sval;
- result = std::make_unique<xml::element> ("conjured-value", false);
- // TODO
- }
- break;
- case SK_ASM_OUTPUT:
- {
- /* const asm_output_svalue *asm_output_sval
- = (const asm_output_svalue *)sval; */
- result = std::make_unique<xml::element> ("asm-output", false);
- // TODO
- }
- break;
- case SK_CONST_FN_RESULT:
- {
- /* const const_fn_result_svalue *const_fn_result_sval
- = (const const_fn_result_svalue *)sval; */
- result = std::make_unique<xml::element> ("const-fn-result", false);
- // TODO
- }
- }
-
- if (result)
- {
- if (sval->get_type ())
- set_type_attr (*result, sval->get_type ());
-
- pretty_printer pp;
- pp_format_decoder (&pp) = default_tree_printer;
- sval->dump_to_pp (&pp, true);
- result->set_attr ("dump-text", pp_formatted_text (&pp));
- }
-
- return result;
-}
-
-std::unique_ptr<xml::document>
-program_state::make_xml (const extrinsic_state &ext_state) const
-{
- return std::make_unique<xml_state> (*this, ext_state);
-}
-
-void
-program_state::dump_xml_to_pp (const extrinsic_state &ext_state,
- pretty_printer *pp) const
-{
- auto doc = make_xml (ext_state);
- doc->write_as_xml (pp, 0, true);
-}
-
-void
-program_state::dump_xml_to_file (const extrinsic_state &ext_state,
- FILE *outf) const
-{
- pretty_printer pp;
- pp.set_output_stream (outf);
- dump_xml_to_pp (ext_state, &pp);
- pp_flush (&pp);
+ return std::make_unique<analyzer_state_graph> (*this, ext_state);
}
void
-program_state::dump_xml (const extrinsic_state &ext_state) const
+program_state::dump_sarif (const extrinsic_state &ext_state) const
{
- dump_xml_to_file (ext_state, stderr);
+ auto g = make_diagnostic_state_graph (ext_state);
+ g->dump ();
}
} // namespace ana
diff --git a/gcc/analyzer/ana-state-to-diagnostic-state.h b/gcc/analyzer/ana-state-to-diagnostic-state.h
index bd6aa46..186e19d 100644
--- a/gcc/analyzer/ana-state-to-diagnostic-state.h
+++ b/gcc/analyzer/ana-state-to-diagnostic-state.h
@@ -1,4 +1,4 @@
-/* XML documents for dumping state in an easier-to-read form.
+/* Creating diagnostic state graphs from ana::program_state.
Copyright (C) 2025 Free Software Foundation, Inc.
Contributed by David Malcolm <dmalcolm@redhat.com>.
@@ -18,41 +18,52 @@ 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_ANALYZER_ANA_STATE_TO_XML_STATE_H
-#define GCC_ANALYZER_ANA_STATE_TO_XML_STATE_H
+#ifndef GCC_ANALYZER_ANA_STATE_TO_DIAGNOSTIC_STATE_H
+#define GCC_ANALYZER_ANA_STATE_TO_DIAGNOSTIC_STATE_H
-#include "xml.h"
+#include "diagnostic-state-graphs.h"
+#include "tree-logical-location.h"
namespace ana {
-class xml_state : public xml::document
+class analyzer_state_graph : public diagnostics::digraphs::digraph
{
public:
- xml_state (const program_state &state,
- const extrinsic_state &ext_state);
-
- xml::element &
- get_or_create_element (const region &reg);
+ analyzer_state_graph (const program_state &state,
+ const extrinsic_state &ext_state);
+ diagnostics::state_graphs::state_node_ref
+ get_or_create_state_node (const region &reg);
private:
- xml::element&
- create_and_add_element (const region &reg);
-
- static std::unique_ptr<xml::element>
- make_memory_space_element (const char *label);
-
- std::unique_ptr<xml::element>
- create_element (const region &reg);
+ struct pending_edge
+ {
+ diagnostics::state_graphs::state_node_ref m_src_node;
+ const region &m_dst_reg;
+ };
+
+ diagnostics::state_graphs::state_node_ref
+ create_and_add_state_node (const region &reg);
+
+ std::unique_ptr<diagnostics::digraphs::node>
+ 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 diagnostics::state_graphs::node_kind kind);
+
+ std::unique_ptr<diagnostics::digraphs::node>
+ create_state_node (const region &reg);
/* Spatially sorted concrete bindings. */
typedef std::map<bit_range, const svalue *> concrete_bindings_t;
void
- create_elements_for_binding_cluster (const binding_cluster &cluster,
- bool create_all);
+ create_state_nodes_for_binding_cluster (const binding_cluster &cluster,
+ bool create_all);
- std::unique_ptr<xml::element>
- create_element_for_conc_bindings (const concrete_bindings_t &conc_bindings);
+ std::unique_ptr<diagnostics::digraphs::node>
+ create_state_node_for_conc_bindings (const concrete_bindings_t &conc_bindings);
// Try to get the bit_range of REG within its base region
bool
@@ -60,30 +71,36 @@ private:
bit_range &out);
void
- populate_element_for_typed_region (xml::element &e,
- const region &reg,
- const concrete_bindings_t &conc_bindings,
- bool create_all);
+ 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, xml::element &e);
+ set_attr_for_dynamic_extents (const region &reg,
+ diagnostics::state_graphs::state_node_ref);
bool
- show_child_element_for_child_region_p (const region &reg,
- const concrete_bindings_t &conc_bindings,
- bool create_all);
+ show_child_state_node_for_child_region_p (const region &reg,
+ const concrete_bindings_t &conc_bindings,
+ bool create_all);
+
+ std::unique_ptr<diagnostics::digraphs::node>
+ create_state_node_for_svalue (const svalue *sval);
- std::unique_ptr<xml::element>
- create_element_for_svalue (const svalue *sval);
+ std::string make_node_id (const region &reg);
+ std::string make_node_id (const char *prefix);
+ tree_logical_location_manager m_logical_loc_mgr;
const program_state &m_state;
const extrinsic_state &m_ext_state;
region_model_manager &m_mgr;
- xml::element *m_root;
- std::map<const region *, xml::element *> m_region_to_element_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;
};
} // namespace ana
-#endif /* GCC_ANALYZER_ANA_STATE_TO_XML_STATE_H */
+#endif /* GCC_ANALYZER_ANA_STATE_TO_DIAGNOSTIC_STATE_H */
diff --git a/gcc/analyzer/checker-event.cc b/gcc/analyzer/checker-event.cc
index af336df..8cc5ac2 100644
--- a/gcc/analyzer/checker-event.cc
+++ b/gcc/analyzer/checker-event.cc
@@ -28,7 +28,7 @@ along with GCC; see the file COPYING3. If not see
#include "inlining-iterator.h"
#include "tree-logical-location.h"
#include "diagnostic-format-sarif.h"
-#include "xml.h"
+#include "diagnostic-state-graphs.h"
#include "analyzer/analyzer-logging.h"
#include "analyzer/sm.h"
@@ -225,8 +225,8 @@ checker_event::prepare_for_emission (checker_path *path,
print_desc (*pp.get ());
}
-std::unique_ptr<xml::document>
-checker_event::maybe_make_xml_state (bool debug) const
+std::unique_ptr<diagnostics::digraphs::digraph>
+checker_event::maybe_make_diagnostic_state_graph (bool debug) const
{
const program_state *state = get_program_state ();
if (!state)
@@ -235,14 +235,16 @@ checker_event::maybe_make_xml_state (bool debug) const
gcc_assert (m_path);
const extrinsic_state &ext_state = m_path->get_ext_state ();
- auto result = state->make_xml (ext_state);
+ auto result = state->make_diagnostic_state_graph (ext_state);
if (debug)
{
pretty_printer pp;
text_art::theme *theme = global_dc->get_diagram_theme ();
text_art::dump_to_pp (*state, theme, &pp);
- result->add_comment (pp_formatted_text (&pp));
+ result->set_attr (STATE_GRAPH_PREFIX,
+ "analyzer/program_state/",
+ pp_formatted_text (&pp));
}
return result;
diff --git a/gcc/analyzer/checker-event.h b/gcc/analyzer/checker-event.h
index 7c44f1e..cf24e77 100644
--- a/gcc/analyzer/checker-event.h
+++ b/gcc/analyzer/checker-event.h
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-logical-location.h"
#include "analyzer/program-state.h"
#include "analyzer/event-loc-info.h"
+#include "diagnostic-digraphs.h"
namespace ana {
@@ -128,12 +129,12 @@ public:
virtual bool is_function_entry_p () const { return false; }
virtual bool is_return_p () const { return false; }
+ std::unique_ptr<diagnostics::digraphs::digraph>
+ maybe_make_diagnostic_state_graph (bool debug) const final override;
+
virtual const program_state *
get_program_state () const { return nullptr; }
- std::unique_ptr<xml::document>
- maybe_make_xml_state (bool debug) const final override;
-
/* For use with %@. */
const diagnostic_event_id_t *get_id_ptr () const
{
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 67024e9..745ef7e 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -1580,9 +1580,9 @@ exploded_node::on_stmt_pre (exploded_graph &eg,
state->dump (eg.get_ext_state (), true);
return;
}
- else if (is_special_named_call_p (call, "__analyzer_dump_xml", 0))
+ else if (is_special_named_call_p (call, "__analyzer_dump_sarif", 0))
{
- state->dump_xml (eg.get_ext_state ());
+ state->dump_sarif (eg.get_ext_state ());
return;
}
else if (is_special_named_call_p (call, "__analyzer_dump_dot", 0))
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index c0befac..85cbe75 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -28,7 +28,7 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h"
#include "digraph.h"
#include "diagnostic-event-id.h"
-#include "diagnostic-state.h"
+#include "diagnostic-state-graphs.h"
#include "graphviz.h"
#include "text-art/tree-widget.h"
@@ -1230,8 +1230,14 @@ program_state::make_dump_widget (const text_art::dump_widget_info &dwi) const
void
program_state::dump_dot (const extrinsic_state &ext_state) const
{
- auto doc = make_xml (ext_state);
- auto graph = make_dot_graph_from_xml_state (*doc);
+ auto state_graph = make_diagnostic_state_graph (ext_state);
+
+ gcc_assert (global_dc);
+ auto logical_loc_mgr = global_dc->get_logical_location_manager ();
+ gcc_assert (logical_loc_mgr);
+
+ auto graph = diagnostics::state_graphs::make_dot_graph (*state_graph,
+ *logical_loc_mgr);
pretty_printer pp;
dot::writer w (pp);
diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h
index e2076c1..4278237 100644
--- a/gcc/analyzer/program-state.h
+++ b/gcc/analyzer/program-state.h
@@ -26,8 +26,6 @@ along with GCC; see the file COPYING3. If not see
#include "analyzer/store.h"
-namespace xml { class document; }
-
namespace ana {
/* Data shared by all program_state instances. */
@@ -248,11 +246,14 @@ public:
void dump (const extrinsic_state &ext_state, bool simple) const;
void dump () const;
- std::unique_ptr<xml::document> make_xml (const extrinsic_state &ext_state) const;
- void dump_xml_to_pp (const extrinsic_state &ext_state, pretty_printer *pp) const;
- void dump_xml_to_file (const extrinsic_state &ext_state, FILE *outf) const;
- void dump_xml (const extrinsic_state &ext_state) const;
- void dump_dot (const extrinsic_state &ext_state) const;
+ std::unique_ptr<diagnostics::digraphs::digraph>
+ make_diagnostic_state_graph (const extrinsic_state &ext_state) const;
+
+ void
+ dump_sarif (const extrinsic_state &ext_state) const;
+
+ void
+ dump_dot (const extrinsic_state &ext_state) const;
std::unique_ptr<json::object>
to_json (const extrinsic_state &ext_state) const;
diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index 3581dbb..2a218d0 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -436,9 +436,9 @@ public:
const extrinsic_state &ext_state) const;
void
- add_state_to_xml (xml_state &out_xml,
- const svalue &sval,
- state_machine::state_t state) const final override;
+ add_state_to_state_graph (analyzer_state_graph &out_state_graph,
+ const svalue &sval,
+ state_machine::state_t state) const final override;
standard_deallocator_set m_free;
standard_deallocator_set m_scalar_delete;
@@ -2735,27 +2735,57 @@ 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 diagnostics::state_graphs::node_dynalloc_state
+get_dynalloc_state_for_state (enum resource_state rs)
+{
+ switch (rs)
+ {
+ default:
+ gcc_unreachable ();
+ case RS_START:
+ case RS_NULL:
+ case RS_NON_HEAP:
+ case RS_STOP:
+ return diagnostics::state_graphs::node_dynalloc_state::unknown;
+
+ case RS_ASSUMED_NON_NULL:
+ return diagnostics::state_graphs::node_dynalloc_state::nonnull;
+
+ case RS_UNCHECKED:
+ return diagnostics::state_graphs::node_dynalloc_state::unchecked;
+ case RS_NONNULL:
+ return diagnostics::state_graphs::node_dynalloc_state::nonnull;
+ case RS_FREED:
+ return diagnostics::state_graphs::node_dynalloc_state::freed;
+ }
+}
+
void
-malloc_state_machine::add_state_to_xml (xml_state &out_xml,
- const svalue &sval,
- state_machine::state_t state) const
+malloc_state_machine::
+add_state_to_state_graph (analyzer_state_graph &out_state_graph,
+ const svalue &sval,
+ state_machine::state_t state) const
{
if (const region *reg = sval.maybe_get_region ())
{
- auto &reg_element = out_xml.get_or_create_element (*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_element.set_attr ("dynamic-alloc-state", state->get_name ());
+ 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_element.set_attr ("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_element.set_attr ("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/analyzer/sm.cc b/gcc/analyzer/sm.cc
index 840806a..c93e9c2 100644
--- a/gcc/analyzer/sm.cc
+++ b/gcc/analyzer/sm.cc
@@ -161,16 +161,16 @@ state_machine::to_json () const
}
void
-state_machine::add_state_to_xml (xml_state &out_xml,
- const svalue &sval,
- state_machine::state_t state) const
+state_machine::add_state_to_state_graph (analyzer_state_graph &out_state_graph,
+ const svalue &sval,
+ state_machine::state_t state) const
{
// no-op
}
void
-state_machine::add_global_state_to_xml (xml_state &out_xml,
- state_machine::state_t state) const
+state_machine::add_global_state_to_state_graph (analyzer_state_graph &out_state_graph,
+ state_machine::state_t state) const
{
// no-op
}
diff --git a/gcc/analyzer/sm.h b/gcc/analyzer/sm.h
index 6298fb6..4633fac 100644
--- a/gcc/analyzer/sm.h
+++ b/gcc/analyzer/sm.h
@@ -28,7 +28,7 @@ namespace ana {
class state_machine;
class sm_context;
class pending_diagnostic;
-class xml_state;
+class analyzer_state_graph;
extern bool any_pointer_p (tree expr);
extern bool any_pointer_p (const svalue *sval);
@@ -188,13 +188,13 @@ public:
state_t get_start_state () const { return m_start; }
virtual void
- add_state_to_xml (xml_state &out_xml,
- const svalue &sval,
- state_machine::state_t state) const;
+ add_state_to_state_graph (analyzer_state_graph &out_state_graph,
+ const svalue &sval,
+ state_machine::state_t state) const;
virtual void
- add_global_state_to_xml (xml_state &out_xml,
- state_machine::state_t state) const;
+ add_global_state_to_state_graph (analyzer_state_graph &out_state_graph,
+ state_machine::state_t state) const;
protected:
state_t add_state (const char *name);