aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/store.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/analyzer/store.cc')
-rw-r--r--gcc/analyzer/store.cc156
1 files changed, 156 insertions, 0 deletions
diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc
index a36de13..d14cfa3 100644
--- a/gcc/analyzer/store.cc
+++ b/gcc/analyzer/store.cc
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#define INCLUDE_MEMORY
+#define INCLUDE_VECTOR
#include "system.h"
#include "coretypes.h"
#include "tree.h"
@@ -54,6 +55,7 @@ along with GCC; see the file COPYING3. If not see
#include "analyzer/call-summary.h"
#include "analyzer/analyzer-selftests.h"
#include "stor-layout.h"
+#include "text-art/tree-widget.h"
#if ENABLE_ANALYZER
@@ -810,6 +812,56 @@ binding_map::to_json () const
return map_obj;
}
+/* Add a child to PARENT_WIDGET expressing a binding between
+ KEY and SVAL. */
+
+static void
+add_binding_to_tree_widget (text_art::tree_widget &parent_widget,
+ const text_art::dump_widget_info &dwi,
+ const binding_key *key,
+ const svalue *sval)
+{
+ pretty_printer the_pp;
+ pretty_printer * const pp = &the_pp;
+ pp_format_decoder (pp) = default_tree_printer;
+ pp_show_color (pp) = true;
+ const bool simple = true;
+
+ key->dump_to_pp (pp, simple);
+ pp_string (pp, ": ");
+ if (tree t = sval->get_type ())
+ dump_quoted_tree (pp, t);
+ pp_string (pp, " {");
+ sval->dump_to_pp (pp, simple);
+ pp_string (pp, "}");
+
+ parent_widget.add_child (text_art::tree_widget::make (dwi, pp));
+}
+
+void
+binding_map::add_to_tree_widget (text_art::tree_widget &parent_widget,
+ const text_art::dump_widget_info &dwi) const
+{
+ auto_vec <const binding_key *> binding_keys;
+ for (map_t::iterator iter = m_map.begin ();
+ iter != m_map.end (); ++iter)
+ {
+ const binding_key *key = (*iter).first;
+ binding_keys.safe_push (key);
+ }
+ binding_keys.qsort (binding_key::cmp_ptrs);
+
+ const binding_key *key;
+ unsigned i;
+ FOR_EACH_VEC_ELT (binding_keys, i, key)
+ {
+ const svalue *sval = *const_cast <map_t &> (m_map).get (key);
+ add_binding_to_tree_widget (parent_widget, dwi,
+ key, sval);
+ }
+}
+
+
/* Comparator for imposing an order on binding_maps. */
int
@@ -1399,6 +1451,48 @@ binding_cluster::to_json () const
return cluster_obj;
}
+std::unique_ptr<text_art::widget>
+binding_cluster::make_dump_widget (const text_art::dump_widget_info &dwi,
+ store_manager *mgr) const
+{
+ pretty_printer the_pp;
+ pretty_printer * const pp = &the_pp;
+ pp_format_decoder (pp) = default_tree_printer;
+ pp_show_color (pp) = true;
+ const bool simple = true;
+
+ m_base_region->dump_to_pp (pp, simple);
+ pp_string (pp, ": ");
+
+ if (const svalue *sval = maybe_get_simple_value (mgr))
+ {
+ /* Special-case to simplify dumps for the common case where
+ we just have one value directly bound to the whole of a
+ region. */
+ sval->dump_to_pp (pp, simple);
+ if (escaped_p ())
+ pp_string (pp, " (ESCAPED)");
+ if (touched_p ())
+ pp_string (pp, " (TOUCHED)");
+
+ return text_art::tree_widget::make (dwi, pp);
+ }
+ else
+ {
+ if (escaped_p ())
+ pp_string (pp, " (ESCAPED)");
+ if (touched_p ())
+ pp_string (pp, " (TOUCHED)");
+
+ std::unique_ptr<text_art::tree_widget> cluster_widget
+ (text_art::tree_widget::make (dwi, pp));
+
+ m_map.add_to_tree_widget (*cluster_widget, dwi);
+
+ return cluster_widget;
+ }
+}
+
/* Add a binding of SVAL of kind KIND to REG, unpacking SVAL if it is a
compound_sval. */
@@ -2613,6 +2707,68 @@ store::to_json () const
return store_obj;
}
+std::unique_ptr<text_art::widget>
+store::make_dump_widget (const text_art::dump_widget_info &dwi,
+ store_manager *mgr) const
+{
+ std::unique_ptr<text_art::tree_widget> store_widget
+ (text_art::tree_widget::make (dwi, "Store"));
+
+ store_widget->add_child
+ (text_art::tree_widget::from_fmt (dwi, nullptr,
+ "m_called_unknown_fn: %s",
+ m_called_unknown_fn ? "true" : "false"));
+
+ /* Sort into some deterministic order. */
+ auto_vec<const region *> base_regions;
+ for (cluster_map_t::iterator iter = m_cluster_map.begin ();
+ iter != m_cluster_map.end (); ++iter)
+ {
+ const region *base_reg = (*iter).first;
+ base_regions.safe_push (base_reg);
+ }
+ base_regions.qsort (region::cmp_ptr_ptr);
+
+ /* Gather clusters, organize by parent region, so that we can group
+ together locals, globals, etc. */
+ auto_vec<const region *> parent_regions;
+ get_sorted_parent_regions (&parent_regions, base_regions);
+
+ const region *parent_reg;
+ unsigned i;
+ FOR_EACH_VEC_ELT (parent_regions, i, parent_reg)
+ {
+ gcc_assert (parent_reg);
+
+ pretty_printer the_pp;
+ pretty_printer * const pp = &the_pp;
+ pp_format_decoder (pp) = default_tree_printer;
+ pp_show_color (pp) = true;
+ const bool simple = true;
+
+ parent_reg->dump_to_pp (pp, simple);
+
+ std::unique_ptr<text_art::tree_widget> parent_reg_widget
+ (text_art::tree_widget::make (dwi, pp));
+
+ const region *base_reg;
+ unsigned j;
+ FOR_EACH_VEC_ELT (base_regions, j, base_reg)
+ {
+ /* This is O(N * M), but N ought to be small. */
+ if (base_reg->get_parent_region () != parent_reg)
+ continue;
+ binding_cluster *cluster
+ = *const_cast<cluster_map_t &> (m_cluster_map).get (base_reg);
+ parent_reg_widget->add_child
+ (cluster->make_dump_widget (dwi, mgr));
+ }
+ store_widget->add_child (std::move (parent_reg_widget));
+ }
+
+ return store_widget;
+}
+
/* Get any svalue bound to REG, or NULL. */
const svalue *