Currently, the analyzer tries to prove that the allocation size is a
multiple of the pointee's type size. This patch reverses the behavior
to try to prove that the expression is not a multiple of the pointee's
type size. With this change, each unhandled case should be gracefully
considered as correct. This fixes the bug reported in PR 109577 by
Paul Eggert.
Regression-tested on Linux x86-64 with -m32 and -m64.
2023-06-09 Tim Lange
PR analyzer/109577
gcc/analyzer/ChangeLog:
* constraint-manager.cc (class sval_finder): Visitor to find
childs in svalue trees.
(constraint_manager::sval_constrained_p): Add new function to
check whether a sval might be part of an constraint.
* constraint-manager.h: Add sval_constrained_p function.
* region-model.cc (class size_visitor): Reverse behavior to not
emit a warning on not explicitly considered cases.
(region_model::check_region_size):
Adapt to size_visitor changes.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/allocation-size-2.c: Change expected output
and add new test case.
* gcc.dg/analyzer/pr109577.c: New test.
---
gcc/analyzer/constraint-manager.cc| 131 ++
gcc/analyzer/constraint-manager.h | 1 +
gcc/analyzer/region-model.cc | 80 ---
.../gcc.dg/analyzer/allocation-size-2.c | 24 ++--
gcc/testsuite/gcc.dg/analyzer/pr109577.c | 16 +++
5 files changed, 194 insertions(+), 58 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr109577.c
diff --git a/gcc/analyzer/constraint-manager.cc
b/gcc/analyzer/constraint-manager.cc
index 2c9c435527e..24cd8960098 100644
--- a/gcc/analyzer/constraint-manager.cc
+++ b/gcc/analyzer/constraint-manager.cc
@@ -2218,6 +2218,137 @@ constraint_manager::get_equiv_class_by_svalue (const
svalue *sval,
return false;
}
+/* Tries to find a svalue inside another svalue. */
+
+class sval_finder : public visitor
+{
+public:
+ sval_finder (const svalue *query) : m_query (query)
+ {
+ }
+
+ bool found_query_p ()
+ {
+return m_found;
+ }
+
+ void visit_region_svalue (const region_svalue *sval)
+ {
+m_found |= m_query == sval;
+ }
+
+ void visit_constant_svalue (const constant_svalue *sval)
+ {
+m_found |= m_query == sval;
+ }
+
+ void visit_unknown_svalue (const unknown_svalue *sval)
+ {
+m_found |= m_query == sval;
+ }
+
+ void visit_poisoned_svalue (const poisoned_svalue *sval)
+ {
+m_found |= m_query == sval;
+ }
+
+ void visit_setjmp_svalue (const setjmp_svalue *sval)
+ {
+m_found |= m_query == sval;
+ }
+
+ void visit_initial_svalue (const initial_svalue *sval)
+ {
+m_found |= m_query == sval;
+ }
+
+ void visit_unaryop_svalue (const unaryop_svalue *sval)
+ {
+m_found |= m_query == sval;
+ }
+
+ void visit_binop_svalue (const binop_svalue *sval)
+ {
+m_found |= m_query == sval;
+ }
+
+ void visit_sub_svalue (const sub_svalue *sval)
+ {
+m_found |= m_query == sval;
+ }
+
+ void visit_repeated_svalue (const repeated_svalue *sval)
+ {
+m_found |= m_query == sval;
+ }
+
+ void visit_bits_within_svalue (const bits_within_svalue *sval)
+ {
+m_found |= m_query == sval;
+ }
+
+ void visit_unmergeable_svalue (const unmergeable_svalue *sval)
+ {
+m_found |= m_query == sval;
+ }
+
+ void visit_placeholder_svalue (const placeholder_svalue *sval)
+ {
+m_found |= m_query == sval;
+ }
+
+ void visit_widening_svalue (const widening_svalue *sval)
+ {
+m_found |= m_query == sval;
+ }
+
+ void visit_compound_svalue (const compound_svalue *sval)
+ {
+m_found |= m_query == sval;
+ }
+
+ void visit_conjured_svalue (const conjured_svalue *sval)
+ {
+m_found |= m_query == sval;
+ }
+
+ void visit_asm_output_svalue (const asm_output_svalue *sval)
+ {
+m_found |= m_query == sval;
+ }
+
+ void visit_const_fn_result_svalue (const const_fn_result_svalue *sval)
+ {
+m_found |= m_query == sval;
+ }
+
+private:
+ const svalue *m_query;
+ bool m_found;
+};
+
+/* Returns true if SVAL is constrained. */
+
+bool
+constraint_manager::sval_constrained_p (const svalue *sval) const
+{
+ int i;
+ equiv_class *ec;
+ sval_finder finder (sval);
+ FOR_EACH_VEC_ELT (m_equiv_classes, i, ec)
+{
+ int j;
+ const svalue *iv;
+ FOR_EACH_VEC_ELT (ec->m_vars, j, iv)
+ {
+ iv->accept ();
+ if (finder.found_query_p ())
+ return true;
+ }
+}
+ return false;
+}
+
/* Ensure that SVAL has an equivalence class within this constraint_manager;
return the ID of the class. */
diff --git a/gcc/analyzer/constraint-manager.h
b/gcc/analyzer/constraint-manager.h
index 3afbc7f848e..72753e43c96 100644
--- a/gcc/analyzer/constraint-manager.h
+++ b/gcc/analyzer/constraint-manager.h
@@ -459,6 +459,7 @@ public:
bool get_equiv_class_by_svalue (const svalue *sval,