1 /* Subclasses of diagnostic_event for analyzer diagnostics.
2 Copyright (C) 2019-2024 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"
26 #include "analyzer/event-loc-info.h"
30 /* An enum for discriminating between the concrete subclasses of
45 EK_START_CONSOLIDATED_CFG_EDGES
,
46 EK_END_CONSOLIDATED_CFG_EDGES
,
49 EK_REWIND_FROM_LONGJMP
,
54 extern const char *event_kind_to_string (enum event_kind ek
);
58 The class hierarchy looks like this (using indentation to show
59 inheritance, and with event_kinds shown for the concrete subclasses):
63 debug_event (EK_DEBUG)
64 custom_event (EK_CUSTOM)
65 precanned_custom_event
66 statement_event (EK_STMT)
67 region_creation_event (EK_REGION_CREATION)
68 function_entry_event (EK_FUNCTION_ENTRY)
69 state_change_event (EK_STATE_CHANGE)
72 start_cfg_edge_event (EK_START_CFG_EDGE)
73 end_cfg_edge_event (EK_END_CFG_EDGE)
74 call_event (EK_CALL_EDGE)
75 return_edge (EK_RETURN_EDGE)
76 start_consolidated_cfg_edges_event (EK_START_CONSOLIDATED_CFG_EDGES)
77 end_consolidated_cfg_edges_event (EK_END_CONSOLIDATED_CFG_EDGES)
78 inlined_call_event (EK_INLINED_CALL)
79 setjmp_event (EK_SETJMP)
81 rewind_from_longjmp_event (EK_REWIND_FROM_LONGJMP)
82 rewind_to_setjmp_event (EK_REWIND_TO_SETJMP)
83 warning_event (EK_WARNING). */
85 /* Abstract subclass of diagnostic_event; the base class for use in
86 checker_path (the analyzer's diagnostic_path subclass). */
88 class checker_event
: public diagnostic_event
91 /* Implementation of diagnostic_event. */
93 location_t
get_location () const final override
{ return m_loc
; }
94 int get_stack_depth () const final override
{ return m_effective_depth
; }
95 const logical_location
*get_logical_location () const final override
97 if (m_effective_fndecl
)
98 return &m_logical_loc
;
102 meaning
get_meaning () const override
;
103 bool connect_to_next_event_p () const override
{ return false; }
104 diagnostic_thread_id_t
get_thread_id () const final override
110 maybe_add_sarif_properties (sarif_object
&thread_flow_loc_obj
) const override
;
112 /* Additional functionality. */
113 tree
get_fndecl () const { return m_effective_fndecl
; }
115 int get_original_stack_depth () const { return m_original_depth
; }
117 virtual void prepare_for_emission (checker_path
*,
118 pending_diagnostic
*pd
,
119 diagnostic_event_id_t emission_id
);
120 virtual bool is_call_p () const { return false; }
121 virtual bool is_function_entry_p () const { return false; }
122 virtual bool is_return_p () const { return false; }
124 /* For use with %@. */
125 const diagnostic_event_id_t
*get_id_ptr () const
127 return &m_emission_id
;
130 void dump (pretty_printer
*pp
) const;
133 void set_location (location_t loc
) { m_loc
= loc
; }
136 checker_event (enum event_kind kind
,
137 const event_loc_info
&loc_info
);
140 const enum event_kind m_kind
;
143 tree m_original_fndecl
;
144 tree m_effective_fndecl
;
145 int m_original_depth
;
146 int m_effective_depth
;
147 pending_diagnostic
*m_pending_diagnostic
;
148 diagnostic_event_id_t m_emission_id
; // only set once all pruning has occurred
149 tree_logical_location m_logical_loc
;
152 /* A concrete event subclass for a purely textual event, for use in
153 debugging path creation and filtering. */
155 class debug_event
: public checker_event
159 debug_event (const event_loc_info
&loc_info
,
161 : checker_event (EK_DEBUG
, loc_info
),
162 m_desc (xstrdup (desc
))
170 label_text
get_desc (bool) const final override
;
176 /* An abstract event subclass for custom events. These are not filtered,
177 as they are likely to be pertinent to the diagnostic. */
179 class custom_event
: public checker_event
182 custom_event (const event_loc_info
&loc_info
)
183 : checker_event (EK_CUSTOM
, loc_info
)
188 /* A concrete custom_event subclass with a precanned message. */
190 class precanned_custom_event
: public custom_event
193 precanned_custom_event (const event_loc_info
&loc_info
,
195 : custom_event (loc_info
),
196 m_desc (xstrdup (desc
))
199 ~precanned_custom_event ()
204 label_text
get_desc (bool) const final override
;
210 /* A concrete event subclass describing the execution of a gimple statement,
211 for use at high verbosity levels when debugging paths. */
213 class statement_event
: public checker_event
216 statement_event (const gimple
*stmt
, tree fndecl
, int depth
,
217 const program_state
&dst_state
);
219 label_text
get_desc (bool) const final override
;
221 const gimple
* const m_stmt
;
222 const program_state m_dst_state
;
225 /* An abstract event subclass describing the creation of a region that
226 is significant for a diagnostic.
228 There are too many combinations to express region creation in one message,
229 so we emit multiple region_creation_event instances when each pertinent
232 The events are created by pending_diagnostic's add_region_creation_events
233 vfunc, which by default creates a region_creation_event_memory_space, and
234 if a capacity is known, a region_creation_event_capacity, giving e.g.:
235 (1) region created on stack here
236 (2) capacity: 100 bytes
237 but this vfunc can be overridden to create other events if other wordings
238 are more appropriate foa a given pending_diagnostic. */
240 class region_creation_event
: public checker_event
243 region_creation_event (const event_loc_info
&loc_info
);
246 /* Concrete subclass of region_creation_event.
247 Generates a message based on the memory space of the region
248 e.g. "region created on stack here". */
250 class region_creation_event_memory_space
: public region_creation_event
253 region_creation_event_memory_space (enum memory_space mem_space
,
254 const event_loc_info
&loc_info
)
255 : region_creation_event (loc_info
),
256 m_mem_space (mem_space
)
260 label_text
get_desc (bool can_colorize
) const final override
;
263 enum memory_space m_mem_space
;
266 /* Concrete subclass of region_creation_event.
267 Generates a message based on the capacity of the region
268 e.g. "capacity: 100 bytes". */
270 class region_creation_event_capacity
: public region_creation_event
273 region_creation_event_capacity (tree capacity
,
274 const event_loc_info
&loc_info
)
275 : region_creation_event (loc_info
),
276 m_capacity (capacity
)
278 gcc_assert (m_capacity
);
281 label_text
get_desc (bool can_colorize
) const final override
;
287 /* Concrete subclass of region_creation_event.
288 Generates a message based on the capacity of the region
289 e.g. "allocated 100 bytes here". */
291 class region_creation_event_allocation_size
: public region_creation_event
294 region_creation_event_allocation_size (tree capacity
,
295 const event_loc_info
&loc_info
)
296 : region_creation_event (loc_info
),
297 m_capacity (capacity
)
300 label_text
get_desc (bool can_colorize
) const final override
;
306 /* Concrete subclass of region_creation_event.
307 Generates a debug message intended for analyzer developers. */
309 class region_creation_event_debug
: public region_creation_event
312 region_creation_event_debug (const region
*reg
, tree capacity
,
313 const event_loc_info
&loc_info
)
314 : region_creation_event (loc_info
),
315 m_reg (reg
), m_capacity (capacity
)
319 label_text
get_desc (bool can_colorize
) const final override
;
326 /* An event subclass describing the entry to a function. */
328 class function_entry_event
: public checker_event
331 function_entry_event (const event_loc_info
&loc_info
)
332 : checker_event (EK_FUNCTION_ENTRY
, loc_info
)
336 function_entry_event (const program_point
&dst_point
);
338 label_text
get_desc (bool can_colorize
) const override
;
339 meaning
get_meaning () const override
;
341 bool is_function_entry_p () const final override
{ return true; }
344 /* Subclass of checker_event describing a state change. */
346 class state_change_event
: public checker_event
349 state_change_event (const supernode
*node
, const gimple
*stmt
,
351 const state_machine
&sm
,
353 state_machine::state_t from
,
354 state_machine::state_t to
,
355 const svalue
*origin
,
356 const program_state
&dst_state
,
357 const exploded_node
*enode
);
359 label_text
get_desc (bool can_colorize
) const final override
;
360 meaning
get_meaning () const override
;
362 const function
*get_dest_function () const
364 return m_dst_state
.get_current_function ();
367 const exploded_node
*get_exploded_node () const { return m_enode
; }
369 const supernode
*m_node
;
370 const gimple
*m_stmt
;
371 const state_machine
&m_sm
;
372 const svalue
*m_sval
;
373 state_machine::state_t m_from
;
374 state_machine::state_t m_to
;
375 const svalue
*m_origin
;
376 program_state m_dst_state
;
377 const exploded_node
*m_enode
;
380 /* Subclass of checker_event; parent class for subclasses that relate to
383 class superedge_event
: public checker_event
386 void maybe_add_sarif_properties (sarif_object
&thread_flow_loc_obj
)
389 /* Mark this edge event as being either an interprocedural call or
390 return in which VAR is in STATE, and that this is critical to the
391 diagnostic (so that get_desc can attempt to get a better description
392 from any pending_diagnostic). */
393 void record_critical_state (tree var
, state_machine::state_t state
)
396 m_critical_state
= state
;
399 const callgraph_superedge
& get_callgraph_superedge () const;
401 bool should_filter_p (int verbosity
) const;
404 superedge_event (enum event_kind kind
, const exploded_edge
&eedge
,
405 const event_loc_info
&loc_info
);
408 const exploded_edge
&m_eedge
;
409 const superedge
*m_sedge
;
411 state_machine::state_t m_critical_state
;
414 /* An abstract event subclass for when a CFG edge is followed; it has two
415 subclasses, representing the start of the edge and the end of the
416 edge, which come in pairs. */
418 class cfg_edge_event
: public superedge_event
421 meaning
get_meaning () const override
;
423 const cfg_superedge
& get_cfg_superedge () const;
426 cfg_edge_event (enum event_kind kind
, const exploded_edge
&eedge
,
427 const event_loc_info
&loc_info
);
430 /* A concrete event subclass for the start of a CFG edge
431 e.g. "following 'false' branch...'. */
433 class start_cfg_edge_event
: public cfg_edge_event
436 start_cfg_edge_event (const exploded_edge
&eedge
,
437 const event_loc_info
&loc_info
)
438 : cfg_edge_event (EK_START_CFG_EDGE
, eedge
, loc_info
)
442 label_text
get_desc (bool can_colorize
) const override
;
443 bool connect_to_next_event_p () const final override
{ return true; }
446 label_text
maybe_describe_condition (bool can_colorize
) const;
449 static label_text
maybe_describe_condition (bool can_colorize
,
453 static bool should_print_expr_p (tree
);
456 /* A concrete event subclass for the end of a CFG edge
457 e.g. "...to here'. */
459 class end_cfg_edge_event
: public cfg_edge_event
462 end_cfg_edge_event (const exploded_edge
&eedge
,
463 const event_loc_info
&loc_info
)
464 : cfg_edge_event (EK_END_CFG_EDGE
, eedge
, loc_info
)
468 label_text
get_desc (bool /*can_colorize*/) const final override
470 return label_text::borrow ("...to here");
474 /* A concrete event subclass for an interprocedural call. */
476 class call_event
: public superedge_event
479 call_event (const exploded_edge
&eedge
,
480 const event_loc_info
&loc_info
);
482 label_text
get_desc (bool can_colorize
) const override
;
483 meaning
get_meaning () const override
;
485 bool is_call_p () const final override
;
488 tree
get_caller_fndecl () const;
489 tree
get_callee_fndecl () const;
491 const supernode
*m_src_snode
;
492 const supernode
*m_dest_snode
;
495 /* A concrete event subclass for an interprocedural return. */
497 class return_event
: public superedge_event
500 return_event (const exploded_edge
&eedge
,
501 const event_loc_info
&loc_info
);
503 label_text
get_desc (bool can_colorize
) const final override
;
504 meaning
get_meaning () const override
;
506 bool is_return_p () const final override
;
508 const supernode
*m_src_snode
;
509 const supernode
*m_dest_snode
;
512 /* A concrete event subclass for the start of a consolidated run of CFG
513 edges all either TRUE or FALSE e.g. "following 'false' branch...'. */
515 class start_consolidated_cfg_edges_event
: public checker_event
518 start_consolidated_cfg_edges_event (const event_loc_info
&loc_info
,
520 : checker_event (EK_START_CONSOLIDATED_CFG_EDGES
, loc_info
),
521 m_edge_sense (edge_sense
)
525 label_text
get_desc (bool can_colorize
) const final override
;
526 meaning
get_meaning () const override
;
527 bool connect_to_next_event_p () const final override
{ return true; }
533 /* A concrete event subclass for the end of a consolidated run of
534 CFG edges e.g. "...to here'. */
536 class end_consolidated_cfg_edges_event
: public checker_event
539 end_consolidated_cfg_edges_event (const event_loc_info
&loc_info
)
540 : checker_event (EK_END_CONSOLIDATED_CFG_EDGES
, loc_info
)
544 label_text
get_desc (bool /*can_colorize*/) const final override
546 return label_text::borrow ("...to here");
550 /* A concrete event subclass for describing an inlined call event
551 e.g. "inlined call to 'callee' from 'caller'". */
553 class inlined_call_event
: public checker_event
556 inlined_call_event (location_t loc
,
557 tree apparent_callee_fndecl
,
558 tree apparent_caller_fndecl
,
560 int stack_depth_adjustment
)
561 : checker_event (EK_INLINED_CALL
,
563 apparent_caller_fndecl
,
564 actual_depth
+ stack_depth_adjustment
)),
565 m_apparent_callee_fndecl (apparent_callee_fndecl
),
566 m_apparent_caller_fndecl (apparent_caller_fndecl
)
568 gcc_assert (LOCATION_BLOCK (loc
) == NULL
);
571 label_text
get_desc (bool /*can_colorize*/) const final override
;
572 meaning
get_meaning () const override
;
575 tree m_apparent_callee_fndecl
;
576 tree m_apparent_caller_fndecl
;
579 /* A concrete event subclass for a setjmp or sigsetjmp call. */
581 class setjmp_event
: public checker_event
584 setjmp_event (const event_loc_info
&loc_info
,
585 const exploded_node
*enode
,
586 const gcall
*setjmp_call
)
587 : checker_event (EK_SETJMP
, loc_info
),
588 m_enode (enode
), m_setjmp_call (setjmp_call
)
592 label_text
get_desc (bool can_colorize
) const final override
;
594 void prepare_for_emission (checker_path
*path
,
595 pending_diagnostic
*pd
,
596 diagnostic_event_id_t emission_id
) final override
;
599 const exploded_node
*m_enode
;
600 const gcall
*m_setjmp_call
;
603 /* An abstract event subclass for rewinding from a longjmp to a setjmp
604 (or siglongjmp to sigsetjmp).
606 Base class for two from/to subclasses, showing the two halves of the
609 class rewind_event
: public checker_event
612 tree
get_longjmp_caller () const;
613 tree
get_setjmp_caller () const;
614 const exploded_edge
*get_eedge () const { return m_eedge
; }
617 rewind_event (const exploded_edge
*eedge
,
618 enum event_kind kind
,
619 const event_loc_info
&loc_info
,
620 const rewind_info_t
*rewind_info
);
621 const rewind_info_t
*m_rewind_info
;
624 const exploded_edge
*m_eedge
;
627 /* A concrete event subclass for rewinding from a longjmp to a setjmp,
628 showing the longjmp (or siglongjmp). */
630 class rewind_from_longjmp_event
: public rewind_event
633 rewind_from_longjmp_event (const exploded_edge
*eedge
,
634 const event_loc_info
&loc_info
,
635 const rewind_info_t
*rewind_info
)
636 : rewind_event (eedge
, EK_REWIND_FROM_LONGJMP
, loc_info
,
641 label_text
get_desc (bool can_colorize
) const final override
;
644 /* A concrete event subclass for rewinding from a longjmp to a setjmp,
645 showing the setjmp (or sigsetjmp). */
647 class rewind_to_setjmp_event
: public rewind_event
650 rewind_to_setjmp_event (const exploded_edge
*eedge
,
651 const event_loc_info
&loc_info
,
652 const rewind_info_t
*rewind_info
)
653 : rewind_event (eedge
, EK_REWIND_TO_SETJMP
, loc_info
,
658 label_text
get_desc (bool can_colorize
) const final override
;
660 void prepare_for_emission (checker_path
*path
,
661 pending_diagnostic
*pd
,
662 diagnostic_event_id_t emission_id
) final override
;
665 diagnostic_event_id_t m_original_setjmp_event_id
;
668 /* Concrete subclass of checker_event for use at the end of a path:
669 a repeat of the warning message at the end of the path (perhaps with
670 references to pertinent events that occurred on the way), at the point
671 where the problem occurs. */
673 class warning_event
: public checker_event
676 warning_event (const event_loc_info
&loc_info
,
677 const exploded_node
*enode
,
678 const state_machine
*sm
,
679 tree var
, state_machine::state_t state
)
680 : checker_event (EK_WARNING
, loc_info
),
682 m_sm (sm
), m_var (var
), m_state (state
)
686 label_text
get_desc (bool can_colorize
) const final override
;
687 meaning
get_meaning () const override
;
689 const exploded_node
*get_exploded_node () const { return m_enode
; }
692 const exploded_node
*m_enode
;
693 const state_machine
*m_sm
;
695 state_machine::state_t m_state
;
700 #endif /* GCC_ANALYZER_CHECKER_EVENT_H */