Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. Pushed to trunk as r16-261-g6f9764571d2dd1.
gcc/analyzer/ChangeLog: * engine.cc (class plugin_analyzer_init_impl): Convert "m_checkers" to use std::vector of std::unique_ptr. Convert "m_known_fn_mgr" to a reference. (impl_run_checkers): Convert "checkers" to use std::vector of std::unique_ptr and move it into the extrinsic_state. * program-state.cc (extrinsic_state::dump_to_pp): Update for changes to m_checkers. (extrinsic_state::to_json): Likewise. (extrinsic_state::get_sm_idx_by_name): Likewise. (selftest::test_sm_state_map): Update to use std::unique_ptr for state machines. (selftest::test_program_state_1): Likewise. (selftest::test_program_state_2): Likewise. (selftest::test_program_state_merging): Likewise. (selftest::test_program_state_merging_2): Likewise. * program-state.h (class extrinsic_state): Convert "m_checkers" to use std::vector of std::unique_ptr and to be owned by this object, rather than a reference. Add ctor for use in selftests. * sm-fd.cc (make_fd_state_machine): Update to use std::unique_ptr. * sm-file.cc (make_fileptr_state_machine): Likewise. * sm-malloc.cc (make_malloc_state_machine): Likewise. * sm-pattern-test.cc (make_pattern_test_state_machine): Likewise. * sm-sensitive.cc (make_sensitive_state_machine): Likewise. * sm-signal.cc (make_signal_state_machine): Likewise. * sm-taint.cc (make_taint_state_machine): Likewise. * sm.cc: Define INCLUDE_LIST. (make_checkers): Return the vector directly, rather than pass it in by reference. Update to use std::unique_ptr throughout. Use an intermediate list, and use that to filter with flag_analyzer_checker, fixing memory leak for this case. * sm.h: (make_checkers): Return the vector directly, rather than pass it in by reference, and use std::vector of std::unique_ptr. (make_malloc_state_machine): Convert return type to use std::unique_ptr. (make_fileptr_state_machine): Likewise. (make_taint_state_machine): Likewise. (make_sensitive_state_machine): Likewise. (make_signal_state_machine): Likewise. (make_pattern_test_state_machine): Likewise. (make_va_list_state_machine): Likewise. (make_fd_state_machine): Likewise. * varargs.cc (make_va_list_state_machine): Update to use std::unique_ptr. Signed-off-by: David Malcolm <dmalc...@redhat.com> --- gcc/analyzer/engine.cc | 28 +++++++-------- gcc/analyzer/program-state.cc | 63 ++++++++++++++------------------- gcc/analyzer/program-state.h | 20 ++++++++--- gcc/analyzer/sm-fd.cc | 4 +-- gcc/analyzer/sm-file.cc | 4 +-- gcc/analyzer/sm-malloc.cc | 4 +-- gcc/analyzer/sm-pattern-test.cc | 4 +-- gcc/analyzer/sm-sensitive.cc | 4 +-- gcc/analyzer/sm-signal.cc | 4 +-- gcc/analyzer/sm-taint.cc | 4 +-- gcc/analyzer/sm.cc | 44 +++++++++++++---------- gcc/analyzer/sm.h | 22 ++++++------ gcc/analyzer/varargs.cc | 4 +-- 13 files changed, 108 insertions(+), 101 deletions(-) diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index f33cc0bda4d..c04bda1e645 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -6103,8 +6103,8 @@ dump_analyzer_json (const supergraph &sg, class plugin_analyzer_init_impl : public plugin_analyzer_init_iface { public: - plugin_analyzer_init_impl (auto_delete_vec <state_machine> *checkers, - known_function_manager *known_fn_mgr, + plugin_analyzer_init_impl (std::vector<std::unique_ptr<state_machine>> &checkers, + known_function_manager &known_fn_mgr, logger *logger) : m_checkers (checkers), m_known_fn_mgr (known_fn_mgr), @@ -6114,14 +6114,14 @@ public: void register_state_machine (std::unique_ptr<state_machine> sm) final override { LOG_SCOPE (m_logger); - m_checkers->safe_push (sm.release ()); + m_checkers.push_back (std::move (sm)); } void register_known_function (const char *name, std::unique_ptr<known_function> kf) final override { LOG_SCOPE (m_logger); - m_known_fn_mgr->add (name, std::move (kf)); + m_known_fn_mgr.add (name, std::move (kf)); } logger *get_logger () const final override @@ -6130,8 +6130,8 @@ public: } private: - auto_delete_vec <state_machine> *m_checkers; - known_function_manager *m_known_fn_mgr; + std::vector<std::unique_ptr<state_machine>> &m_checkers; + known_function_manager &m_known_fn_mgr; logger *m_logger; }; @@ -6185,27 +6185,25 @@ impl_run_checkers (logger *logger) free (filename); } - auto_delete_vec <state_machine> checkers; - make_checkers (checkers, logger); + auto checkers = make_checkers (logger); register_known_functions (*eng.get_known_function_manager (), *eng.get_model_manager ()); - plugin_analyzer_init_impl data (&checkers, - eng.get_known_function_manager (), + plugin_analyzer_init_impl data (checkers, + *eng.get_known_function_manager (), logger); invoke_plugin_callbacks (PLUGIN_ANALYZER_INIT, &data); if (logger) { - int i; - state_machine *sm; - FOR_EACH_VEC_ELT (checkers, i, sm) - logger->log ("checkers[%i]: %s", i, sm->get_name ()); + int i = 0; + for (auto &sm : checkers) + logger->log ("checkers[%i]: %s", ++i, sm->get_name ()); } /* Extrinsic state shared by nodes in the graph. */ - const extrinsic_state ext_state (checkers, &eng, logger); + const extrinsic_state ext_state (std::move (checkers), &eng, logger); const analysis_plan plan (sg, logger); diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc index 32b50070e01..4d3fec0b960 100644 --- a/gcc/analyzer/program-state.cc +++ b/gcc/analyzer/program-state.cc @@ -61,11 +61,10 @@ void extrinsic_state::dump_to_pp (pretty_printer *pp) const { pp_printf (pp, "extrinsic_state: %i checker(s)\n", get_num_checkers ()); - unsigned i; - state_machine *checker; - FOR_EACH_VEC_ELT (m_checkers, i, checker) + unsigned i = 0; + for (auto &checker : m_checkers) { - pp_printf (pp, "m_checkers[%i]: %qs\n", i, checker->get_name ()); + pp_printf (pp, "m_checkers[%i]: %qs\n", ++i, checker->get_name ()); checker->dump_to_pp (pp); } } @@ -97,9 +96,7 @@ extrinsic_state::to_json () const { auto checkers_arr = ::make_unique<json::array> (); - unsigned i; - state_machine *sm; - FOR_EACH_VEC_ELT (m_checkers, i, sm) + for (auto &sm : m_checkers) checkers_arr->append (sm->to_json ()); ext_state_obj->set ("checkers", std::move (checkers_arr)); } @@ -125,10 +122,8 @@ extrinsic_state::get_model_manager () const bool extrinsic_state::get_sm_idx_by_name (const char *name, unsigned *out) const { - unsigned i; - state_machine *sm; - FOR_EACH_VEC_ELT (m_checkers, i, sm) - if (0 == strcmp (name, sm->get_name ())) + for (size_t i = 0; i < m_checkers.size (); ++i) + if (0 == strcmp (name, m_checkers[i]->get_name ())) { /* Found NAME. */ *out = i; @@ -1783,12 +1778,13 @@ test_sm_state_map () tree y = build_global_decl ("y", integer_type_node); tree z = build_global_decl ("z", integer_type_node); - state_machine *sm = make_malloc_state_machine (NULL); - auto_delete_vec <state_machine> checkers; - checkers.safe_push (sm); - engine eng; - extrinsic_state ext_state (checkers, &eng); + std::unique_ptr<state_machine> sm = make_malloc_state_machine (NULL); state_machine::state_t start = sm->get_start_state (); + std::vector<std::unique_ptr<state_machine>> checkers; + const state_machine &borrowed_sm = *sm.get (); + checkers.push_back (std::move (sm)); + engine eng; + extrinsic_state ext_state (std::move (checkers), &eng); /* Test setting states on svalue_id instances directly. */ { @@ -1800,7 +1796,7 @@ test_sm_state_map () const svalue *y_sval = model.get_rvalue (y, NULL); const svalue *z_sval = model.get_rvalue (z, NULL); - sm_state_map map (*sm); + sm_state_map map (borrowed_sm); ASSERT_TRUE (map.is_empty_p ()); ASSERT_EQ (map.get_state (x_sval, ext_state), start); @@ -1829,7 +1825,7 @@ test_sm_state_map () const svalue *y_sval = model.get_rvalue (y, NULL); const svalue *z_sval = model.get_rvalue (z, NULL); - sm_state_map map (*sm); + sm_state_map map (borrowed_sm); ASSERT_TRUE (map.is_empty_p ()); ASSERT_EQ (map.get_state (x_sval, ext_state), start); ASSERT_EQ (map.get_state (y_sval, ext_state), start); @@ -1852,9 +1848,9 @@ test_sm_state_map () const svalue *y_sval = model.get_rvalue (y, NULL); const svalue *z_sval = model.get_rvalue (z, NULL); - sm_state_map map0 (*sm); - sm_state_map map1 (*sm); - sm_state_map map2 (*sm); + sm_state_map map0 (borrowed_sm); + sm_state_map map1 (borrowed_sm); + sm_state_map map2 (borrowed_sm); ASSERT_EQ (map0.hash (), map1.hash ()); ASSERT_EQ (map0, map1); @@ -1875,9 +1871,9 @@ test_sm_state_map () const state_machine::state_t TEST_STATE_2 = &test_state_2; const state_machine::state test_state_3 ("test state 3", 3); const state_machine::state_t TEST_STATE_3 = &test_state_3; - sm_state_map map0 (*sm); - sm_state_map map1 (*sm); - sm_state_map map2 (*sm); + sm_state_map map0 (borrowed_sm); + sm_state_map map1 (borrowed_sm); + sm_state_map map2 (borrowed_sm); ASSERT_EQ (map0.hash (), map1.hash ()); ASSERT_EQ (map0, map1); @@ -1912,14 +1908,12 @@ test_program_state_1 () malloc sm-state, pointing to a region on the heap. */ tree p = build_global_decl ("p", ptr_type_node); - state_machine *sm = make_malloc_state_machine (NULL); + std::unique_ptr<state_machine> sm = make_malloc_state_machine (NULL); const state_machine::state_t UNCHECKED_STATE = sm->get_state_by_name ("unchecked"); - auto_delete_vec <state_machine> checkers; - checkers.safe_push (sm); engine eng; - extrinsic_state ext_state (checkers, &eng); + extrinsic_state ext_state (std::move (sm), &eng); region_model_manager *mgr = eng.get_model_manager (); program_state s (ext_state); region_model *model = s.m_region_model; @@ -1947,9 +1941,9 @@ test_program_state_2 () tree string_cst_ptr = build_string_literal (4, "foo"); - auto_delete_vec <state_machine> checkers; + std::vector<std::unique_ptr<state_machine>> checkers; engine eng; - extrinsic_state ext_state (checkers, &eng); + extrinsic_state ext_state (std::move (checkers), &eng); program_state s (ext_state); region_model *model = s.m_region_model; @@ -1971,9 +1965,8 @@ test_program_state_merging () engine eng; region_model_manager *mgr = eng.get_model_manager (); program_point point (program_point::origin (*mgr)); - auto_delete_vec <state_machine> checkers; - checkers.safe_push (make_malloc_state_machine (NULL)); - extrinsic_state ext_state (checkers, &eng); + extrinsic_state ext_state (make_malloc_state_machine (NULL), + &eng); program_state s0 (ext_state); uncertainty_t uncertainty; @@ -2039,9 +2032,7 @@ test_program_state_merging_2 () engine eng; region_model_manager *mgr = eng.get_model_manager (); program_point point (program_point::origin (*mgr)); - auto_delete_vec <state_machine> checkers; - checkers.safe_push (make_signal_state_machine (NULL)); - extrinsic_state ext_state (checkers, &eng); + extrinsic_state ext_state (make_signal_state_machine (NULL), &eng); const state_machine::state test_state_0 ("test state 0", 0); const state_machine::state test_state_1 ("test state 1", 1); diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h index 48563a93e09..269ffde9ee6 100644 --- a/gcc/analyzer/program-state.h +++ b/gcc/analyzer/program-state.h @@ -30,13 +30,25 @@ namespace ana { class extrinsic_state { public: - extrinsic_state (auto_delete_vec <state_machine> &checkers, + extrinsic_state (std::vector<std::unique_ptr<state_machine>> &&checkers, engine *eng, logger *logger = NULL) - : m_checkers (checkers), m_logger (logger), m_engine (eng) + : m_checkers (std::move (checkers)), + m_logger (logger), + m_engine (eng) { } + // For use in selftests that use just one state machine + extrinsic_state (std::unique_ptr<state_machine> sm, + engine *eng, + logger *logger = NULL) + : m_logger (logger), + m_engine (eng) + { + m_checkers.push_back (std::move (sm)); + } + const state_machine &get_sm (int idx) const { return *m_checkers[idx]; @@ -47,7 +59,7 @@ public: return m_checkers[idx]->get_name (); } - unsigned get_num_checkers () const { return m_checkers.length (); } + unsigned get_num_checkers () const { return m_checkers.size (); } logger *get_logger () const { return m_logger; } @@ -64,7 +76,7 @@ public: private: /* The state machines. */ - auto_delete_vec <state_machine> &m_checkers; + std::vector<std::unique_ptr<state_machine>> m_checkers; logger *m_logger; engine *m_engine; diff --git a/gcc/analyzer/sm-fd.cc b/gcc/analyzer/sm-fd.cc index 3119b13e146..dd9ae93ad60 100644 --- a/gcc/analyzer/sm-fd.cc +++ b/gcc/analyzer/sm-fd.cc @@ -2327,10 +2327,10 @@ fd_state_machine::on_leak (tree var) const } } // namespace -state_machine * +std::unique_ptr<state_machine> make_fd_state_machine (logger *logger) { - return new fd_state_machine (logger); + return std::make_unique<fd_state_machine> (logger); } static bool diff --git a/gcc/analyzer/sm-file.cc b/gcc/analyzer/sm-file.cc index 7de7663c8c2..319ac01b218 100644 --- a/gcc/analyzer/sm-file.cc +++ b/gcc/analyzer/sm-file.cc @@ -500,10 +500,10 @@ fileptr_state_machine::on_leak (tree var) const /* Internal interface to this file. */ -state_machine * +std::unique_ptr<state_machine> make_fileptr_state_machine (logger *logger) { - return new fileptr_state_machine (logger); + return std::make_unique<fileptr_state_machine> (logger); } /* Handler for various stdio-related builtins that merely have external diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc index aad625eea77..ad7974e2d3b 100644 --- a/gcc/analyzer/sm-malloc.cc +++ b/gcc/analyzer/sm-malloc.cc @@ -2698,10 +2698,10 @@ malloc_state_machine::transition_ptr_sval_non_null (region_model *model, /* Internal interface to this file. */ -state_machine * +std::unique_ptr<state_machine> make_malloc_state_machine (logger *logger) { - return new malloc_state_machine (logger); + return std::make_unique<malloc_state_machine> (logger); } /* Specialcase hook for handling realloc, for use by diff --git a/gcc/analyzer/sm-pattern-test.cc b/gcc/analyzer/sm-pattern-test.cc index 151e625dc46..f24e8df4743 100644 --- a/gcc/analyzer/sm-pattern-test.cc +++ b/gcc/analyzer/sm-pattern-test.cc @@ -146,10 +146,10 @@ pattern_test_state_machine::can_purge_p (state_t s ATTRIBUTE_UNUSED) const /* Internal interface to this file. */ -state_machine * +std::unique_ptr<state_machine> make_pattern_test_state_machine (logger *logger) { - return new pattern_test_state_machine (logger); + return std::make_unique<pattern_test_state_machine> (logger); } } // namespace ana diff --git a/gcc/analyzer/sm-sensitive.cc b/gcc/analyzer/sm-sensitive.cc index 3ffe30d6c4d..385573b178c 100644 --- a/gcc/analyzer/sm-sensitive.cc +++ b/gcc/analyzer/sm-sensitive.cc @@ -242,10 +242,10 @@ sensitive_state_machine::can_purge_p (state_t s ATTRIBUTE_UNUSED) const /* Internal interface to this file. */ -state_machine * +std::unique_ptr<state_machine> make_sensitive_state_machine (logger *logger) { - return new sensitive_state_machine (logger); + return std::make_unique<sensitive_state_machine> (logger); } } // namespace ana diff --git a/gcc/analyzer/sm-signal.cc b/gcc/analyzer/sm-signal.cc index 1e7415149f8..2521c7c29ea 100644 --- a/gcc/analyzer/sm-signal.cc +++ b/gcc/analyzer/sm-signal.cc @@ -369,10 +369,10 @@ signal_state_machine::can_purge_p (state_t s ATTRIBUTE_UNUSED) const /* Internal interface to this file. */ -state_machine * +std::unique_ptr<state_machine> make_signal_state_machine (logger *logger) { - return new signal_state_machine (logger); + return std::make_unique<signal_state_machine> (logger); } #if CHECKING_P diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc index efbc483e173..21ce68ed716 100644 --- a/gcc/analyzer/sm-taint.cc +++ b/gcc/analyzer/sm-taint.cc @@ -1518,10 +1518,10 @@ taint_state_machine::check_for_tainted_divisor (sm_context &sm_ctxt, /* Internal interface to this file. */ -state_machine * +std::unique_ptr<state_machine> make_taint_state_machine (logger *logger) { - return new taint_state_machine (logger); + return std::make_unique<taint_state_machine> (logger); } /* A closed concrete range. */ diff --git a/gcc/analyzer/sm.cc b/gcc/analyzer/sm.cc index f1590f7d5a0..4328e3c7e2d 100644 --- a/gcc/analyzer/sm.cc +++ b/gcc/analyzer/sm.cc @@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ +#define INCLUDE_LIST #include "analyzer/common.h" #include "tree-diagnostic.h" @@ -169,35 +170,40 @@ sm_context::get_old_region_model () const } /* Create instances of the various state machines, each using LOGGER, - and populate OUT with them. */ + returning a vector of them. */ -void -make_checkers (auto_delete_vec <state_machine> &out, logger *logger) +std::vector<std::unique_ptr<state_machine>> +make_checkers (logger *logger) { - out.safe_push (make_malloc_state_machine (logger)); - out.safe_push (make_fileptr_state_machine (logger)); - out.safe_push (make_fd_state_machine (logger)); - out.safe_push (make_taint_state_machine (logger)); - out.safe_push (make_sensitive_state_machine (logger)); - out.safe_push (make_signal_state_machine (logger)); - out.safe_push (make_va_list_state_machine (logger)); + /* Start with a list so that we can filter it. */ + std::list<std::unique_ptr<state_machine>> out; + out.push_back (make_malloc_state_machine (logger)); + out.push_back (make_fileptr_state_machine (logger)); + out.push_back (make_fd_state_machine (logger)); + out.push_back (make_taint_state_machine (logger)); + out.push_back (make_sensitive_state_machine (logger)); + out.push_back (make_signal_state_machine (logger)); + out.push_back (make_va_list_state_machine (logger)); /* We only attempt to run the pattern tests if it might have been manually enabled (for DejaGnu purposes). */ if (flag_analyzer_checker) - out.safe_push (make_pattern_test_state_machine (logger)); + out.push_back (make_pattern_test_state_machine (logger)); if (flag_analyzer_checker) { - unsigned read_index, write_index; - state_machine **sm; - - /* TODO: this leaks the machines - Would be nice to log the things that were removed. */ - VEC_ORDERED_REMOVE_IF (out, read_index, write_index, sm, - 0 != strcmp (flag_analyzer_checker, - (*sm)->get_name ())); + out.remove_if ([] (auto &sm) + { + return 0 != strcmp (flag_analyzer_checker, + sm->get_name ()); + }); } + + std::vector<std::unique_ptr<state_machine>> out_vec; + for (auto &iter: out) + out_vec.push_back (std::move (iter)); + + return out_vec; } } // namespace ana diff --git a/gcc/analyzer/sm.h b/gcc/analyzer/sm.h index 6cdb161c66e..a932765131b 100644 --- a/gcc/analyzer/sm.h +++ b/gcc/analyzer/sm.h @@ -341,17 +341,17 @@ protected: /* The various state_machine subclasses are hidden in their respective implementation files. */ -extern void make_checkers (auto_delete_vec <state_machine> &out, - logger *logger); - -extern state_machine *make_malloc_state_machine (logger *logger); -extern state_machine *make_fileptr_state_machine (logger *logger); -extern state_machine *make_taint_state_machine (logger *logger); -extern state_machine *make_sensitive_state_machine (logger *logger); -extern state_machine *make_signal_state_machine (logger *logger); -extern state_machine *make_pattern_test_state_machine (logger *logger); -extern state_machine *make_va_list_state_machine (logger *logger); -extern state_machine *make_fd_state_machine (logger *logger); +extern std::vector<std::unique_ptr<state_machine>> +make_checkers (logger *logger); + +extern std::unique_ptr<state_machine> make_malloc_state_machine (logger *); +extern std::unique_ptr<state_machine> make_fileptr_state_machine (logger *); +extern std::unique_ptr<state_machine> make_taint_state_machine (logger *); +extern std::unique_ptr<state_machine> make_sensitive_state_machine (logger *); +extern std::unique_ptr<state_machine> make_signal_state_machine (logger *); +extern std::unique_ptr<state_machine> make_pattern_test_state_machine (logger *); +extern std::unique_ptr<state_machine> make_va_list_state_machine (logger *); +extern std::unique_ptr<state_machine> make_fd_state_machine (logger *); } // namespace ana diff --git a/gcc/analyzer/varargs.cc b/gcc/analyzer/varargs.cc index 7e0854ced54..55730a36141 100644 --- a/gcc/analyzer/varargs.cc +++ b/gcc/analyzer/varargs.cc @@ -642,10 +642,10 @@ va_list_state_machine::on_leak (tree var) const /* Internal interface to this file. */ -state_machine * +std::unique_ptr<state_machine> make_va_list_state_machine (logger *logger) { - return new va_list_state_machine (logger); + return std::make_unique<va_list_state_machine> (logger); } /* Handler for "__builtin_va_start". */ -- 2.26.3