1 /* Subclasses of diagnostic_event for analyzer diagnostics.
2 Copyright (C) 2019-2022 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)
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_CHECKER_EVENT_H
22 #define GCC_ANALYZER_CHECKER_EVENT_H
24 #include "tree-logical-location.h"
25 #include "analyzer/program-state.h"
29 /* A bundle of location information for a checker_event. */
33 event_loc_info (location_t loc, tree fndecl, int depth)
34 : m_loc (loc), m_fndecl (fndecl), m_depth (depth)
42 /* An enum for discriminating between the concrete subclasses of
57 EK_START_CONSOLIDATED_CFG_EDGES,
58 EK_END_CONSOLIDATED_CFG_EDGES,
61 EK_REWIND_FROM_LONGJMP,
66 extern const char *event_kind_to_string (enum event_kind ek);
70 The class hierarchy looks like this (using indentation to show
71 inheritance, and with event_kinds shown for the concrete subclasses):
75 debug_event (EK_DEBUG)
76 custom_event (EK_CUSTOM)
77 precanned_custom_event
78 statement_event (EK_STMT)
79 region_creation_event (EK_REGION_CREATION)
80 function_entry_event (EK_FUNCTION_ENTRY)
81 state_change_event (EK_STATE_CHANGE)
84 start_cfg_edge_event (EK_START_CFG_EDGE)
85 end_cfg_edge_event (EK_END_CFG_EDGE)
86 call_event (EK_CALL_EDGE)
87 return_edge (EK_RETURN_EDGE)
88 start_consolidated_cfg_edges_event (EK_START_CONSOLIDATED_CFG_EDGES)
89 end_consolidated_cfg_edges_event (EK_END_CONSOLIDATED_CFG_EDGES)
90 inlined_call_event (EK_INLINED_CALL)
91 setjmp_event (EK_SETJMP)
93 rewind_from_longjmp_event (EK_REWIND_FROM_LONGJMP)
94 rewind_to_setjmp_event (EK_REWIND_TO_SETJMP)
95 warning_event (EK_WARNING). */
97 /* Abstract subclass of diagnostic_event; the base class for use in
98 checker_path (the analyzer's diagnostic_path subclass). */
100 class checker_event : public diagnostic_event
103 /* Implementation of diagnostic_event. */
105 location_t get_location () const final override { return m_loc; }
106 tree get_fndecl () const final override { return m_effective_fndecl; }
107 int get_stack_depth () const final override { return m_effective_depth; }
108 const logical_location *get_logical_location () const final override
110 if (m_effective_fndecl)
111 return &m_logical_loc;
115 meaning get_meaning () const override;
117 /* Additional functionality. */
119 int get_original_stack_depth () const { return m_original_depth; }
121 virtual void prepare_for_emission (checker_path *,
122 pending_diagnostic *pd,
123 diagnostic_event_id_t emission_id);
124 virtual bool is_call_p () const { return false; }
125 virtual bool is_function_entry_p () const { return false; }
126 virtual bool is_return_p () const { return false; }
128 /* For use with %@. */
129 const diagnostic_event_id_t *get_id_ptr () const
131 return &m_emission_id;
134 void dump (pretty_printer *pp) const;
137 void set_location (location_t loc) { m_loc = loc; }
140 checker_event (enum event_kind kind,
141 const event_loc_info &loc_info);
144 const enum event_kind m_kind;
147 tree m_original_fndecl;
148 tree m_effective_fndecl;
149 int m_original_depth;
150 int m_effective_depth;
151 pending_diagnostic *m_pending_diagnostic;
152 diagnostic_event_id_t m_emission_id; // only set once all pruning has occurred
153 tree_logical_location m_logical_loc;
156 /* A concrete event subclass for a purely textual event, for use in
157 debugging path creation and filtering. */
159 class debug_event : public checker_event
163 debug_event (const event_loc_info &loc_info,
165 : checker_event (EK_DEBUG, loc_info),
166 m_desc (xstrdup (desc))
174 label_text get_desc (bool) const final override;
180 /* An abstract event subclass for custom events. These are not filtered,
181 as they are likely to be pertinent to the diagnostic. */
183 class custom_event : public checker_event
186 custom_event (const event_loc_info &loc_info)
187 : checker_event (EK_CUSTOM, loc_info)
192 /* A concrete custom_event subclass with a precanned message. */
194 class precanned_custom_event : public custom_event
197 precanned_custom_event (const event_loc_info &loc_info,
199 : custom_event (loc_info),
200 m_desc (xstrdup (desc))
203 ~precanned_custom_event ()
208 label_text get_desc (bool) const final override;
214 /* A concrete event subclass describing the execution of a gimple statement,
215 for use at high verbosity levels when debugging paths. */
217 class statement_event : public checker_event
220 statement_event (const gimple *stmt, tree fndecl, int depth,
221 const program_state &dst_state);
223 label_text get_desc (bool) const final override;
225 const gimple * const m_stmt;
226 const program_state m_dst_state;
229 /* An abstract event subclass describing the creation of a region that
230 is significant for a diagnostic.
232 There are too many combinations to express region creation in one message,
233 so we emit multiple region_creation_event instances when each pertinent
236 The events are created by pending_diagnostic's add_region_creation_events
237 vfunc, which by default creates a region_creation_event_memory_space, and
238 if a capacity is known, a region_creation_event_capacity, giving e.g.:
239 (1) region created on stack here
240 (2) capacity: 100 bytes
241 but this vfunc can be overridden to create other events if other wordings
242 are more appropriate foa a given pending_diagnostic. */
244 class region_creation_event : public checker_event
247 region_creation_event (const event_loc_info &loc_info);
250 /* Concrete subclass of region_creation_event.
251 Generates a message based on the memory space of the region
252 e.g. "region created on stack here". */
254 class region_creation_event_memory_space : public region_creation_event
257 region_creation_event_memory_space (enum memory_space mem_space,
258 const event_loc_info &loc_info)
259 : region_creation_event (loc_info),
260 m_mem_space (mem_space)
264 label_text get_desc (bool can_colorize) const final override;
267 enum memory_space m_mem_space;
270 /* Concrete subclass of region_creation_event.
271 Generates a message based on the capacity of the region
272 e.g. "capacity: 100 bytes". */
274 class region_creation_event_capacity : public region_creation_event
277 region_creation_event_capacity (tree capacity,
278 const event_loc_info &loc_info)
279 : region_creation_event (loc_info),
280 m_capacity (capacity)
282 gcc_assert (m_capacity);
285 label_text get_desc (bool can_colorize) const final override;
291 /* Concrete subclass of region_creation_event.
292 Generates a message based on the capacity of the region
293 e.g. "allocated 100 bytes here". */
295 class region_creation_event_allocation_size : public region_creation_event
298 region_creation_event_allocation_size (tree capacity,
299 const event_loc_info &loc_info)
300 : region_creation_event (loc_info),
301 m_capacity (capacity)
304 label_text get_desc (bool can_colorize) const final override;
310 /* Concrete subclass of region_creation_event.
311 Generates a debug message intended for analyzer developers. */
313 class region_creation_event_debug : public region_creation_event
316 region_creation_event_debug (const region *reg, tree capacity,
317 const event_loc_info &loc_info)
318 : region_creation_event (loc_info),
319 m_reg (reg), m_capacity (capacity)
323 label_text get_desc (bool can_colorize) const final override;
330 /* An event subclass describing the entry to a function. */
332 class function_entry_event : public checker_event
335 function_entry_event (const event_loc_info &loc_info)
336 : checker_event (EK_FUNCTION_ENTRY, loc_info)
340 function_entry_event (const program_point &dst_point);
342 label_text get_desc (bool can_colorize) const override;
343 meaning get_meaning () const override;
345 bool is_function_entry_p () const final override { return true; }
348 /* Subclass of checker_event describing a state change. */
350 class state_change_event : public checker_event
353 state_change_event (const supernode *node, const gimple *stmt,
355 const state_machine &sm,
357 state_machine::state_t from,
358 state_machine::state_t to,
359 const svalue *origin,
360 const program_state &dst_state);
362 label_text get_desc (bool can_colorize) const final override;
363 meaning get_meaning () const override;
365 function *get_dest_function () const
367 return m_dst_state.get_current_function ();
370 const supernode *m_node;
371 const gimple *m_stmt;
372 const state_machine &m_sm;
373 const svalue *m_sval;
374 state_machine::state_t m_from;
375 state_machine::state_t m_to;
376 const svalue *m_origin;
377 program_state m_dst_state;
380 /* Subclass of checker_event; parent class for subclasses that relate to
383 class superedge_event : public checker_event
386 /* Mark this edge event as being either an interprocedural call or
387 return in which VAR is in STATE, and that this is critical to the
388 diagnostic (so that get_desc can attempt to get a better description
389 from any pending_diagnostic). */
390 void record_critical_state (tree var, state_machine::state_t state)
393 m_critical_state = state;
396 const callgraph_superedge& get_callgraph_superedge () const;
398 bool should_filter_p (int verbosity) const;
401 superedge_event (enum event_kind kind, const exploded_edge &eedge,
402 const event_loc_info &loc_info);
405 const exploded_edge &m_eedge;
406 const superedge *m_sedge;
408 state_machine::state_t m_critical_state;
411 /* An abstract event subclass for when a CFG edge is followed; it has two
412 subclasses, representing the start of the edge and the end of the
413 edge, which come in pairs. */
415 class cfg_edge_event : public superedge_event
418 meaning get_meaning () const override;
420 const cfg_superedge& get_cfg_superedge () const;
423 cfg_edge_event (enum event_kind kind, const exploded_edge &eedge,
424 const event_loc_info &loc_info);
427 /* A concrete event subclass for the start of a CFG edge
428 e.g. "following 'false' branch...'. */
430 class start_cfg_edge_event : public cfg_edge_event
433 start_cfg_edge_event (const exploded_edge &eedge,
434 const event_loc_info &loc_info)
435 : cfg_edge_event (EK_START_CFG_EDGE, eedge, loc_info)
439 label_text get_desc (bool can_colorize) const final override;
442 label_text maybe_describe_condition (bool can_colorize) const;
444 static label_text maybe_describe_condition (bool can_colorize,
448 static bool should_print_expr_p (tree);
451 /* A concrete event subclass for the end of a CFG edge
452 e.g. "...to here'. */
454 class end_cfg_edge_event : public cfg_edge_event
457 end_cfg_edge_event (const exploded_edge &eedge,
458 const event_loc_info &loc_info)
459 : cfg_edge_event (EK_END_CFG_EDGE, eedge, loc_info)
463 label_text get_desc (bool /*can_colorize*/) const final override
465 return label_text::borrow ("...to here");
469 /* A concrete event subclass for an interprocedural call. */
471 class call_event : public superedge_event
474 call_event (const exploded_edge &eedge,
475 const event_loc_info &loc_info);
477 label_text get_desc (bool can_colorize) const override;
478 meaning get_meaning () const override;
480 bool is_call_p () const final override;
483 tree get_caller_fndecl () const;
484 tree get_callee_fndecl () const;
486 const supernode *m_src_snode;
487 const supernode *m_dest_snode;
490 /* A concrete event subclass for an interprocedural return. */
492 class return_event : public superedge_event
495 return_event (const exploded_edge &eedge,
496 const event_loc_info &loc_info);
498 label_text get_desc (bool can_colorize) const final override;
499 meaning get_meaning () const override;
501 bool is_return_p () const final override;
503 const supernode *m_src_snode;
504 const supernode *m_dest_snode;
507 /* A concrete event subclass for the start of a consolidated run of CFG
508 edges all either TRUE or FALSE e.g. "following 'false' branch...'. */
510 class start_consolidated_cfg_edges_event : public checker_event
513 start_consolidated_cfg_edges_event (const event_loc_info &loc_info,
515 : checker_event (EK_START_CONSOLIDATED_CFG_EDGES, loc_info),
516 m_edge_sense (edge_sense)
520 label_text get_desc (bool can_colorize) const final override;
521 meaning get_meaning () const override;
527 /* A concrete event subclass for the end of a consolidated run of
528 CFG edges e.g. "...to here'. */
530 class end_consolidated_cfg_edges_event : public checker_event
533 end_consolidated_cfg_edges_event (const event_loc_info &loc_info)
534 : checker_event (EK_END_CONSOLIDATED_CFG_EDGES, loc_info)
538 label_text get_desc (bool /*can_colorize*/) const final override
540 return label_text::borrow ("...to here");
544 /* A concrete event subclass for describing an inlined call event
545 e.g. "inlined call to 'callee' from 'caller'". */
547 class inlined_call_event : public checker_event
550 inlined_call_event (location_t loc,
551 tree apparent_callee_fndecl,
552 tree apparent_caller_fndecl,
554 int stack_depth_adjustment)
555 : checker_event (EK_INLINED_CALL,
557 apparent_caller_fndecl,
558 actual_depth + stack_depth_adjustment)),
559 m_apparent_callee_fndecl (apparent_callee_fndecl),
560 m_apparent_caller_fndecl (apparent_caller_fndecl)
562 gcc_assert (LOCATION_BLOCK (loc) == NULL);
565 label_text get_desc (bool /*can_colorize*/) const final override;
566 meaning get_meaning () const override;
569 tree m_apparent_callee_fndecl;
570 tree m_apparent_caller_fndecl;
573 /* A concrete event subclass for a setjmp or sigsetjmp call. */
575 class setjmp_event : public checker_event
578 setjmp_event (const event_loc_info &loc_info,
579 const exploded_node *enode,
580 const gcall *setjmp_call)
581 : checker_event (EK_SETJMP, loc_info),
582 m_enode (enode), m_setjmp_call (setjmp_call)
586 label_text get_desc (bool can_colorize) const final override;
588 void prepare_for_emission (checker_path *path,
589 pending_diagnostic *pd,
590 diagnostic_event_id_t emission_id) final override;
593 const exploded_node *m_enode;
594 const gcall *m_setjmp_call;
597 /* An abstract event subclass for rewinding from a longjmp to a setjmp
598 (or siglongjmp to sigsetjmp).
600 Base class for two from/to subclasses, showing the two halves of the
603 class rewind_event : public checker_event
606 tree get_longjmp_caller () const;
607 tree get_setjmp_caller () const;
608 const exploded_edge *get_eedge () const { return m_eedge; }
611 rewind_event (const exploded_edge *eedge,
612 enum event_kind kind,
613 const event_loc_info &loc_info,
614 const rewind_info_t *rewind_info);
615 const rewind_info_t *m_rewind_info;
618 const exploded_edge *m_eedge;
621 /* A concrete event subclass for rewinding from a longjmp to a setjmp,
622 showing the longjmp (or siglongjmp). */
624 class rewind_from_longjmp_event : public rewind_event
627 rewind_from_longjmp_event (const exploded_edge *eedge,
628 const event_loc_info &loc_info,
629 const rewind_info_t *rewind_info)
630 : rewind_event (eedge, EK_REWIND_FROM_LONGJMP, loc_info,
635 label_text get_desc (bool can_colorize) const final override;
638 /* A concrete event subclass for rewinding from a longjmp to a setjmp,
639 showing the setjmp (or sigsetjmp). */
641 class rewind_to_setjmp_event : public rewind_event
644 rewind_to_setjmp_event (const exploded_edge *eedge,
645 const event_loc_info &loc_info,
646 const rewind_info_t *rewind_info)
647 : rewind_event (eedge, EK_REWIND_TO_SETJMP, loc_info,
652 label_text get_desc (bool can_colorize) const final override;
654 void prepare_for_emission (checker_path *path,
655 pending_diagnostic *pd,
656 diagnostic_event_id_t emission_id) final override;
659 diagnostic_event_id_t m_original_setjmp_event_id;
662 /* Concrete subclass of checker_event for use at the end of a path:
663 a repeat of the warning message at the end of the path (perhaps with
664 references to pertinent events that occurred on the way), at the point
665 where the problem occurs. */
667 class warning_event : public checker_event
670 warning_event (const event_loc_info &loc_info,
671 const state_machine *sm,
672 tree var, state_machine::state_t state)
673 : checker_event (EK_WARNING, loc_info),
674 m_sm (sm), m_var (var), m_state (state)
678 label_text get_desc (bool can_colorize) const final override;
679 meaning get_meaning () const override;
682 const state_machine *m_sm;
684 state_machine::state_t m_state;
689 #endif /* GCC_ANALYZER_CHECKER_EVENT_H */