diff options
author | David Malcolm <dmalcolm@redhat.com> | 2019-12-20 10:56:28 -0500 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2020-01-14 20:44:33 -0500 |
commit | 8397af8ed0db685312e44117fd52316b57c2c129 (patch) | |
tree | bc5012254244c350b835ad1e32593ff126bbb1c6 /gcc | |
parent | 03dc3f26231cbf5733330028e14706f8ad77fd5a (diff) | |
download | gcc-8397af8ed0db685312e44117fd52316b57c2c129.zip gcc-8397af8ed0db685312e44117fd52316b57c2c129.tar.gz gcc-8397af8ed0db685312e44117fd52316b57c2c129.tar.bz2 |
analyzer: fix tests for UNKNOWN_LOCATION
In the reproducer for PR analyzer/58237 I noticed that some events were
missing locations (and text); for example event 3 here:
| 15 | while (fgets(buf, 10, fp) != NULL)
| | ~
| | |
| | (2) following 'false' branch...
|
'f1': event 3
|
|cc1:
|
'f1': event 4
|
|<source>:19:1:
| 19 | }
| | ^
| | |
| | (4) 'fp' leaks here; was opened at (1)
|
The root cause is that various places in the analyzer compare locations
against UNKNOWN_LOCATION, which fails to detect an unknown location for
the case where an unknown_location has been wrapped into an ad-hoc
location to record a block.
This patch fixes the issue by using get_pure_location whenever testing
against UNKNOWN_LOCATION to look through ad-hoc wrappers.
For the case above, it thus picks a better location in
supernode::get_start_location for event (3) above, improving it to:
| 15 | while (fgets(buf, 10, fp) != NULL)
| | ~
| | |
| | (2) following 'false' branch...
|......
| 19 | }
| | ~
| | |
| | (3) ...to here
| | (4) 'fp' leaks here; was opened at (1)
|
gcc/analyzer/ChangeLog:
PR analyzer/58237
* engine.cc (leak_stmt_finder::find_stmt): Use get_pure_location
when comparing against UNKNOWN_LOCATION.
(stmt_requires_new_enode_p): Likewise.
(exploded_graph::dump_exploded_nodes): Likewise.
* supergraph.cc (supernode::get_start_location): Likewise.
(supernode::get_end_location): Likewise.
gcc/testsuite/ChangeLog:
PR analyzer/58237
* gcc.dg/analyzer/file-paths-1.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/analyzer/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/analyzer/engine.cc | 8 | ||||
-rw-r--r-- | gcc/analyzer/supergraph.cc | 10 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/analyzer/file-paths-1.c | 25 |
5 files changed, 50 insertions, 8 deletions
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog index aad8528..2f91cd1 100644 --- a/gcc/analyzer/ChangeLog +++ b/gcc/analyzer/ChangeLog @@ -1,6 +1,16 @@ 2020-01-14 David Malcolm <dmalcolm@redhat.com> PR analyzer/58237 + * engine.cc (leak_stmt_finder::find_stmt): Use get_pure_location + when comparing against UNKNOWN_LOCATION. + (stmt_requires_new_enode_p): Likewise. + (exploded_graph::dump_exploded_nodes): Likewise. + * supergraph.cc (supernode::get_start_location): Likewise. + (supernode::get_end_location): Likewise. + +2020-01-14 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/58237 * analyzer-selftests.cc (selftest::run_analyzer_selftests): Call selftest::analyzer_sm_file_cc_tests. * analyzer-selftests.h (selftest::analyzer_sm_file_cc_tests): New diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index 573f9f6..9092024 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -417,7 +417,7 @@ public: const program_point &dst_point = dst_node->get_point (); const gimple *stmt = dst_point.get_stmt (); if (stmt) - if (stmt->location != UNKNOWN_LOCATION) + if (get_pure_location (stmt->location) != UNKNOWN_LOCATION) return stmt; } @@ -2300,8 +2300,8 @@ stmt_requires_new_enode_p (const gimple *stmt, could be consolidated into PREV_STMT, giving us an event with no location. Ensure that STMT gets its own exploded_node to avoid this. */ - if (prev_stmt->location == UNKNOWN_LOCATION - && stmt->location != UNKNOWN_LOCATION) + if (get_pure_location (prev_stmt->location) == UNKNOWN_LOCATION + && get_pure_location (stmt->location) != UNKNOWN_LOCATION) return true; return false; @@ -3098,7 +3098,7 @@ exploded_graph::dump_exploded_nodes () const { if (const gimple *stmt = enode->get_stmt ()) { - if (richloc.get_loc () == UNKNOWN_LOCATION) + if (get_pure_location (richloc.get_loc ()) == UNKNOWN_LOCATION) richloc.set_range (0, stmt->location, SHOW_RANGE_WITH_CARET); else richloc.add_range (stmt->location, diff --git a/gcc/analyzer/supergraph.cc b/gcc/analyzer/supergraph.cc index 24f83c9..fd905ea 100644 --- a/gcc/analyzer/supergraph.cc +++ b/gcc/analyzer/supergraph.cc @@ -531,13 +531,14 @@ supernode::dump_dot_id (pretty_printer *pp) const location_t supernode::get_start_location () const { - if (m_returning_call && m_returning_call->location != UNKNOWN_LOCATION) + if (m_returning_call + && get_pure_location (m_returning_call->location) != UNKNOWN_LOCATION) return m_returning_call->location; int i; gimple *stmt; FOR_EACH_VEC_ELT (m_stmts, i, stmt) - if (stmt->location != UNKNOWN_LOCATION) + if (get_pure_location (stmt->location) != UNKNOWN_LOCATION) return stmt->location; if (entry_p ()) @@ -561,10 +562,11 @@ supernode::get_end_location () const int i; gimple *stmt; FOR_EACH_VEC_ELT_REVERSE (m_stmts, i, stmt) - if (stmt->location != UNKNOWN_LOCATION) + if (get_pure_location (stmt->location) != UNKNOWN_LOCATION) return stmt->location; - if (m_returning_call && m_returning_call->location != UNKNOWN_LOCATION) + if (m_returning_call + && get_pure_location (m_returning_call->location) != UNKNOWN_LOCATION) return m_returning_call->location; if (entry_p ()) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 18c6a88..ac0cd2d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,6 +1,11 @@ 2020-01-14 David Malcolm <dmalcolm@redhat.com> PR analyzer/58237 + * gcc.dg/analyzer/file-paths-1.c: New test. + +2020-01-14 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/58237 * gcc.dg/analyzer/file-1.c (test_4): New. * gcc.dg/analyzer/file-pr58237.c: New test. diff --git a/gcc/testsuite/gcc.dg/analyzer/file-paths-1.c b/gcc/testsuite/gcc.dg/analyzer/file-paths-1.c new file mode 100644 index 0000000..1c8bf61 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/file-paths-1.c @@ -0,0 +1,25 @@ +#include <stdio.h> + +/* Verify that we correctly emit CFG events in the face of buffers + being clobbered in these leak reports. */ + +void f1 (const char *str) +{ + FILE * fp = fopen(str, "r"); /* { dg-message "opened here" } */ + char buf[10]; + + while (fgets(buf, 10, fp) != NULL) /* { dg-message "following 'false' branch\\.\\.\\." } */ + { + } +} /* { dg-warning "leak of FILE 'fp'" } */ +/* { dg-message "\\.\\.\\.to here" "" { target *-*-* } .-1 } */ + +void f2(const char *str, int flag) +{ + FILE * fp = fopen(str, "r"); /* { dg-message "opened here" } */ + char buf[10]; + + if (flag) /* { dg-message "when 'flag == 0'" } */ + fclose(fp); +} /* { dg-warning "leak of FILE 'fp'" } */ +/* { dg-message "\\.\\.\\.to here" "" { target *-*-* } .-1 } */ |