diff options
Diffstat (limited to 'gcc/analyzer/sm-file.cc')
-rw-r--r-- | gcc/analyzer/sm-file.cc | 132 |
1 files changed, 71 insertions, 61 deletions
diff --git a/gcc/analyzer/sm-file.cc b/gcc/analyzer/sm-file.cc index 1e41dc9..4b1fc77 100644 --- a/gcc/analyzer/sm-file.cc +++ b/gcc/analyzer/sm-file.cc @@ -18,28 +18,19 @@ 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/>. */ -#include "config.h" -#define INCLUDE_VECTOR -#include "system.h" -#include "coretypes.h" -#include "make-unique.h" -#include "tree.h" -#include "function.h" -#include "basic-block.h" -#include "gimple.h" -#include "options.h" -#include "diagnostic-core.h" -#include "diagnostic-path.h" -#include "analyzer/analyzer.h" +#include "analyzer/common.h" + #include "diagnostic-event-id.h" +#include "selftest.h" + #include "analyzer/analyzer-logging.h" #include "analyzer/sm.h" #include "analyzer/pending-diagnostic.h" #include "analyzer/function-set.h" #include "analyzer/analyzer-selftests.h" -#include "selftest.h" #include "analyzer/call-string.h" #include "analyzer/program-point.h" +#include "analyzer/program-state.h" #include "analyzer/store.h" #include "analyzer/region-model.h" #include "analyzer/call-details.h" @@ -82,7 +73,11 @@ public: const svalue *rhs) const final override; bool can_purge_p (state_t s) const final override; - std::unique_ptr<pending_diagnostic> on_leak (tree var) const final override; + + std::unique_ptr<pending_diagnostic> + on_leak (tree var, + const program_state *old_state, + const program_state *new_state) const final override; /* State for a FILE * returned from fopen that hasn't been checked for NULL. @@ -166,11 +161,11 @@ public: { if (change.m_old_state == m_sm.get_start_state () && change.m_new_state == m_sm.m_unchecked) - return diagnostic_event::meaning (diagnostic_event::VERB_acquire, - diagnostic_event::NOUN_resource); + return diagnostic_event::meaning (diagnostic_event::verb::acquire, + diagnostic_event::noun::resource); if (change.m_new_state == m_sm.m_closed) - return diagnostic_event::meaning (diagnostic_event::VERB_release, - diagnostic_event::NOUN_resource); + return diagnostic_event::meaning (diagnostic_event::verb::release, + diagnostic_event::noun::resource); return diagnostic_event::meaning (); } @@ -236,9 +231,14 @@ private: class file_leak : public file_diagnostic { public: - file_leak (const fileptr_state_machine &sm, tree arg) - : file_diagnostic (sm, arg) - {} + file_leak (const fileptr_state_machine &sm, tree arg, + const program_state *final_state) + : file_diagnostic (sm, arg), + m_final_state () + { + if (final_state) + m_final_state = std::make_unique<program_state> (*final_state); + } const char *get_kind () const final override { return "file_leak"; } @@ -296,8 +296,15 @@ public: return true; } + const program_state * + get_final_state () const final override + { + return m_final_state.get (); + } + private: diagnostic_event_id_t m_fopen_event; + std::unique_ptr<program_state> m_final_state; }; /* fileptr_state_machine's ctor. */ @@ -403,9 +410,9 @@ fileptr_state_machine::on_stmt (sm_context &sm_ctxt, const gimple *stmt) const { if (const gcall *call = dyn_cast <const gcall *> (stmt)) - if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (call)) + if (tree callee_fndecl = sm_ctxt.get_fndecl_for_call (*call)) { - if (is_named_call_p (callee_fndecl, "fopen", call, 2)) + if (is_named_call_p (callee_fndecl, "fopen", *call, 2)) { tree lhs = gimple_call_lhs (call); if (lhs) @@ -417,7 +424,7 @@ fileptr_state_machine::on_stmt (sm_context &sm_ctxt, return true; } - if (is_named_call_p (callee_fndecl, "fclose", call, 1)) + if (is_named_call_p (callee_fndecl, "fclose", *call, 1)) { tree arg = gimple_call_arg (call, 0); @@ -433,7 +440,8 @@ fileptr_state_machine::on_stmt (sm_context &sm_ctxt, { tree diag_arg = sm_ctxt.get_diagnostic_tree (arg); sm_ctxt.warn (node, stmt, arg, - make_unique<double_fclose> (*this, diag_arg)); + std::make_unique<double_fclose> (*this, + diag_arg)); sm_ctxt.set_next_state (stmt, arg, m_stop); } return true; @@ -501,19 +509,21 @@ fileptr_state_machine::can_purge_p (state_t s) const state 'unchecked' and 'nonnull'. */ std::unique_ptr<pending_diagnostic> -fileptr_state_machine::on_leak (tree var) const +fileptr_state_machine::on_leak (tree var, + const program_state *, + const program_state *new_state) const { - return make_unique<file_leak> (*this, var); + return std::make_unique<file_leak> (*this, var, new_state); } } // anonymous namespace /* 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 @@ -655,40 +665,40 @@ public: void register_known_file_functions (known_function_manager &kfm) { - kfm.add (BUILT_IN_FPRINTF, make_unique<kf_stdio_output_fn> ()); - kfm.add (BUILT_IN_FPRINTF_UNLOCKED, make_unique<kf_stdio_output_fn> ()); - kfm.add (BUILT_IN_FPUTC, make_unique<kf_stdio_output_fn> ()); - kfm.add (BUILT_IN_FPUTC_UNLOCKED, make_unique<kf_stdio_output_fn> ()); - kfm.add (BUILT_IN_FPUTS, make_unique<kf_stdio_output_fn> ()); - kfm.add (BUILT_IN_FPUTS_UNLOCKED, make_unique<kf_stdio_output_fn> ()); - kfm.add (BUILT_IN_FWRITE, make_unique<kf_stdio_output_fn> ()); - kfm.add (BUILT_IN_FWRITE_UNLOCKED, make_unique<kf_stdio_output_fn> ()); - kfm.add (BUILT_IN_PRINTF, make_unique<kf_stdio_output_fn> ()); - kfm.add (BUILT_IN_PRINTF_UNLOCKED, make_unique<kf_stdio_output_fn> ()); - kfm.add (BUILT_IN_PUTC, make_unique<kf_stdio_output_fn> ()); - kfm.add (BUILT_IN_PUTCHAR, make_unique<kf_stdio_output_fn> ()); - kfm.add (BUILT_IN_PUTCHAR_UNLOCKED, make_unique<kf_stdio_output_fn> ()); - kfm.add (BUILT_IN_PUTC_UNLOCKED, make_unique<kf_stdio_output_fn> ()); - kfm.add (BUILT_IN_PUTS, make_unique<kf_stdio_output_fn> ()); - kfm.add (BUILT_IN_PUTS_UNLOCKED, make_unique<kf_stdio_output_fn> ()); - kfm.add (BUILT_IN_VFPRINTF, make_unique<kf_stdio_output_fn> ()); - kfm.add (BUILT_IN_VPRINTF, make_unique<kf_stdio_output_fn> ()); - - kfm.add ("ferror", make_unique<kf_ferror> ()); - kfm.add ("fgets", make_unique<kf_fgets> ()); - kfm.add ("fgets_unlocked", make_unique<kf_fgets> ()); // non-standard - kfm.add ("fileno", make_unique<kf_fileno> ()); - kfm.add ("fread", make_unique<kf_fread> ()); - kfm.add ("getc", make_unique<kf_getc> ()); - kfm.add ("getchar", make_unique<kf_getchar> ()); + kfm.add (BUILT_IN_FPRINTF, std::make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_FPRINTF_UNLOCKED, std::make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_FPUTC, std::make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_FPUTC_UNLOCKED, std::make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_FPUTS, std::make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_FPUTS_UNLOCKED, std::make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_FWRITE, std::make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_FWRITE_UNLOCKED, std::make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_PRINTF, std::make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_PRINTF_UNLOCKED, std::make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_PUTC, std::make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_PUTCHAR, std::make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_PUTCHAR_UNLOCKED, std::make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_PUTC_UNLOCKED, std::make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_PUTS, std::make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_PUTS_UNLOCKED, std::make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_VFPRINTF, std::make_unique<kf_stdio_output_fn> ()); + kfm.add (BUILT_IN_VPRINTF, std::make_unique<kf_stdio_output_fn> ()); + + kfm.add ("ferror", std::make_unique<kf_ferror> ()); + kfm.add ("fgets", std::make_unique<kf_fgets> ()); + kfm.add ("fgets_unlocked", std::make_unique<kf_fgets> ()); // non-standard + kfm.add ("fileno", std::make_unique<kf_fileno> ()); + kfm.add ("fread", std::make_unique<kf_fread> ()); + kfm.add ("getc", std::make_unique<kf_getc> ()); + kfm.add ("getchar", std::make_unique<kf_getchar> ()); /* Some C++ implementations use the std:: copies of these functions from <cstdio> for <stdio.h>, so we must match against these too. */ - kfm.add_std_ns ("ferror", make_unique<kf_ferror> ()); - kfm.add_std_ns ("fgets", make_unique<kf_fgets> ()); - kfm.add_std_ns ("fread", make_unique<kf_fread> ()); - kfm.add_std_ns ("getc", make_unique<kf_getc> ()); - kfm.add_std_ns ("getchar", make_unique<kf_getchar> ()); + kfm.add_std_ns ("ferror", std::make_unique<kf_ferror> ()); + kfm.add_std_ns ("fgets", std::make_unique<kf_fgets> ()); + kfm.add_std_ns ("fread", std::make_unique<kf_fread> ()); + kfm.add_std_ns ("getc", std::make_unique<kf_getc> ()); + kfm.add_std_ns ("getchar", std::make_unique<kf_getchar> ()); } #if CHECKING_P |