analyzer: show value ranges in svalue::dump

Message ID 20260506141056.2747121-1-dmalcolm@redhat.com
State New
Headers
Series analyzer: show value ranges in svalue::dump |

Commit Message

David Malcolm May 6, 2026, 2:10 p.m. UTC
  This patch adds value_range info where available to the various nodes
in svalue dumps, such as:

(gdb) call rhs2_sval->dump ()
(27): ‘long long unsigned int’: binop_svalue(bit_and_expr: ‘&’) value range: {[irange] long long unsigned int [0, 0]}
├─ (24): ‘long long unsigned int’: unaryop_svalue(nop_expr) value range: {[irange] long long unsigned int [0, 4294967295] MASK 0xffffffff VALUE 0x0}
│  ╰─ (22): ‘unsigned int’: initial_svalue value range: {[irange] unsigned int VARYING}
│     ╰─ m_reg: (21): ‘unsigned int’: decl_region(‘m’)
│        ╰─ parent: (4): globals
│           ╰─ parent: (0): root region
╰─ (26): ‘long long unsigned int’: constant_svalue (‘5497558138880’) value range: {[irange] long long unsigned int [5497558138880, 5497558138880]}

where we can see that sval 27 has value range [0,0] and
where that comes from (due to being a bit_and_expr of non-overlapping
ranges from sval 24 and 26).

Successfully bootstrapped & regrtested on aarch64-unknown-linux-gnu.

Andrew: are the value-range parts OK for trunk?

gcc/analyzer/ChangeLog:
	* svalue.cc (svalue::make_dump_widget): Show value ranges in
	svalue dumps.

gcc/ChangeLog:
	* value-range.cc (value_range::print): New, based on
	value_range::dump.
	* value-range.h (value_range::print): New decl.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/analyzer/svalue.cc |  8 ++++++++
 gcc/value-range.cc     | 12 ++++++++++++
 gcc/value-range.h      |  1 +
 3 files changed, 21 insertions(+)
  

Comments

Andrew MacLeod May 6, 2026, 2:14 p.m. UTC | #1
On 5/6/26 10:10, David Malcolm wrote:
> This patch adds value_range info where available to the various nodes
> in svalue dumps, such as:
>
> (gdb) call rhs2_sval->dump ()
> (27): ‘long long unsigned int’: binop_svalue(bit_and_expr: ‘&’) value range: {[irange] long long unsigned int [0, 0]}
> ├─ (24): ‘long long unsigned int’: unaryop_svalue(nop_expr) value range: {[irange] long long unsigned int [0, 4294967295] MASK 0xffffffff VALUE 0x0}
> │  ╰─ (22): ‘unsigned int’: initial_svalue value range: {[irange] unsigned int VARYING}
> │     ╰─ m_reg: (21): ‘unsigned int’: decl_region(‘m’)
> │        ╰─ parent: (4): globals
> │           ╰─ parent: (0): root region
> ╰─ (26): ‘long long unsigned int’: constant_svalue (‘5497558138880’) value range: {[irange] long long unsigned int [5497558138880, 5497558138880]}
>
> where we can see that sval 27 has value range [0,0] and
> where that comes from (due to being a bit_and_expr of non-overlapping
> ranges from sval 24 and 26).
>
> Successfully bootstrapped & regrtested on aarch64-unknown-linux-gnu.
>
> Andrew: are the value-range parts OK for trunk?

OK.

Andrew
  

Patch

diff --git a/gcc/analyzer/svalue.cc b/gcc/analyzer/svalue.cc
index fe22ae73ddd..1c0041ab75b 100644
--- a/gcc/analyzer/svalue.cc
+++ b/gcc/analyzer/svalue.cc
@@ -227,6 +227,14 @@  svalue::make_dump_widget (const text_art::dump_widget_info &dwi,
 
   print_dump_widget_label (&pp);
 
+  value_range out;
+  if (maybe_get_value_range (out))
+    {
+      pp_printf (&pp, " value range: {"),
+	out.print (&pp);
+      pp_string (&pp, "}");
+    }
+
   std::unique_ptr<text_art::tree_widget> w
     (text_art::tree_widget::make (dwi, &pp));
 
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 657afa0acaa..a1e5c805057 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -157,6 +157,18 @@  value_range::dump (FILE *out) const
     fprintf (out, "NULL");
 }
 
+void
+value_range::print (pretty_printer *pp) const
+{
+  if (m_vrange)
+    {
+      vrange_printer vrange_pp (pp);
+      m_vrange->accept (vrange_pp);
+    }
+  else
+    pp_string (pp, "NULL");
+}
+
 DEBUG_FUNCTION void
 debug (const value_range &r)
 {
diff --git a/gcc/value-range.h b/gcc/value-range.h
index eaf29236d99..85deebab092 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -792,6 +792,7 @@  public:
   operator vrange &();
   operator const vrange &() const;
   void dump (FILE *) const;
+  void print (pretty_printer *) const;
   static bool supports_type_p (const_tree type);
 
   tree type () { return m_vrange->type (); }