Line data Source code
1 : /* Classes for saving, deduplicating, and emitting analyzer diagnostics.
2 : Copyright (C) 2019-2026 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 17774 : struct pending_location
35 : {
36 : public:
37 1256 : 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 3995 : const feasibility_problem *get_feasibility_problem () const
99 : {
100 3995 : return m_problem.get ();
101 : }
102 :
103 : bool calc_best_epath (epath_finder *pf);
104 10088 : 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 10650 : 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 3377 : 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 */
|