]>
| Commit | Line | Data |
|---|---|---|
| 757bf1df | 1 | /* Classes for analyzer diagnostics. |
| 6441eb6d | 2 | Copyright (C) 2019-2025 Free Software Foundation, Inc. |
| 757bf1df DM |
3 | Contributed by David Malcolm <dmalcolm@redhat.com>. |
| 4 | ||
| 5 | This file is part of GCC. | |
| 6 | ||
| 7 | GCC is free software; you can redistribute it and/or modify it | |
| 8 | under the terms of the GNU General Public License as published by | |
| 9 | the Free Software Foundation; either version 3, or (at your option) | |
| 10 | any later version. | |
| 11 | ||
| 12 | GCC is distributed in the hope that it will be useful, but | |
| 13 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 15 | General Public License for more details. | |
| 16 | ||
| 17 | You should have received a copy of the GNU General Public License | |
| 18 | along with GCC; see the file COPYING3. If not see | |
| 19 | <http://www.gnu.org/licenses/>. */ | |
| 20 | ||
| d0500cd5 DM |
21 | #include "analyzer/common.h" |
| 22 | ||
| 5b64ba69 | 23 | #include "diagnostics/event-id.h" |
| 9e98b37f | 24 | #include "diagnostics/logging.h" |
| d0500cd5 DM |
25 | #include "cpplib.h" |
| 26 | #include "digraph.h" | |
| 27 | #include "ordered-hash-map.h" | |
| 28 | #include "cfg.h" | |
| 29 | #include "gimple-iterator.h" | |
| 30 | #include "cgraph.h" | |
| 31 | ||
| 757bf1df DM |
32 | #include "analyzer/analyzer-logging.h" |
| 33 | #include "analyzer/sm.h" | |
| 757bf1df DM |
34 | #include "analyzer/sm.h" |
| 35 | #include "analyzer/pending-diagnostic.h" | |
| 2402dc6b | 36 | #include "analyzer/diagnostic-manager.h" |
| 00e7d024 DM |
37 | #include "analyzer/call-string.h" |
| 38 | #include "analyzer/program-point.h" | |
| 39 | #include "analyzer/store.h" | |
| 40 | #include "analyzer/region-model.h" | |
| 2402dc6b DM |
41 | #include "analyzer/supergraph.h" |
| 42 | #include "analyzer/program-state.h" | |
| 2402dc6b | 43 | #include "analyzer/exploded-graph.h" |
| 2402dc6b | 44 | #include "analyzer/checker-path.h" |
| 757bf1df DM |
45 | |
| 46 | #if ENABLE_ANALYZER | |
| 47 | ||
| 75038aa6 DM |
48 | namespace ana { |
| 49 | ||
| 00e7d024 DM |
50 | /* struct interesting_t. */ |
| 51 | ||
| 52 | /* Mark the creation of REG as being interesting. */ | |
| 53 | ||
| 54 | void | |
| 55 | interesting_t::add_region_creation (const region *reg) | |
| 56 | { | |
| 57 | gcc_assert (reg); | |
| 58 | m_region_creation.safe_push (reg); | |
| 59 | } | |
| 60 | ||
| 61 | void | |
| 62 | interesting_t::dump_to_pp (pretty_printer *pp, bool simple) const | |
| 63 | { | |
| 64 | pp_string (pp, "{ region creation: ["); | |
| 65 | unsigned i; | |
| 66 | const region *reg; | |
| 67 | FOR_EACH_VEC_ELT (m_region_creation, i, reg) | |
| 68 | { | |
| 69 | if (i > 0) | |
| 70 | pp_string (pp, ", "); | |
| 71 | reg->dump_to_pp (pp, simple); | |
| 72 | } | |
| 73 | pp_string (pp, "]}"); | |
| 74 | } | |
| 75 | ||
| 12b67d1e DM |
76 | /* class diagnostic_emission_context. */ |
| 77 | ||
| 78 | /* Get the pending_diagnostic being emitted. */ | |
| 79 | ||
| 80 | const pending_diagnostic & | |
| 81 | diagnostic_emission_context::get_pending_diagnostic () const | |
| 82 | { | |
| 83 | return *m_sd.m_d.get (); | |
| 84 | } | |
| 85 | ||
| 86 | /* Emit a warning, using the rich_location, metadata, and the | |
| 87 | pending_diagnostic's option. */ | |
| 88 | ||
| 89 | bool | |
| 90 | diagnostic_emission_context::warn (const char *gmsgid, ...) | |
| 91 | { | |
| 9e98b37f DM |
92 | auto dc_logger = global_dc->get_logger (); |
| 93 | diagnostics::logging::log_function_params | |
| 94 | (dc_logger, "ana::diagnostic_emission_context::warn") | |
| 95 | .log_param_string ("gmsgid", gmsgid); | |
| 96 | diagnostics::logging::auto_inc_depth depth_sentinel (dc_logger); | |
| 97 | ||
| 12b67d1e DM |
98 | const pending_diagnostic &pd = get_pending_diagnostic (); |
| 99 | auto_diagnostic_group d; | |
| 100 | va_list ap; | |
| 101 | va_start (ap, gmsgid); | |
| 3cc27ed5 | 102 | const bool result = emit_diagnostic_valist_meta (diagnostics::kind::warning, |
| b753ef8f DM |
103 | &m_rich_loc, &m_metadata, |
| 104 | pd.get_controlling_option (), | |
| 105 | gmsgid, &ap); | |
| 12b67d1e | 106 | va_end (ap); |
| 9e98b37f DM |
107 | |
| 108 | if (dc_logger) | |
| 109 | dc_logger->log_bool_return ("ana::diagnostic_emission_context::warn", | |
| 110 | result); | |
| 111 | ||
| 12b67d1e DM |
112 | return result; |
| 113 | } | |
| 114 | ||
| 115 | /* Emit a note, using the rich_location and metadata (and the | |
| 116 | pending_diagnostic's option). */ | |
| 117 | ||
| 118 | void | |
| 119 | diagnostic_emission_context::inform (const char *gmsgid, ...) | |
| 120 | { | |
| 9e98b37f DM |
121 | auto dc_logger = global_dc->get_logger (); |
| 122 | diagnostics::logging::log_function_params | |
| 123 | (dc_logger, "ana::diagnostic_emission_context::inform") | |
| 124 | .log_param_string ("gmsgid", gmsgid); | |
| 125 | diagnostics::logging::auto_inc_depth depth_sentinel (dc_logger); | |
| 126 | ||
| 12b67d1e DM |
127 | const pending_diagnostic &pd = get_pending_diagnostic (); |
| 128 | auto_diagnostic_group d; | |
| 129 | va_list ap; | |
| 130 | va_start (ap, gmsgid); | |
| 3cc27ed5 | 131 | emit_diagnostic_valist_meta (diagnostics::kind::note, |
| b753ef8f DM |
132 | &m_rich_loc, &m_metadata, |
| 133 | pd.get_controlling_option (), | |
| 134 | gmsgid, &ap); | |
| 12b67d1e DM |
135 | va_end (ap); |
| 136 | } | |
| 137 | ||
| 14f9d7b9 DM |
138 | /* Return true if T1 and T2 are "the same" for the purposes of |
| 139 | diagnostic deduplication. */ | |
| 140 | ||
| 141 | bool | |
| 142 | pending_diagnostic::same_tree_p (tree t1, tree t2) | |
| 143 | { | |
| 144 | return simple_cst_equal (t1, t2) == 1; | |
| 145 | } | |
| 146 | ||
| 2402dc6b DM |
147 | /* Return true iff IDENT is STR. */ |
| 148 | ||
| 149 | static bool | |
| 150 | ht_ident_eq (ht_identifier ident, const char *str) | |
| 151 | { | |
| 152 | return (strlen (str) == ident.len | |
| 153 | && 0 == strcmp (str, (const char *)ident.str)); | |
| 154 | } | |
| 155 | ||
| 156 | /* Return true if we should show the expansion location rather than unwind | |
| 157 | within MACRO. */ | |
| 158 | ||
| 159 | static bool | |
| 160 | fixup_location_in_macro_p (cpp_hashnode *macro) | |
| 161 | { | |
| 162 | ht_identifier ident = macro->ident; | |
| 70d34f2a DM |
163 | |
| 164 | /* Don't unwind inside "alloca" macro, so that we don't suppress warnings | |
| 165 | from it (due to being in system headers). */ | |
| 166 | if (ht_ident_eq (ident, "alloca")) | |
| 167 | return true; | |
| 168 | ||
| 2402dc6b DM |
169 | /* Don't unwind inside <stdarg.h> macros, so that we don't suppress warnings |
| 170 | from them (due to being in system headers). */ | |
| 171 | if (ht_ident_eq (ident, "va_start") | |
| 172 | || ht_ident_eq (ident, "va_copy") | |
| 173 | || ht_ident_eq (ident, "va_arg") | |
| 174 | || ht_ident_eq (ident, "va_end")) | |
| 175 | return true; | |
| 176 | return false; | |
| 177 | } | |
| 178 | ||
| 179 | /* Base implementation of pending_diagnostic::fixup_location. | |
| 180 | Don't unwind inside macros for which fixup_location_in_macro_p is true. */ | |
| 181 | ||
| 182 | location_t | |
| d777b38c | 183 | pending_diagnostic::fixup_location (location_t loc, bool) const |
| 2402dc6b DM |
184 | { |
| 185 | if (linemap_location_from_macro_expansion_p (line_table, loc)) | |
| 186 | { | |
| 187 | line_map *map | |
| 188 | = const_cast <line_map *> (linemap_lookup (line_table, loc)); | |
| 189 | const line_map_macro *macro_map = linemap_check_macro (map); | |
| 190 | if (fixup_location_in_macro_p (macro_map->macro)) | |
| 191 | loc = linemap_resolve_location (line_table, loc, | |
| 8ea555b7 | 192 | LRK_MACRO_EXPANSION_POINT, nullptr); |
| 2402dc6b DM |
193 | } |
| 194 | return loc; | |
| 195 | } | |
| 196 | ||
| 12c583a2 DM |
197 | /* Base implementation of pending_diagnostic::add_function_entry_event. |
| 198 | Add a function_entry_event to EMISSION_PATH. */ | |
| 199 | ||
| 200 | void | |
| 201 | pending_diagnostic::add_function_entry_event (const exploded_edge &eedge, | |
| 202 | checker_path *emission_path) | |
| 203 | { | |
| 204 | const exploded_node *dst_node = eedge.m_dest; | |
| 205 | const program_point &dst_point = dst_node->get_point (); | |
| 2334d30c DM |
206 | const program_state &dst_state = dst_node->get_state (); |
| 207 | emission_path->add_event | |
| 208 | (std::make_unique<function_entry_event> (dst_point, | |
| 209 | dst_state)); | |
| 12c583a2 DM |
210 | } |
| 211 | ||
| 2402dc6b DM |
212 | /* Base implementation of pending_diagnostic::add_call_event. |
| 213 | Add a call_event to EMISSION_PATH. */ | |
| 214 | ||
| 215 | void | |
| 216 | pending_diagnostic::add_call_event (const exploded_edge &eedge, | |
| 217 | checker_path *emission_path) | |
| 218 | { | |
| 219 | const exploded_node *src_node = eedge.m_src; | |
| 220 | const program_point &src_point = src_node->get_point (); | |
| 221 | const int src_stack_depth = src_point.get_stack_depth (); | |
| 222 | const gimple *last_stmt = src_point.get_supernode ()->get_last_stmt (); | |
| 223 | emission_path->add_event | |
| cf5fb8f1 DM |
224 | (std::make_unique<call_event> (eedge, |
| 225 | event_loc_info (last_stmt | |
| 226 | ? last_stmt->location | |
| 227 | : UNKNOWN_LOCATION, | |
| 228 | src_point.get_fndecl (), | |
| 229 | src_stack_depth))); | |
| 2402dc6b DM |
230 | } |
| 231 | ||
| f5758fe5 DM |
232 | /* Base implementation of pending_diagnostic::add_region_creation_events. |
| 233 | See the comment for class region_creation_event. */ | |
| 234 | ||
| 235 | void | |
| 236 | pending_diagnostic::add_region_creation_events (const region *reg, | |
| 237 | tree capacity, | |
| e24fe128 | 238 | const event_loc_info &loc_info, |
| f5758fe5 DM |
239 | checker_path &emission_path) |
| 240 | { | |
| 241 | emission_path.add_event | |
| cf5fb8f1 DM |
242 | (std::make_unique<region_creation_event_memory_space> |
| 243 | (reg->get_memory_space (), | |
| 244 | loc_info)); | |
| f5758fe5 DM |
245 | |
| 246 | if (capacity) | |
| 247 | emission_path.add_event | |
| cf5fb8f1 | 248 | (std::make_unique<region_creation_event_capacity> (capacity, loc_info)); |
| f5758fe5 DM |
249 | } |
| 250 | ||
| 12c583a2 DM |
251 | /* Base implementation of pending_diagnostic::add_final_event. |
| 252 | Add a warning_event to the end of EMISSION_PATH. */ | |
| 253 | ||
| 254 | void | |
| 255 | pending_diagnostic::add_final_event (const state_machine *sm, | |
| 256 | const exploded_node *enode, | |
| 2b0a7fe3 | 257 | const event_loc_info &loc_info, |
| 12c583a2 DM |
258 | tree var, state_machine::state_t state, |
| 259 | checker_path *emission_path) | |
| 260 | { | |
| 261 | emission_path->add_event | |
| cf5fb8f1 | 262 | (std::make_unique<warning_event> |
| 2b0a7fe3 | 263 | (loc_info, |
| 0d6f7b1d | 264 | enode, |
| 2334d30c DM |
265 | sm, var, state, |
| 266 | get_final_state ())); | |
| 12c583a2 DM |
267 | } |
| 268 | ||
| 75038aa6 DM |
269 | } // namespace ana |
| 270 | ||
| 757bf1df | 271 | #endif /* #if ENABLE_ANALYZER */ |