Branch data Line data Source code
1 : : /* Classes for saving, deduplicating, and emitting analyzer diagnostics.
2 : : Copyright (C) 2019-2024 Free Software Foundation, Inc.
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 : : #ifndef GCC_ANALYZER_DIAGNOSTIC_MANAGER_H
22 : : #define GCC_ANALYZER_DIAGNOSTIC_MANAGER_H
23 : :
24 : : namespace ana {
25 : :
26 : : class epath_finder;
27 : :
28 : : /* A to-be-emitted diagnostic stored within diagnostic_manager. */
29 : :
30 : : class saved_diagnostic
31 : : {
32 : : public:
33 : : saved_diagnostic (const state_machine *sm,
34 : : const pending_location &ploc,
35 : : tree var, const svalue *sval,
36 : : state_machine::state_t state,
37 : : std::unique_ptr<pending_diagnostic> d,
38 : : unsigned idx);
39 : :
40 : : bool operator== (const saved_diagnostic &other) const;
41 : :
42 : : void add_note (std::unique_ptr<pending_note> pn);
43 : : void add_event (std::unique_ptr<checker_event> event);
44 : :
45 : : std::unique_ptr<json::object> to_json () const;
46 : :
47 : : void dump_dot_id (pretty_printer *pp) const;
48 : : void dump_as_dot_node (pretty_printer *pp) const;
49 : :
50 : 3857 : const feasibility_problem *get_feasibility_problem () const
51 : : {
52 : 3857 : return m_problem.get ();
53 : : }
54 : :
55 : : bool calc_best_epath (epath_finder *pf);
56 : 3857 : const exploded_path *get_best_epath () const { return m_best_epath.get (); }
57 : : unsigned get_epath_length () const;
58 : :
59 : : void add_duplicate (saved_diagnostic *other);
60 : 11024 : unsigned get_num_dupes () const { return m_duplicates.length (); }
61 : :
62 : 3881 : unsigned get_index () const { return m_idx; }
63 : :
64 : : bool supercedes_p (const saved_diagnostic &other) const;
65 : :
66 : : void add_any_saved_events (checker_path &dst_path);
67 : :
68 : : void emit_any_notes () const;
69 : :
70 : : void maybe_add_sarif_properties (sarif_object &result_obj) const;
71 : :
72 : : //private:
73 : : const state_machine *m_sm;
74 : : const exploded_node *m_enode;
75 : : const supernode *m_snode;
76 : : const gimple *m_stmt;
77 : : std::unique_ptr<stmt_finder> m_stmt_finder;
78 : : location_t m_loc;
79 : : tree m_var;
80 : : const svalue *m_sval;
81 : : state_machine::state_t m_state;
82 : : std::unique_ptr<pending_diagnostic> m_d;
83 : : const exploded_edge *m_trailing_eedge;
84 : :
85 : : private:
86 : : DISABLE_COPY_AND_ASSIGN (saved_diagnostic);
87 : :
88 : : unsigned m_idx;
89 : : std::unique_ptr<exploded_path> m_best_epath;
90 : : std::unique_ptr<feasibility_problem> m_problem;
91 : :
92 : : auto_vec<const saved_diagnostic *> m_duplicates;
93 : : auto_delete_vec <pending_note> m_notes;
94 : :
95 : : /* Optionally: additional context-dependent events to be emitted
96 : : immediately before the warning_event, giving more details of what
97 : : operation was being simulated when a diagnostic was saved
98 : : e.g. "looking for null terminator in param 2 of 'foo'". */
99 : : auto_delete_vec <checker_event> m_saved_events;
100 : : };
101 : :
102 : : class path_builder;
103 : :
104 : : /* A bundle of information capturing where a pending_diagnostic should
105 : : be emitted. */
106 : :
107 : : struct pending_location
108 : : {
109 : : public:
110 : 10705 : pending_location (exploded_node *enode,
111 : : const supernode *snode,
112 : : const gimple *stmt,
113 : : const stmt_finder *finder)
114 : 10705 : : m_enode (enode),
115 : 10705 : m_snode (snode),
116 : 10705 : m_stmt (stmt),
117 : 10705 : m_finder (finder),
118 : 10705 : m_loc (UNKNOWN_LOCATION)
119 : : {
120 : 10705 : gcc_assert (m_stmt || m_finder);
121 : 8924 : }
122 : :
123 : : /* ctor for cases where we have a location_t but there isn't any
124 : : gimple stmt associated with the diagnostic. */
125 : :
126 : 88 : pending_location (exploded_node *enode,
127 : : const supernode *snode,
128 : : location_t loc)
129 : 88 : : m_enode (enode),
130 : 88 : m_snode (snode),
131 : 88 : m_stmt (nullptr),
132 : 88 : m_finder (nullptr),
133 : 88 : m_loc (loc)
134 : : {
135 : : }
136 : :
137 : : exploded_node *m_enode;
138 : : const supernode *m_snode;
139 : : const gimple *m_stmt;
140 : : const stmt_finder *m_finder;
141 : : location_t m_loc;
142 : : };
143 : :
144 : : /* A class with responsibility for saving pending diagnostics, so that
145 : : they can be emitted after the exploded_graph is complete.
146 : : This lets us de-duplicate diagnostics, and find the shortest path
147 : : for each similar diagnostic, potentially using edges that might
148 : : not have been found when each diagnostic was first saved.
149 : :
150 : : This also lets us compute shortest_paths once, rather than
151 : : per-diagnostic. */
152 : :
153 : 3197 : class diagnostic_manager : public log_user
154 : : {
155 : : public:
156 : : diagnostic_manager (logger *logger, engine *eng, int verbosity);
157 : :
158 : : engine *get_engine () const { return m_eng; }
159 : :
160 : : std::unique_ptr<json::object> to_json () const;
161 : :
162 : : bool add_diagnostic (const state_machine *sm,
163 : : const pending_location &ploc,
164 : : tree var,
165 : : const svalue *sval,
166 : : state_machine::state_t state,
167 : : std::unique_ptr<pending_diagnostic> d);
168 : :
169 : : bool add_diagnostic (const pending_location &ploc,
170 : : std::unique_ptr<pending_diagnostic> d);
171 : :
172 : : void add_note (std::unique_ptr<pending_note> pn);
173 : : void add_event (std::unique_ptr<checker_event> event);
174 : :
175 : : void emit_saved_diagnostics (const exploded_graph &eg);
176 : :
177 : : void emit_saved_diagnostic (const exploded_graph &eg,
178 : : saved_diagnostic &sd);
179 : :
180 : 40 : unsigned get_num_diagnostics () const
181 : : {
182 : 44 : return m_saved_diagnostics.length ();
183 : : }
184 : 8 : saved_diagnostic *get_saved_diagnostic (unsigned idx)
185 : : {
186 : 8 : return m_saved_diagnostics[idx];
187 : : }
188 : : const saved_diagnostic *get_saved_diagnostic (unsigned idx) const
189 : : {
190 : : return m_saved_diagnostics[idx];
191 : : }
192 : :
193 : : private:
194 : : void build_emission_path (const path_builder &pb,
195 : : const exploded_path &epath,
196 : : checker_path *emission_path) const;
197 : :
198 : : void add_event_on_final_node (const path_builder &pb,
199 : : const exploded_node *final_enode,
200 : : checker_path *emission_path,
201 : : interesting_t *interest) const;
202 : :
203 : : void add_events_for_eedge (const path_builder &pb,
204 : : const exploded_edge &eedge,
205 : : checker_path *emission_path,
206 : : interesting_t *interest) const;
207 : :
208 : : bool significant_edge_p (const path_builder &pb,
209 : : const exploded_edge &eedge) const;
210 : :
211 : : void add_events_for_superedge (const path_builder &pb,
212 : : const exploded_edge &eedge,
213 : : checker_path *emission_path) const;
214 : :
215 : : void prune_path (checker_path *path,
216 : : const state_machine *sm,
217 : : const svalue *sval,
218 : : state_machine::state_t state) const;
219 : :
220 : : void prune_for_sm_diagnostic (checker_path *path,
221 : : const state_machine *sm,
222 : : tree var,
223 : : state_machine::state_t state) const;
224 : : void prune_for_sm_diagnostic (checker_path *path,
225 : : const state_machine *sm,
226 : : const svalue *sval,
227 : : state_machine::state_t state) const;
228 : : void update_for_unsuitable_sm_exprs (tree *expr) const;
229 : : void prune_interproc_events (checker_path *path) const;
230 : : void prune_system_headers (checker_path *path) const;
231 : : void consolidate_conditions (checker_path *path) const;
232 : : void finish_pruning (checker_path *path) const;
233 : :
234 : : engine *m_eng;
235 : : auto_delete_vec<saved_diagnostic> m_saved_diagnostics;
236 : : const int m_verbosity;
237 : : int m_num_disabled_diagnostics;
238 : : };
239 : :
240 : : } // namespace ana
241 : :
242 : : #endif /* GCC_ANALYZER_DIAGNOSTIC_MANAGER_H */
|