]>
Commit | Line | Data |
---|---|---|
757bf1df | 1 | /* Classes for analyzer diagnostics. |
83ffe9cd | 2 | Copyright (C) 2019-2023 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 | ||
21 | #include "config.h" | |
6341f14e | 22 | #define INCLUDE_MEMORY |
757bf1df DM |
23 | #include "system.h" |
24 | #include "coretypes.h" | |
25 | #include "tree.h" | |
26 | #include "intl.h" | |
27 | #include "diagnostic.h" | |
757bf1df DM |
28 | #include "analyzer/analyzer.h" |
29 | #include "diagnostic-event-id.h" | |
30 | #include "analyzer/analyzer-logging.h" | |
31 | #include "analyzer/sm.h" | |
32 | #include "diagnostic-event-id.h" | |
33 | #include "analyzer/sm.h" | |
34 | #include "analyzer/pending-diagnostic.h" | |
2402dc6b | 35 | #include "analyzer/diagnostic-manager.h" |
00e7d024 DM |
36 | #include "analyzer/call-string.h" |
37 | #include "analyzer/program-point.h" | |
38 | #include "analyzer/store.h" | |
39 | #include "analyzer/region-model.h" | |
2402dc6b DM |
40 | #include "cpplib.h" |
41 | #include "digraph.h" | |
42 | #include "ordered-hash-map.h" | |
43 | #include "cfg.h" | |
44 | #include "basic-block.h" | |
45 | #include "gimple.h" | |
46 | #include "gimple-iterator.h" | |
47 | #include "cgraph.h" | |
48 | #include "analyzer/supergraph.h" | |
49 | #include "analyzer/program-state.h" | |
2402dc6b DM |
50 | #include "analyzer/exploded-graph.h" |
51 | #include "diagnostic-path.h" | |
52 | #include "analyzer/checker-path.h" | |
d60b40b8 | 53 | #include "make-unique.h" |
757bf1df DM |
54 | |
55 | #if ENABLE_ANALYZER | |
56 | ||
75038aa6 DM |
57 | namespace ana { |
58 | ||
00e7d024 DM |
59 | /* struct interesting_t. */ |
60 | ||
61 | /* Mark the creation of REG as being interesting. */ | |
62 | ||
63 | void | |
64 | interesting_t::add_region_creation (const region *reg) | |
65 | { | |
66 | gcc_assert (reg); | |
67 | m_region_creation.safe_push (reg); | |
68 | } | |
69 | ||
70 | void | |
71 | interesting_t::dump_to_pp (pretty_printer *pp, bool simple) const | |
72 | { | |
73 | pp_string (pp, "{ region creation: ["); | |
74 | unsigned i; | |
75 | const region *reg; | |
76 | FOR_EACH_VEC_ELT (m_region_creation, i, reg) | |
77 | { | |
78 | if (i > 0) | |
79 | pp_string (pp, ", "); | |
80 | reg->dump_to_pp (pp, simple); | |
81 | } | |
82 | pp_string (pp, "]}"); | |
83 | } | |
84 | ||
757bf1df DM |
85 | /* Generate a label_text by printing FMT. |
86 | ||
87 | Use a clone of the global_dc for formatting callbacks. | |
88 | ||
89 | Use this evdesc::event_desc's m_colorize flag to control colorization | |
90 | (so that e.g. we can disable it for JSON output). */ | |
91 | ||
92 | label_text | |
93 | evdesc::event_desc::formatted_print (const char *fmt, ...) const | |
94 | { | |
95 | pretty_printer *pp = global_dc->printer->clone (); | |
96 | ||
97 | pp_show_color (pp) = m_colorize; | |
98 | ||
99 | text_info ti; | |
100 | rich_location rich_loc (line_table, UNKNOWN_LOCATION); | |
101 | va_list ap; | |
102 | va_start (ap, fmt); | |
103 | ti.format_spec = _(fmt); | |
104 | ti.args_ptr = ≈ | |
105 | ti.err_no = 0; | |
106 | ti.x_data = NULL; | |
107 | ti.m_richloc = &rich_loc; | |
108 | pp_format (pp, &ti); | |
109 | pp_output_formatted_text (pp); | |
110 | va_end (ap); | |
111 | ||
112 | label_text result = label_text::take (xstrdup (pp_formatted_text (pp))); | |
113 | delete pp; | |
114 | return result; | |
115 | } | |
116 | ||
14f9d7b9 DM |
117 | /* Return true if T1 and T2 are "the same" for the purposes of |
118 | diagnostic deduplication. */ | |
119 | ||
120 | bool | |
121 | pending_diagnostic::same_tree_p (tree t1, tree t2) | |
122 | { | |
123 | return simple_cst_equal (t1, t2) == 1; | |
124 | } | |
125 | ||
2402dc6b DM |
126 | /* Return true iff IDENT is STR. */ |
127 | ||
128 | static bool | |
129 | ht_ident_eq (ht_identifier ident, const char *str) | |
130 | { | |
131 | return (strlen (str) == ident.len | |
132 | && 0 == strcmp (str, (const char *)ident.str)); | |
133 | } | |
134 | ||
135 | /* Return true if we should show the expansion location rather than unwind | |
136 | within MACRO. */ | |
137 | ||
138 | static bool | |
139 | fixup_location_in_macro_p (cpp_hashnode *macro) | |
140 | { | |
141 | ht_identifier ident = macro->ident; | |
142 | /* Don't unwind inside <stdarg.h> macros, so that we don't suppress warnings | |
143 | from them (due to being in system headers). */ | |
144 | if (ht_ident_eq (ident, "va_start") | |
145 | || ht_ident_eq (ident, "va_copy") | |
146 | || ht_ident_eq (ident, "va_arg") | |
147 | || ht_ident_eq (ident, "va_end")) | |
148 | return true; | |
149 | return false; | |
150 | } | |
151 | ||
152 | /* Base implementation of pending_diagnostic::fixup_location. | |
153 | Don't unwind inside macros for which fixup_location_in_macro_p is true. */ | |
154 | ||
155 | location_t | |
d777b38c | 156 | pending_diagnostic::fixup_location (location_t loc, bool) const |
2402dc6b DM |
157 | { |
158 | if (linemap_location_from_macro_expansion_p (line_table, loc)) | |
159 | { | |
160 | line_map *map | |
161 | = const_cast <line_map *> (linemap_lookup (line_table, loc)); | |
162 | const line_map_macro *macro_map = linemap_check_macro (map); | |
163 | if (fixup_location_in_macro_p (macro_map->macro)) | |
164 | loc = linemap_resolve_location (line_table, loc, | |
165 | LRK_MACRO_EXPANSION_POINT, NULL); | |
166 | } | |
167 | return loc; | |
168 | } | |
169 | ||
12c583a2 DM |
170 | /* Base implementation of pending_diagnostic::add_function_entry_event. |
171 | Add a function_entry_event to EMISSION_PATH. */ | |
172 | ||
173 | void | |
174 | pending_diagnostic::add_function_entry_event (const exploded_edge &eedge, | |
175 | checker_path *emission_path) | |
176 | { | |
177 | const exploded_node *dst_node = eedge.m_dest; | |
178 | const program_point &dst_point = dst_node->get_point (); | |
179 | emission_path->add_event (make_unique<function_entry_event> (dst_point)); | |
180 | } | |
181 | ||
2402dc6b DM |
182 | /* Base implementation of pending_diagnostic::add_call_event. |
183 | Add a call_event to EMISSION_PATH. */ | |
184 | ||
185 | void | |
186 | pending_diagnostic::add_call_event (const exploded_edge &eedge, | |
187 | checker_path *emission_path) | |
188 | { | |
189 | const exploded_node *src_node = eedge.m_src; | |
190 | const program_point &src_point = src_node->get_point (); | |
191 | const int src_stack_depth = src_point.get_stack_depth (); | |
192 | const gimple *last_stmt = src_point.get_supernode ()->get_last_stmt (); | |
193 | emission_path->add_event | |
d60b40b8 | 194 | (make_unique<call_event> (eedge, |
e24fe128 DM |
195 | event_loc_info (last_stmt |
196 | ? last_stmt->location | |
197 | : UNKNOWN_LOCATION, | |
198 | src_point.get_fndecl (), | |
199 | src_stack_depth))); | |
2402dc6b DM |
200 | } |
201 | ||
f5758fe5 DM |
202 | /* Base implementation of pending_diagnostic::add_region_creation_events. |
203 | See the comment for class region_creation_event. */ | |
204 | ||
205 | void | |
206 | pending_diagnostic::add_region_creation_events (const region *reg, | |
207 | tree capacity, | |
e24fe128 | 208 | const event_loc_info &loc_info, |
f5758fe5 DM |
209 | checker_path &emission_path) |
210 | { | |
211 | emission_path.add_event | |
212 | (make_unique<region_creation_event_memory_space> (reg->get_memory_space (), | |
e24fe128 | 213 | loc_info)); |
f5758fe5 DM |
214 | |
215 | if (capacity) | |
216 | emission_path.add_event | |
e24fe128 | 217 | (make_unique<region_creation_event_capacity> (capacity, loc_info)); |
f5758fe5 DM |
218 | } |
219 | ||
12c583a2 DM |
220 | /* Base implementation of pending_diagnostic::add_final_event. |
221 | Add a warning_event to the end of EMISSION_PATH. */ | |
222 | ||
223 | void | |
224 | pending_diagnostic::add_final_event (const state_machine *sm, | |
225 | const exploded_node *enode, | |
226 | const gimple *stmt, | |
227 | tree var, state_machine::state_t state, | |
228 | checker_path *emission_path) | |
229 | { | |
230 | emission_path->add_event | |
e24fe128 DM |
231 | (make_unique<warning_event> |
232 | (event_loc_info (get_stmt_location (stmt, enode->get_function ()), | |
233 | enode->get_function ()->decl, | |
234 | enode->get_stack_depth ()), | |
235 | sm, var, state)); | |
12c583a2 DM |
236 | } |
237 | ||
75038aa6 DM |
238 | } // namespace ana |
239 | ||
757bf1df | 240 | #endif /* #if ENABLE_ANALYZER */ |