From 7fc972b6a4eb6e62a6b350c38031dc4369aeb7e4 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Mon, 2 Feb 2026 22:23:52 -0500 Subject: [PATCH] FIXME: WIP use of value_range in analyzer (PR analyzer/98447) --- gcc/analyzer/common.h | 1 + gcc/analyzer/region-model.cc | 25 +++++++++++ gcc/analyzer/svalue.cc | 45 +++++++++++++++++++ gcc/analyzer/svalue.h | 7 +++ .../analyzer/conditionals-pr98447.c | 6 +++ 5 files changed, 84 insertions(+) create mode 100644 gcc/testsuite/c-c++-common/analyzer/conditionals-pr98447.c diff --git a/gcc/analyzer/common.h b/gcc/analyzer/common.h index 27ca49ee1c81..cbe36dfb9c99 100644 --- a/gcc/analyzer/common.h +++ b/gcc/analyzer/common.h @@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "json.h" #include "tristate.h" +#include "value-range.h" class graphviz_out; diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index 1efb19b07761..44510195d762 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -46,6 +46,8 @@ along with GCC; see the file COPYING3. If not see #include "selftest-tree.h" #include "context.h" #include "channels.h" +#include "value-relation.h" +#include "range-op.h" #include "text-art/tree-widget.h" @@ -5381,6 +5383,27 @@ region_model::eval_condition (const svalue *lhs, } } + /* Try ranger. */ + { + value_range lhs_vr, rhs_vr; + if (lhs->maybe_get_value_range (lhs_vr)) + if (rhs->maybe_get_value_range (rhs_vr)) + { + range_op_handler handler (op); + if (handler) + { + value_range out (boolean_type_node); + if (handler.fold_range (out, boolean_type_node, lhs_vr, rhs_vr)) + { + if (out.zero_p ()) + return tristate::TS_FALSE; + if (out.nonzero_p ()) + return tristate::TS_TRUE; + } + } + } + } + /* Otherwise, try constraints. Cast to const to ensure we don't change the constraint_manager as we do this (e.g. by creating equivalence classes). */ @@ -5620,6 +5643,7 @@ region_model::add_constraints_from_binop (const svalue *outer_lhs, then both inner_lhs and inner_rhs must be true. */ const svalue *false_sval = m_mgr->get_or_create_constant_svalue (boolean_false_node); + // FIXME: ^^^^ need to use same type as inner_lhs bool sat1 = add_constraint (inner_lhs, NE_EXPR, false_sval, ctxt); bool sat2 = add_constraint (inner_rhs, NE_EXPR, false_sval, ctxt); *out = sat1 && sat2; @@ -5635,6 +5659,7 @@ region_model::add_constraints_from_binop (const svalue *outer_lhs, then both inner_lhs and inner_rhs must be false. */ const svalue *false_sval = m_mgr->get_or_create_constant_svalue (boolean_false_node); + // FIXME: ^^^^ need to use same type as inner_lhs bool sat1 = add_constraint (inner_lhs, EQ_EXPR, false_sval, ctxt); bool sat2 = add_constraint (inner_rhs, EQ_EXPR, false_sval, ctxt); *out = sat1 && sat2; diff --git a/gcc/analyzer/svalue.cc b/gcc/analyzer/svalue.cc index 0b3ef6e5f050..366e13e859a7 100644 --- a/gcc/analyzer/svalue.cc +++ b/gcc/analyzer/svalue.cc @@ -25,6 +25,8 @@ along with GCC; see the file COPYING3. If not see #include "fold-const.h" #include "diagnostic.h" #include "tree-diagnostic.h" +#include "value-relation.h" +#include "range-op.h" #include "text-art/dump.h" @@ -880,6 +882,22 @@ svalue::maybe_get_type_from_typeinfo () const return NULL_TREE; } +bool +svalue::maybe_get_value_range (value_range &out) const +{ + tree type = get_type (); + if (!type) + return false; + + if (!INTEGRAL_TYPE_P (type)) + return false; + + out = value_range (TYPE_MIN_VALUE (type), + TYPE_MAX_VALUE (type), + VR_RANGE); + return true; +} + /* class region_svalue : public svalue. */ /* Implementation of svalue::dump_to_pp vfunc for region_svalue. */ @@ -1165,6 +1183,15 @@ constant_svalue::all_zeroes_p () const return zerop (m_cst_expr); } +bool +constant_svalue::maybe_get_value_range (value_range &out) const +{ + if (!get_type ()) + return false; + out = value_range (m_cst_expr, m_cst_expr, VR_RANGE); + return true; +} + /* class unknown_svalue : public svalue. */ /* Implementation of svalue::dump_to_pp vfunc for unknown_svalue. */ @@ -1634,6 +1661,24 @@ sub_svalue::sub_svalue (symbol::id_t id, gcc_assert (parent_svalue->can_have_associated_state_p ()); } +bool +binop_svalue::maybe_get_value_range (value_range &out) const +{ + value_range lhs, rhs; + if (m_arg0->maybe_get_value_range (lhs)) + if (m_arg1->maybe_get_value_range (rhs)) + { + range_op_handler handler (m_op); + if (handler) + { + out = value_range (get_type ()); + if (handler.fold_range (out, get_type (), lhs, rhs)) + return true; + } + } + return false; +} + /* Implementation of svalue::dump_to_pp vfunc for sub_svalue. */ void diff --git a/gcc/analyzer/svalue.h b/gcc/analyzer/svalue.h index 5025d966f8f0..6faa473e865d 100644 --- a/gcc/analyzer/svalue.h +++ b/gcc/analyzer/svalue.h @@ -190,6 +190,9 @@ public: tree maybe_get_type_from_typeinfo () const; + // FIXME: + virtual bool maybe_get_value_range (value_range &out) const; + protected: svalue (complexity c, symbol::id_t id, tree type) : symbol (c, id), m_type (type) @@ -366,6 +369,8 @@ public: bool all_zeroes_p () const final override; + bool maybe_get_value_range (value_range &out) const final override; + private: tree m_cst_expr; }; @@ -859,6 +864,8 @@ public: bool implicitly_live_p (const svalue_set *, const region_model *) const final override; + bool maybe_get_value_range (value_range &out) const final override; + enum tree_code get_op () const { return m_op; } const svalue *get_arg0 () const { return m_arg0; } const svalue *get_arg1 () const { return m_arg1; } diff --git a/gcc/testsuite/c-c++-common/analyzer/conditionals-pr98447.c b/gcc/testsuite/c-c++-common/analyzer/conditionals-pr98447.c new file mode 100644 index 000000000000..9a7107a26051 --- /dev/null +++ b/gcc/testsuite/c-c++-common/analyzer/conditionals-pr98447.c @@ -0,0 +1,6 @@ +#include "analyzer-decls.h" + +void test_1 (int i) +{ + __analyzer_eval (64 <= (i % 64)); /* { dg-warning "FALSE" } */ +} -- 2.26.3