From 7fd6e36ea9aa8575841ff1da08b4aebc0298abe2 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Wed, 16 Mar 2022 10:54:44 -0400 Subject: analyzer: early rejection of disabled warnings [PR104955] Avoid generating execution paths for warnings that are ultimately rejected due to -Wno-analyzer-* flags. This improves the test case from taking at least several minutes (before I killed it) to taking under a second. This doesn't fix the slowdown seen in PR analyzer/104955 with large numbers of warnings when the warnings are still enabled. gcc/analyzer/ChangeLog: PR analyzer/104955 * diagnostic-manager.cc (get_emission_location): New. (diagnostic_manager::diagnostic_manager): Initialize m_num_disabled_diagnostics. (diagnostic_manager::add_diagnostic): Reject diagnostics that will eventually be rejected due to being disabled. (diagnostic_manager::emit_saved_diagnostics): Log the number of disabled diagnostics. (diagnostic_manager::emit_saved_diagnostic): Split out logic for determining emission location to get_emission_location. * diagnostic-manager.h (diagnostic_manager::m_num_disabled_diagnostics): New field. * engine.cc (stale_jmp_buf::get_controlling_option): New. (stale_jmp_buf::emit): Use it. * pending-diagnostic.h (pending_diagnostic::get_controlling_option): New vfunc. * region-model.cc (poisoned_value_diagnostic::get_controlling_option): New. (poisoned_value_diagnostic::emit): Use it. (shift_count_negative_diagnostic::get_controlling_option): New. (shift_count_negative_diagnostic::emit): Use it. (shift_count_overflow_diagnostic::get_controlling_option): New. (shift_count_overflow_diagnostic::emit): Use it. (dump_path_diagnostic::get_controlling_option): New. (dump_path_diagnostic::emit): Use it. (write_to_const_diagnostic::get_controlling_option): New. (write_to_const_diagnostic::emit): Use it. (write_to_string_literal_diagnostic::get_controlling_option): New. (write_to_string_literal_diagnostic::emit): Use it. * sm-file.cc (double_fclose::get_controlling_option): New. (double_fclose::emit): Use it. (file_leak::get_controlling_option): New. (file_leak::emit): Use it. * sm-malloc.cc (mismatching_deallocation::get_controlling_option): New. (mismatching_deallocation::emit): Use it. (double_free::get_controlling_option): New. (double_free::emit): Use it. (possible_null_deref::get_controlling_option): New. (possible_null_deref::emit): Use it. (possible_null_arg::get_controlling_option): New. (possible_null_arg::emit): Use it. (null_deref::get_controlling_option): New. (null_deref::emit): Use it. (null_arg::get_controlling_option): New. (null_arg::emit): Use it. (use_after_free::get_controlling_option): New. (use_after_free::emit): Use it. (malloc_leak::get_controlling_option): New. (malloc_leak::emit): Use it. (free_of_non_heap::get_controlling_option): New. (free_of_non_heap::emit): Use it. * sm-pattern-test.cc (pattern_match::get_controlling_option): New. (pattern_match::emit): Use it. * sm-sensitive.cc (exposure_through_output_file::get_controlling_option): New. (exposure_through_output_file::emit): Use it. * sm-signal.cc (signal_unsafe_call::get_controlling_option): New. (signal_unsafe_call::emit): Use it. * sm-taint.cc (tainted_array_index::get_controlling_option): New. (tainted_array_index::emit): Use it. (tainted_offset::get_controlling_option): New. (tainted_offset::emit): Use it. (tainted_size::get_controlling_option): New. (tainted_size::emit): Use it. (tainted_divisor::get_controlling_option): New. (tainted_divisor::emit): Use it. (tainted_allocation_size::get_controlling_option): New. (tainted_allocation_size::emit): Use it. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/many-disabled-diagnostics.c: New test. * gcc.dg/plugin/analyzer_gil_plugin.c (gil_diagnostic::get_controlling_option): New. (double_save_thread::emit): Use it. (fncall_without_gil::emit): Likewise. (pyobject_usage_without_gil::emit): Likewise. Signed-off-by: David Malcolm --- gcc/analyzer/sm-malloc.cc | 72 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 15 deletions(-) (limited to 'gcc/analyzer/sm-malloc.cc') diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc index a5fa60d..4c03080 100644 --- a/gcc/analyzer/sm-malloc.cc +++ b/gcc/analyzer/sm-malloc.cc @@ -760,6 +760,11 @@ public: return "mismatching_deallocation"; } + int get_controlling_option () const FINAL OVERRIDE + { + return OPT_Wanalyzer_mismatching_deallocation; + } + bool emit (rich_location *rich_loc) FINAL OVERRIDE { auto_diagnostic_group d; @@ -767,13 +772,13 @@ public: m.add_cwe (762); /* CWE-762: Mismatched Memory Management Routines. */ if (const deallocator *expected_dealloc = m_expected_deallocators->maybe_get_single ()) - return warning_meta (rich_loc, m, OPT_Wanalyzer_mismatching_deallocation, + return warning_meta (rich_loc, m, get_controlling_option (), "%qE should have been deallocated with %qs" " but was deallocated with %qs", m_arg, expected_dealloc->m_name, m_actual_dealloc->m_name); else - return warning_meta (rich_loc, m, OPT_Wanalyzer_mismatching_deallocation, + return warning_meta (rich_loc, m, get_controlling_option (), "%qs called on %qE returned from a mismatched" " allocation function", m_actual_dealloc->m_name, m_arg); @@ -834,12 +839,17 @@ public: const char *get_kind () const FINAL OVERRIDE { return "double_free"; } + int get_controlling_option () const FINAL OVERRIDE + { + return OPT_Wanalyzer_double_free; + } + bool emit (rich_location *rich_loc) FINAL OVERRIDE { auto_diagnostic_group d; diagnostic_metadata m; m.add_cwe (415); /* CWE-415: Double Free. */ - return warning_meta (rich_loc, m, OPT_Wanalyzer_double_free, + return warning_meta (rich_loc, m, get_controlling_option (), "double-%qs of %qE", m_funcname, m_arg); } @@ -925,13 +935,17 @@ public: const char *get_kind () const FINAL OVERRIDE { return "possible_null_deref"; } + int get_controlling_option () const FINAL OVERRIDE + { + return OPT_Wanalyzer_possible_null_dereference; + } + bool emit (rich_location *rich_loc) FINAL OVERRIDE { /* CWE-690: Unchecked Return Value to NULL Pointer Dereference. */ diagnostic_metadata m; m.add_cwe (690); - return warning_meta (rich_loc, m, - OPT_Wanalyzer_possible_null_dereference, + return warning_meta (rich_loc, m, get_controlling_option (), "dereference of possibly-NULL %qE", m_arg); } @@ -1010,6 +1024,10 @@ public: && m_arg_idx == sub_other.m_arg_idx); } + int get_controlling_option () const FINAL OVERRIDE + { + return OPT_Wanalyzer_possible_null_argument; + } bool emit (rich_location *rich_loc) FINAL OVERRIDE { @@ -1018,7 +1036,7 @@ public: diagnostic_metadata m; m.add_cwe (690); bool warned - = warning_meta (rich_loc, m, OPT_Wanalyzer_possible_null_argument, + = warning_meta (rich_loc, m, get_controlling_option (), "use of possibly-NULL %qE where non-null expected", m_arg); if (warned) @@ -1058,13 +1076,17 @@ public: const char *get_kind () const FINAL OVERRIDE { return "null_deref"; } + int get_controlling_option () const FINAL OVERRIDE + { + return OPT_Wanalyzer_null_dereference; + } + bool emit (rich_location *rich_loc) FINAL OVERRIDE { /* CWE-476: NULL Pointer Dereference. */ diagnostic_metadata m; m.add_cwe (476); - return warning_meta (rich_loc, m, - OPT_Wanalyzer_null_dereference, + return warning_meta (rich_loc, m, get_controlling_option (), "dereference of NULL %qE", m_arg); } @@ -1106,6 +1128,11 @@ public: && m_arg_idx == sub_other.m_arg_idx); } + int get_controlling_option () const FINAL OVERRIDE + { + return OPT_Wanalyzer_null_argument; + } + bool emit (rich_location *rich_loc) FINAL OVERRIDE { /* CWE-476: NULL Pointer Dereference. */ @@ -1115,10 +1142,10 @@ public: bool warned; if (zerop (m_arg)) - warned = warning_meta (rich_loc, m, OPT_Wanalyzer_null_argument, + warned = warning_meta (rich_loc, m, get_controlling_option (), "use of NULL where non-null expected"); else - warned = warning_meta (rich_loc, m, OPT_Wanalyzer_null_argument, + warned = warning_meta (rich_loc, m, get_controlling_option (), "use of NULL %qE where non-null expected", m_arg); if (warned) @@ -1159,12 +1186,17 @@ public: const char *get_kind () const FINAL OVERRIDE { return "use_after_free"; } + int get_controlling_option () const FINAL OVERRIDE + { + return OPT_Wanalyzer_use_after_free; + } + bool emit (rich_location *rich_loc) FINAL OVERRIDE { /* CWE-416: Use After Free. */ diagnostic_metadata m; m.add_cwe (416); - return warning_meta (rich_loc, m, OPT_Wanalyzer_use_after_free, + return warning_meta (rich_loc, m, get_controlling_option (), "use after %<%s%> of %qE", m_deallocator->m_name, m_arg); } @@ -1248,15 +1280,20 @@ public: const char *get_kind () const FINAL OVERRIDE { return "malloc_leak"; } + int get_controlling_option () const FINAL OVERRIDE + { + return OPT_Wanalyzer_malloc_leak; + } + bool emit (rich_location *rich_loc) FINAL OVERRIDE { diagnostic_metadata m; m.add_cwe (401); if (m_arg) - return warning_meta (rich_loc, m, OPT_Wanalyzer_malloc_leak, + return warning_meta (rich_loc, m, get_controlling_option (), "leak of %qE", m_arg); else - return warning_meta (rich_loc, m, OPT_Wanalyzer_malloc_leak, + return warning_meta (rich_loc, m, get_controlling_option (), "leak of %qs", ""); } @@ -1316,6 +1353,11 @@ public: && m_freed_reg == other.m_freed_reg); } + int get_controlling_option () const FINAL OVERRIDE + { + return OPT_Wanalyzer_free_of_non_heap; + } + bool emit (rich_location *rich_loc) FINAL OVERRIDE { auto_diagnostic_group d; @@ -1330,13 +1372,13 @@ public: case MEMSPACE_CODE: case MEMSPACE_GLOBALS: case MEMSPACE_READONLY_DATA: - return warning_meta (rich_loc, m, OPT_Wanalyzer_free_of_non_heap, + return warning_meta (rich_loc, m, get_controlling_option (), "%<%s%> of %qE which points to memory" " not on the heap", m_funcname, m_arg); break; case MEMSPACE_STACK: - return warning_meta (rich_loc, m, OPT_Wanalyzer_free_of_non_heap, + return warning_meta (rich_loc, m, get_controlling_option (), "%<%s%> of %qE which points to memory" " on the stack", m_funcname, m_arg); -- cgit v1.1