From c7cc58e87775ac6b4733f25b88f954463d567531 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Tue, 21 Jul 2020 17:30:28 -0400 Subject: [PATCH 315/315] FIXME: rework null_assignment_sm_context to work on every stmt in enode, not just first --- gcc/analyzer/diagnostic-manager.cc | 58 ++++++++++++++---------- gcc/analyzer/program-point.cc | 13 ++++++ gcc/analyzer/program-point.h | 8 +++- gcc/testsuite/gcc.dg/analyzer/malloc-1.c | 13 ++++++ 4 files changed, 67 insertions(+), 25 deletions(-) diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc index 28924d493dd..dadbfc1aaf5 100644 --- a/gcc/analyzer/diagnostic-manager.cc +++ b/gcc/analyzer/diagnostic-manager.cc @@ -1035,12 +1035,11 @@ struct null_assignment_sm_context : public sm_context { null_assignment_sm_context (int sm_idx, const state_machine &sm, - const program_state *old_state, const program_state *new_state, const gimple *stmt, const program_point *point, checker_path *emission_path) - : sm_context (sm_idx, sm), m_old_state (old_state), m_new_state (new_state), + : sm_context (sm_idx, sm), m_new_state (new_state), m_stmt (stmt), m_point (point), m_emission_path (emission_path) { } @@ -1060,8 +1059,6 @@ struct null_assignment_sm_context : public sm_context if (from != 0) return; - const svalue2 *var_old_sval - = m_old_state->m_region_model2->get_rvalue (var, NULL); const svalue2 *var_new_sval = m_new_state->m_region_model2->get_rvalue (var, NULL); const supernode *supernode = m_point->get_supernode (); @@ -1117,7 +1114,6 @@ struct null_assignment_sm_context : public sm_context return NULL_TREE; } - const program_state *m_old_state; const program_state *m_new_state; const program_point *m_point; state_change_visitor2 *m_visitor; @@ -1224,25 +1220,39 @@ diagnostic_manager::add_events_for_eedge (const path_builder &pb, dst_point.get_fndecl (), dst_stack_depth, dst_state)); - /* Create state change events for assignment to NULL. */ - if (stmt->code == GIMPLE_ASSIGN) - { - const extrinsic_state &ext_state = pb.get_ext_state (); - for (unsigned i = 0; i < ext_state.get_num_checkers (); i++) - { - const state_machine &sm = ext_state.get_sm (i); - program_state state_after_stmt (dst_state); - state_after_stmt.m_region_model2->on_stmt (stmt, NULL); - null_assignment_sm_context sm_ctxt (i, sm, - &dst_state, - &state_after_stmt, - stmt, - &dst_point, emission_path); - sm.on_stmt (&sm_ctxt, dst_point.get_supernode (), stmt); - // TODO: what if it isn't the first stmt in the enode? - // TODO: what about phi nodes? - } - } + /* Create state change events for assignment to NULL. + Iterate through the stmts in dst_enode, adding state change + events for them. */ + { + program_state iter_state (dst_state); + program_point iter_point (dst_point); + while (1) + { + const gimple *stmt = iter_point.get_stmt (); + if (stmt->code == GIMPLE_ASSIGN) + { + const extrinsic_state &ext_state = pb.get_ext_state (); + iter_state.m_region_model2->on_stmt (stmt, NULL); + for (unsigned i = 0; i < ext_state.get_num_checkers (); i++) + { + const state_machine &sm = ext_state.get_sm (i); + null_assignment_sm_context sm_ctxt (i, sm, + &iter_state, + stmt, + &iter_point, + emission_path); + sm.on_stmt (&sm_ctxt, dst_point.get_supernode (), stmt); + // TODO: what about phi nodes? + } + } + iter_point.next_stmt (); + if (iter_point.get_kind () == PK_AFTER_SUPERNODE + || (dst_node->m_succs.length () > 1 + && (iter_point + == dst_node->m_succs[0]->m_dest->get_point ()))) + break; + } + } } break; } diff --git a/gcc/analyzer/program-point.cc b/gcc/analyzer/program-point.cc index a07f236fd71..e4893424f4d 100644 --- a/gcc/analyzer/program-point.cc +++ b/gcc/analyzer/program-point.cc @@ -538,6 +538,19 @@ function_point::cmp_within_supernode (const function_point &point_a, return result; } +/* For PK_BEFORE_STMT, go to next stmt (or to PK_AFTER_SUPERNODE). */ + +void +function_point::next_stmt () +{ + gcc_assert (m_kind == PK_BEFORE_STMT); + if (++m_stmt_idx == m_supernode->m_stmts.length ()) + { + m_kind = PK_AFTER_SUPERNODE; + m_stmt_idx = 0; + } +} + #if CHECKING_P namespace selftest { diff --git a/gcc/analyzer/program-point.h b/gcc/analyzer/program-point.h index 8a9fd019260..23e8a0b91b0 100644 --- a/gcc/analyzer/program-point.h +++ b/gcc/analyzer/program-point.h @@ -146,6 +146,9 @@ public: static int cmp_within_supernode (const function_point &point_a, const function_point &point_b); + /* For before_stmt, go to next stmt. */ + void next_stmt (); + private: const supernode *m_supernode; @@ -292,8 +295,11 @@ public: void validate () const; + /* For before_stmt, go to next stmt. */ + void next_stmt () { m_function_point.next_stmt (); } + private: - const function_point m_function_point; + function_point m_function_point; call_string m_call_string; }; diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c index 27491428cd6..48766238d8b 100644 --- a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c @@ -586,3 +586,16 @@ void test_48 (void) int *p = NULL; /* { dg-message "'p' is NULL" } */ *p = 1; /* { dg-warning "dereference of NULL 'p'" } */ } + +/* As test_48, but where the assignment of NULL is not at the start of a BB. */ + +int test_49 (int i) +{ + int *p; + int x; + + x = i * 2; + p = NULL; /* { dg-message "'p' is NULL" } */ + *p = 1; /* { dg-warning "dereference of NULL 'p'" } */ + return x; +} -- 2.26.2