c++: Simplify uses of LAMBDA_EXPR_EXTRA_SCOPE
[official-gcc.git] / gcc / analyzer / checker-event.h
blob4343641f441ce5d34f5cae43dffa1d8ab18a13aa
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)
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_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"
28 namespace ana {
30 /* An enum for discriminating between the concrete subclasses of
31 checker_event. */
33 enum event_kind
35 EK_DEBUG,
36 EK_CUSTOM,
37 EK_STMT,
38 EK_REGION_CREATION,
39 EK_FUNCTION_ENTRY,
40 EK_STATE_CHANGE,
41 EK_START_CFG_EDGE,
42 EK_END_CFG_EDGE,
43 EK_CALL_EDGE,
44 EK_RETURN_EDGE,
45 EK_START_CONSOLIDATED_CFG_EDGES,
46 EK_END_CONSOLIDATED_CFG_EDGES,
47 EK_INLINED_CALL,
48 EK_SETJMP,
49 EK_REWIND_FROM_LONGJMP,
50 EK_REWIND_TO_SETJMP,
51 EK_WARNING
54 extern const char *event_kind_to_string (enum event_kind ek);
56 /* Event subclasses.
58 The class hierarchy looks like this (using indentation to show
59 inheritance, and with event_kinds shown for the concrete subclasses):
61 diagnostic_event
62 checker_event
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)
70 superedge_event
71 cfg_edge_event
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)
80 rewind_event
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
90 public:
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;
99 else
100 return NULL;
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
106 return 0;
109 void
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;
131 void debug () const;
133 void set_location (location_t loc) { m_loc = loc; }
135 protected:
136 checker_event (enum event_kind kind,
137 const event_loc_info &loc_info);
139 public:
140 const enum event_kind m_kind;
141 protected:
142 location_t m_loc;
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
157 public:
159 debug_event (const event_loc_info &loc_info,
160 const char *desc)
161 : checker_event (EK_DEBUG, loc_info),
162 m_desc (xstrdup (desc))
165 ~debug_event ()
167 free (m_desc);
170 label_text get_desc (bool) const final override;
172 private:
173 char *m_desc;
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
181 protected:
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
192 public:
193 precanned_custom_event (const event_loc_info &loc_info,
194 const char *desc)
195 : custom_event (loc_info),
196 m_desc (xstrdup (desc))
199 ~precanned_custom_event ()
201 free (m_desc);
204 label_text get_desc (bool) const final override;
206 private:
207 char *m_desc;
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
215 public:
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
230 region is created.
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
242 protected:
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
252 public:
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;
262 private:
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
272 public:
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;
283 private:
284 tree m_capacity;
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
293 public:
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;
302 private:
303 tree m_capacity;
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
311 public:
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;
321 private:
322 const region *m_reg;
323 tree m_capacity;
326 /* An event subclass describing the entry to a function. */
328 class function_entry_event : public checker_event
330 public:
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
348 public:
349 state_change_event (const supernode *node, const gimple *stmt,
350 int stack_depth,
351 const state_machine &sm,
352 const svalue *sval,
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
381 a superedge. */
383 class superedge_event : public checker_event
385 public:
386 void maybe_add_sarif_properties (sarif_object &thread_flow_loc_obj)
387 const override;
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)
395 m_var = var;
396 m_critical_state = state;
399 const callgraph_superedge& get_callgraph_superedge () const;
401 bool should_filter_p (int verbosity) const;
403 protected:
404 superedge_event (enum event_kind kind, const exploded_edge &eedge,
405 const event_loc_info &loc_info);
407 public:
408 const exploded_edge &m_eedge;
409 const superedge *m_sedge;
410 tree m_var;
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
420 public:
421 meaning get_meaning () const override;
423 const cfg_superedge& get_cfg_superedge () const;
425 protected:
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
435 public:
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; }
445 protected:
446 label_text maybe_describe_condition (bool can_colorize) const;
448 private:
449 static label_text maybe_describe_condition (bool can_colorize,
450 tree lhs,
451 enum tree_code op,
452 tree rhs);
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
461 public:
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
478 public:
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;
487 protected:
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
499 public:
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
517 public:
518 start_consolidated_cfg_edges_event (const event_loc_info &loc_info,
519 bool edge_sense)
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; }
529 private:
530 bool m_edge_sense;
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
538 public:
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
555 public:
556 inlined_call_event (location_t loc,
557 tree apparent_callee_fndecl,
558 tree apparent_caller_fndecl,
559 int actual_depth,
560 int stack_depth_adjustment)
561 : checker_event (EK_INLINED_CALL,
562 event_loc_info (loc,
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;
574 private:
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
583 public:
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;
598 private:
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
607 rewind. */
609 class rewind_event : public checker_event
611 public:
612 tree get_longjmp_caller () const;
613 tree get_setjmp_caller () const;
614 const exploded_edge *get_eedge () const { return m_eedge; }
616 protected:
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;
623 private:
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
632 public:
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,
637 rewind_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
649 public:
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,
654 rewind_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;
664 private:
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
675 public:
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),
681 m_enode (enode),
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; }
691 private:
692 const exploded_node *m_enode;
693 const state_machine *m_sm;
694 tree m_var;
695 state_machine::state_t m_state;
698 } // namespace ana
700 #endif /* GCC_ANALYZER_CHECKER_EVENT_H */