diff options
author | David Malcolm <dmalcolm@redhat.com> | 2023-03-22 08:40:34 -0400 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2023-03-22 08:40:34 -0400 |
commit | 0c652ebbf79bd168766097f3ac4c1b3b79d68a43 (patch) | |
tree | 820aef7492def9c7de3fc8740cb0606222aa4e39 /gcc/analyzer | |
parent | 1bde3acee77c171117dfb988998daa8197c73b34 (diff) | |
download | gcc-0c652ebbf79bd168766097f3ac4c1b3b79d68a43.zip gcc-0c652ebbf79bd168766097f3ac4c1b3b79d68a43.tar.gz gcc-0c652ebbf79bd168766097f3ac4c1b3b79d68a43.tar.bz2 |
analyzer: fix false +ves from -Wanalyzer-deref-before-check due to inlining [PR109239]
The patch has this effect on my integration tests of -fanalyzer:
Comparison:
GOOD: 129 (17.70% -> 17.92%)
BAD: 600 -> 591 (-9)
which is purely due to improvements to -Wanalyzer-deref-before-check
on the Linux kernel:
-Wanalyzer-deref-before-check:
GOOD: 1 (4.55% -> 7.69%)
BAD: 21 -> 12 (-9)
Known false positives: 16 -> 10 (-6)
linux-5.10.162: 7 -> 1 (-6)
Suspected false positives: 3 -> 0 (-3)
linux-5.10.162: 3 -> 0 (-3)
gcc/analyzer/ChangeLog:
PR analyzer/109239
* program-point.cc: Include "analyzer/inlining-iterator.h".
(program_point::effectively_intraprocedural_p): New function.
* program-point.h (program_point::effectively_intraprocedural_p):
New decl.
* sm-malloc.cc (deref_before_check::emit): Use it when rejecting
interprocedural cases, so that we reject interprocedural cases
that have become intraprocedural due to inlining.
gcc/testsuite/ChangeLog:
PR analyzer/109239
* gcc.dg/analyzer/deref-before-check-pr109239-linux-bus.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc/analyzer')
-rw-r--r-- | gcc/analyzer/program-point.cc | 42 | ||||
-rw-r--r-- | gcc/analyzer/program-point.h | 3 | ||||
-rw-r--r-- | gcc/analyzer/sm-malloc.cc | 9 |
3 files changed, 50 insertions, 4 deletions
diff --git a/gcc/analyzer/program-point.cc b/gcc/analyzer/program-point.cc index 0ab55fa..f2d6490 100644 --- a/gcc/analyzer/program-point.cc +++ b/gcc/analyzer/program-point.cc @@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see #include "shortest-paths.h" #include "analyzer/exploded-graph.h" #include "analyzer/analysis-plan.h" +#include "analyzer/inlining-iterator.h" #if ENABLE_ANALYZER @@ -719,6 +720,47 @@ program_point::get_next () const } } +/* Return true iff POINT_A and POINT_B share the same function and + call_string, both directly, and when attempting to undo inlining + information. */ + +bool +program_point::effectively_intraprocedural_p (const program_point &point_a, + const program_point &point_b) +{ + /* First, compare without considering inlining info. */ + if (point_a.get_function () + != point_b.get_function ()) + return false; + if (&point_a.get_call_string () + != &point_b.get_call_string ()) + return false; + + /* Consider inlining info; they must have originally come from + the same function and have been inlined in the same way. */ + location_t loc_a = point_a.get_location (); + location_t loc_b = point_b.get_location (); + inlining_iterator iter_a (loc_a); + inlining_iterator iter_b (loc_b); + while (!(iter_a.done_p () || iter_b.done_p ())) + { + if (iter_a.done_p () || iter_b.done_p ()) + return false; + + if (iter_a.get_fndecl () != iter_b.get_fndecl ()) + return false; + if (iter_a.get_callsite () != iter_b.get_callsite ()) + return false; + if (iter_a.get_block () != iter_b.get_block ()) + return false; + + iter_a.next (); + iter_b.next (); + } + + return true; +} + #if CHECKING_P namespace selftest { diff --git a/gcc/analyzer/program-point.h b/gcc/analyzer/program-point.h index d1f8480..7df3b69 100644 --- a/gcc/analyzer/program-point.h +++ b/gcc/analyzer/program-point.h @@ -299,6 +299,9 @@ public: program_point get_next () const; + static bool effectively_intraprocedural_p (const program_point &point_a, + const program_point &point_b); + private: program_point (const function_point &fn_point) : m_function_point (fn_point), diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc index 16883d3..7470137 100644 --- a/gcc/analyzer/sm-malloc.cc +++ b/gcc/analyzer/sm-malloc.cc @@ -1520,10 +1520,11 @@ public: if (!m_check_enode) return false; /* Only emit the warning for intraprocedural cases. */ - if (m_deref_enode->get_function () != m_check_enode->get_function ()) - return false; - if (&m_deref_enode->get_point ().get_call_string () - != &m_check_enode->get_point ().get_call_string ()) + const program_point &deref_point = m_deref_enode->get_point (); + const program_point &check_point = m_check_enode->get_point (); + + if (!program_point::effectively_intraprocedural_p (deref_point, + check_point)) return false; /* Reject the warning if the check occurs within a macro defintion. |