aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2023-03-22 08:40:34 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2023-03-22 08:40:34 -0400
commit0c652ebbf79bd168766097f3ac4c1b3b79d68a43 (patch)
tree820aef7492def9c7de3fc8740cb0606222aa4e39 /gcc/analyzer
parent1bde3acee77c171117dfb988998daa8197c73b34 (diff)
downloadgcc-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.cc42
-rw-r--r--gcc/analyzer/program-point.h3
-rw-r--r--gcc/analyzer/sm-malloc.cc9
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.