Update baseline symbols for hppa-linux.
[official-gcc.git] / gcc / analyzer / pending-diagnostic.h
blob7582b37efe79a27ac5324bd575d4e6b88067f7fc
1 /* Classes for analyzer diagnostics.
2 Copyright (C) 2019-2023 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
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.
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.
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/>. */
21 #ifndef GCC_ANALYZER_PENDING_DIAGNOSTIC_H
22 #define GCC_ANALYZER_PENDING_DIAGNOSTIC_H
24 #include "diagnostic-path.h"
25 #include "analyzer/sm.h"
27 namespace ana {
29 /* A bundle of information about things that are of interest to a
30 pending_diagnostic.
32 For now, merely the set of regions that are pertinent to the
33 diagnostic, so that we can notify the user about when they
34 were created. */
36 struct interesting_t
38 void add_region_creation (const region *reg);
40 void dump_to_pp (pretty_printer *pp, bool simple) const;
42 auto_vec<const region *> m_region_creation;
45 /* Various bundles of information used for generating more precise
46 messages for events within a diagnostic_path, for passing to the
47 various "describe_*" vfuncs of pending_diagnostic. See those
48 for more information. */
50 namespace evdesc {
52 struct event_desc
54 event_desc (bool colorize) : m_colorize (colorize) {}
56 label_text formatted_print (const char *fmt, ...) const
57 ATTRIBUTE_GCC_DIAG(2,3);
59 bool m_colorize;
62 /* For use by pending_diagnostic::describe_state_change. */
64 struct state_change : public event_desc
66 state_change (bool colorize,
67 tree expr,
68 tree origin,
69 state_machine::state_t old_state,
70 state_machine::state_t new_state,
71 diagnostic_event_id_t event_id,
72 const state_change_event &event)
73 : event_desc (colorize),
74 m_expr (expr), m_origin (origin),
75 m_old_state (old_state), m_new_state (new_state),
76 m_event_id (event_id), m_event (event)
79 bool is_global_p () const { return m_expr == NULL_TREE; }
81 tree m_expr;
82 tree m_origin;
83 state_machine::state_t m_old_state;
84 state_machine::state_t m_new_state;
85 diagnostic_event_id_t m_event_id;
86 const state_change_event &m_event;
89 /* For use by pending_diagnostic::describe_call_with_state. */
91 struct call_with_state : public event_desc
93 call_with_state (bool colorize,
94 tree caller_fndecl, tree callee_fndecl,
95 tree expr, state_machine::state_t state)
96 : event_desc (colorize),
97 m_caller_fndecl (caller_fndecl),
98 m_callee_fndecl (callee_fndecl),
99 m_expr (expr),
100 m_state (state)
104 tree m_caller_fndecl;
105 tree m_callee_fndecl;
106 tree m_expr;
107 state_machine::state_t m_state;
110 /* For use by pending_diagnostic::describe_return_of_state. */
112 struct return_of_state : public event_desc
114 return_of_state (bool colorize,
115 tree caller_fndecl, tree callee_fndecl,
116 state_machine::state_t state)
117 : event_desc (colorize),
118 m_caller_fndecl (caller_fndecl),
119 m_callee_fndecl (callee_fndecl),
120 m_state (state)
124 tree m_caller_fndecl;
125 tree m_callee_fndecl;
126 state_machine::state_t m_state;
129 /* For use by pending_diagnostic::describe_final_event. */
131 struct final_event : public event_desc
133 final_event (bool colorize,
134 tree expr, state_machine::state_t state,
135 const warning_event &event)
136 : event_desc (colorize),
137 m_expr (expr), m_state (state), m_event (event)
140 tree m_expr;
141 state_machine::state_t m_state;
142 const warning_event &m_event;
145 } /* end of namespace evdesc */
147 /* An abstract base class for capturing information about a diagnostic in
148 a form that is ready to emit at a later point (or be rejected).
149 Each kind of diagnostic will have a concrete subclass of
150 pending_diagnostic.
152 Normally, gcc diagnostics are emitted using va_list, which can't be
153 portably stored for later use, so we have to use an "emit" virtual
154 function.
156 This class also supports comparison, so that multiple pending_diagnostic
157 instances can be de-duplicated.
159 As well as emitting a diagnostic, the class has various "precision of
160 wording" virtual functions, for generating descriptions for events
161 within a diagnostic_path. These are optional, but implementing these
162 allows for more precise wordings than the more generic
163 implementation. */
165 class pending_diagnostic
167 public:
168 virtual ~pending_diagnostic () {}
170 /* Vfunc to get the command-line option used when emitting the diagnostic,
171 or zero if there is none.
172 Used by diagnostic_manager for early rejection of diagnostics (to avoid
173 having to generate feasible execution paths for them). */
174 virtual int get_controlling_option () const = 0;
176 /* Vfunc to give the diagnostic the chance to terminate the execution
177 path being explored. By default, don't terminate the path. */
178 virtual bool terminate_path_p () const { return false; }
180 /* Vfunc for emitting the diagnostic. The rich_location will have been
181 populated with a diagnostic_path.
182 Return true if a diagnostic is actually emitted. */
183 virtual bool emit (rich_location *, logger *) = 0;
185 /* Hand-coded RTTI: get an ID for the subclass. */
186 virtual const char *get_kind () const = 0;
188 /* A vfunc for identifying "use of uninitialized value". */
189 virtual bool use_of_uninit_p () const { return false; }
191 /* Compare for equality with OTHER, which might be of a different
192 subclass. */
194 bool equal_p (const pending_diagnostic &other) const
196 /* Check for pointer equality on the IDs from get_kind. */
197 if (get_kind () != other.get_kind ())
198 return false;
199 /* Call vfunc now we know they have the same ID: */
200 return subclass_equal_p (other);
203 /* A vfunc for testing for equality, where we've already
204 checked they have the same ID. See pending_diagnostic_subclass
205 below for a convenience subclass for implementing this. */
206 virtual bool subclass_equal_p (const pending_diagnostic &other) const = 0;
208 /* Return true if T1 and T2 are "the same" for the purposes of
209 diagnostic deduplication. */
210 static bool same_tree_p (tree t1, tree t2);
212 /* Vfunc for fixing up locations, e.g. to avoid unwinding
213 inside specific macros. PRIMARY is true for the primary location
214 for the diagnostic, and FALSE for events in their paths. */
215 virtual location_t fixup_location (location_t loc, bool primary) const;
217 /* Precision-of-wording vfunc for describing a critical state change
218 within the diagnostic_path.
220 For example, a double-free diagnostic might use the descriptions:
221 - "first 'free' happens here"
222 - "second 'free' happens here"
223 for the pertinent events, whereas a use-after-free might use the
224 descriptions:
225 - "freed here"
226 - "use after free here"
227 Note how in both cases the first event is a "free": the best
228 description to use depends on the diagnostic. */
230 virtual label_text describe_state_change (const evdesc::state_change &)
232 /* Default no-op implementation. */
233 return label_text ();
236 /* Vfunc for implementing diagnostic_event::get_meaning for
237 state_change_event. */
238 virtual diagnostic_event::meaning
239 get_meaning_for_state_change (const evdesc::state_change &) const
241 /* Default no-op implementation. */
242 return diagnostic_event::meaning ();
245 /* Precision-of-wording vfunc for describing an interprocedural call
246 carrying critial state for the diagnostic, from caller to callee.
248 For example a double-free diagnostic might use:
249 - "passing freed pointer 'ptr' in call to 'deallocator' from 'test'"
250 to make it clearer how the freed value moves from caller to
251 callee. */
253 virtual label_text describe_call_with_state (const evdesc::call_with_state &)
255 /* Default no-op implementation. */
256 return label_text ();
259 /* Precision-of-wording vfunc for describing an interprocedural return
260 within the diagnostic_path that carries critial state for the
261 diagnostic, from callee back to caller.
263 For example, a deref-of-unchecked-malloc diagnostic might use:
264 - "returning possibly-NULL pointer to 'make_obj' from 'allocator'"
265 to make it clearer how the unchecked value moves from callee
266 back to caller. */
268 virtual label_text describe_return_of_state (const evdesc::return_of_state &)
270 /* Default no-op implementation. */
271 return label_text ();
274 /* Precision-of-wording vfunc for describing the final event within a
275 diagnostic_path.
277 For example a double-free diagnostic might use:
278 - "second 'free' here; first 'free' was at (3)"
279 and a use-after-free might use
280 - "use after 'free' here; memory was freed at (2)". */
282 virtual label_text describe_final_event (const evdesc::final_event &)
284 /* Default no-op implementation. */
285 return label_text ();
288 /* End of precision-of-wording vfuncs. */
290 /* Vfunc for adding a function_entry_event to a checker_path, so that e.g.
291 the infinite recursion diagnostic can add a custom event subclass
292 that annotates recursively entering a function. */
294 virtual void
295 add_function_entry_event (const exploded_edge &eedge,
296 checker_path *emission_path);
298 /* Vfunc for extending/overriding creation of the events for an
299 exploded_edge that corresponds to a superedge, allowing for custom
300 events to be created that are pertinent to a particular
301 pending_diagnostic subclass.
303 For example, the -Wanalyzer-stale-setjmp-buffer diagnostic adds a
304 custom event showing when the pertinent stack frame is popped
305 (and thus the point at which the jmp_buf becomes invalid). */
307 virtual bool maybe_add_custom_events_for_superedge (const exploded_edge &,
308 checker_path *)
310 return false;
313 /* Vfunc for adding a call_event to a checker_path, so that e.g.
314 the varargs diagnostics can add a custom event subclass that annotates
315 the variadic arguments. */
316 virtual void add_call_event (const exploded_edge &,
317 checker_path *);
319 /* Vfunc for adding any events for the creation of regions identified
320 by the mark_interesting_stuff vfunc.
321 See the comment for class region_creation_event. */
322 virtual void add_region_creation_events (const region *reg,
323 tree capacity,
324 const event_loc_info &loc_info,
325 checker_path &emission_path);
327 /* Vfunc for adding the final warning_event to a checker_path, so that e.g.
328 the infinite recursion diagnostic can have its diagnostic appear at
329 the callsite, but the final event in the path be at the entrypoint
330 of the called function. */
331 virtual void add_final_event (const state_machine *sm,
332 const exploded_node *enode,
333 const gimple *stmt,
334 tree var, state_machine::state_t state,
335 checker_path *emission_path);
337 /* Vfunc for determining that this pending_diagnostic supercedes OTHER,
338 and that OTHER should therefore not be emitted.
339 They have already been tested for being at the same stmt. */
341 virtual bool
342 supercedes_p (const pending_diagnostic &other ATTRIBUTE_UNUSED) const
344 return false;
347 /* Vfunc for registering additional information of interest to this
348 diagnostic. */
350 virtual void mark_interesting_stuff (interesting_t *)
352 /* Default no-op implementation. */
355 /* Vfunc to give diagnostic subclasses the opportunity to reject diagnostics
356 by imposing their own additional feasibility checks on the path to a
357 given feasible_node. */
358 virtual bool check_valid_fpath_p (const feasible_node &,
359 const gimple *) const
361 /* Default implementation: accept this path. */
362 return true;
366 /* A template to make it easier to make subclasses of pending_diagnostic.
368 This uses the curiously-recurring template pattern, to implement
369 pending_diagnostic::subclass_equal_p by casting and calling
370 the operator==
372 This assumes that BASE_OTHER has already been checked to have
373 been of the same subclass (which pending_diagnostic::equal_p does). */
375 template <class Subclass>
376 class pending_diagnostic_subclass : public pending_diagnostic
378 public:
379 bool subclass_equal_p (const pending_diagnostic &base_other) const
380 final override
382 const Subclass &other = (const Subclass &)base_other;
383 return *(const Subclass*)this == other;
387 /* An abstract base class for capturing additional notes that are to be
388 emitted with a diagnostic. */
390 class pending_note
392 public:
393 virtual ~pending_note () {}
395 /* Hand-coded RTTI: get an ID for the subclass. */
396 virtual const char *get_kind () const = 0;
398 /* Vfunc for emitting the note. */
399 virtual void emit () const = 0;
401 bool equal_p (const pending_note &other) const
403 /* Check for pointer equality on the IDs from get_kind. */
404 if (get_kind () != other.get_kind ())
405 return false;
406 /* Call vfunc now we know they have the same ID: */
407 return subclass_equal_p (other);
410 /* A vfunc for testing for equality, where we've already
411 checked they have the same ID. See pending_note_subclass
412 below for a convenience subclass for implementing this. */
413 virtual bool subclass_equal_p (const pending_note &other) const = 0;
416 /* Analogous to pending_diagnostic_subclass, but for pending_note. */
418 template <class Subclass>
419 class pending_note_subclass : public pending_note
421 public:
422 bool subclass_equal_p (const pending_note &base_other) const
423 final override
425 const Subclass &other = (const Subclass &)base_other;
426 return *(const Subclass*)this == other;
430 } // namespace ana
432 #endif /* GCC_ANALYZER_PENDING_DIAGNOSTIC_H */