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