Require target lra in gcc.dg/pr108095.c
[official-gcc.git] / gcc / analyzer / checker-event.h
blob7ba92f196508f0529b9af29b2d503fa22483da04
1 /* Subclasses of diagnostic_event 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_CHECKER_EVENT_H
22 #define GCC_ANALYZER_CHECKER_EVENT_H
24 #include "tree-logical-location.h"
25 #include "analyzer/program-state.h"
27 namespace ana {
29 /* A bundle of location information for a checker_event. */
31 struct event_loc_info
33 event_loc_info (location_t loc, tree fndecl, int depth)
34 : m_loc (loc), m_fndecl (fndecl), m_depth (depth)
37 location_t m_loc;
38 tree m_fndecl;
39 int m_depth;
42 /* An enum for discriminating between the concrete subclasses of
43 checker_event. */
45 enum event_kind
47 EK_DEBUG,
48 EK_CUSTOM,
49 EK_STMT,
50 EK_REGION_CREATION,
51 EK_FUNCTION_ENTRY,
52 EK_STATE_CHANGE,
53 EK_START_CFG_EDGE,
54 EK_END_CFG_EDGE,
55 EK_CALL_EDGE,
56 EK_RETURN_EDGE,
57 EK_START_CONSOLIDATED_CFG_EDGES,
58 EK_END_CONSOLIDATED_CFG_EDGES,
59 EK_INLINED_CALL,
60 EK_SETJMP,
61 EK_REWIND_FROM_LONGJMP,
62 EK_REWIND_TO_SETJMP,
63 EK_WARNING
66 extern const char *event_kind_to_string (enum event_kind ek);
68 /* Event subclasses.
70 The class hierarchy looks like this (using indentation to show
71 inheritance, and with event_kinds shown for the concrete subclasses):
73 diagnostic_event
74 checker_event
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)
82 superedge_event
83 cfg_edge_event
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)
92 rewind_event
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
102 public:
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;
112 else
113 return NULL;
115 meaning get_meaning () const override;
116 diagnostic_thread_id_t get_thread_id () const final override
118 return 0;
121 /* Additional functionality. */
123 int get_original_stack_depth () const { return m_original_depth; }
125 virtual void prepare_for_emission (checker_path *,
126 pending_diagnostic *pd,
127 diagnostic_event_id_t emission_id);
128 virtual bool is_call_p () const { return false; }
129 virtual bool is_function_entry_p () const { return false; }
130 virtual bool is_return_p () const { return false; }
132 /* For use with %@. */
133 const diagnostic_event_id_t *get_id_ptr () const
135 return &m_emission_id;
138 void dump (pretty_printer *pp) const;
139 void debug () const;
141 void set_location (location_t loc) { m_loc = loc; }
143 protected:
144 checker_event (enum event_kind kind,
145 const event_loc_info &loc_info);
147 public:
148 const enum event_kind m_kind;
149 protected:
150 location_t m_loc;
151 tree m_original_fndecl;
152 tree m_effective_fndecl;
153 int m_original_depth;
154 int m_effective_depth;
155 pending_diagnostic *m_pending_diagnostic;
156 diagnostic_event_id_t m_emission_id; // only set once all pruning has occurred
157 tree_logical_location m_logical_loc;
160 /* A concrete event subclass for a purely textual event, for use in
161 debugging path creation and filtering. */
163 class debug_event : public checker_event
165 public:
167 debug_event (const event_loc_info &loc_info,
168 const char *desc)
169 : checker_event (EK_DEBUG, loc_info),
170 m_desc (xstrdup (desc))
173 ~debug_event ()
175 free (m_desc);
178 label_text get_desc (bool) const final override;
180 private:
181 char *m_desc;
184 /* An abstract event subclass for custom events. These are not filtered,
185 as they are likely to be pertinent to the diagnostic. */
187 class custom_event : public checker_event
189 protected:
190 custom_event (const event_loc_info &loc_info)
191 : checker_event (EK_CUSTOM, loc_info)
196 /* A concrete custom_event subclass with a precanned message. */
198 class precanned_custom_event : public custom_event
200 public:
201 precanned_custom_event (const event_loc_info &loc_info,
202 const char *desc)
203 : custom_event (loc_info),
204 m_desc (xstrdup (desc))
207 ~precanned_custom_event ()
209 free (m_desc);
212 label_text get_desc (bool) const final override;
214 private:
215 char *m_desc;
218 /* A concrete event subclass describing the execution of a gimple statement,
219 for use at high verbosity levels when debugging paths. */
221 class statement_event : public checker_event
223 public:
224 statement_event (const gimple *stmt, tree fndecl, int depth,
225 const program_state &dst_state);
227 label_text get_desc (bool) const final override;
229 const gimple * const m_stmt;
230 const program_state m_dst_state;
233 /* An abstract event subclass describing the creation of a region that
234 is significant for a diagnostic.
236 There are too many combinations to express region creation in one message,
237 so we emit multiple region_creation_event instances when each pertinent
238 region is created.
240 The events are created by pending_diagnostic's add_region_creation_events
241 vfunc, which by default creates a region_creation_event_memory_space, and
242 if a capacity is known, a region_creation_event_capacity, giving e.g.:
243 (1) region created on stack here
244 (2) capacity: 100 bytes
245 but this vfunc can be overridden to create other events if other wordings
246 are more appropriate foa a given pending_diagnostic. */
248 class region_creation_event : public checker_event
250 protected:
251 region_creation_event (const event_loc_info &loc_info);
254 /* Concrete subclass of region_creation_event.
255 Generates a message based on the memory space of the region
256 e.g. "region created on stack here". */
258 class region_creation_event_memory_space : public region_creation_event
260 public:
261 region_creation_event_memory_space (enum memory_space mem_space,
262 const event_loc_info &loc_info)
263 : region_creation_event (loc_info),
264 m_mem_space (mem_space)
268 label_text get_desc (bool can_colorize) const final override;
270 private:
271 enum memory_space m_mem_space;
274 /* Concrete subclass of region_creation_event.
275 Generates a message based on the capacity of the region
276 e.g. "capacity: 100 bytes". */
278 class region_creation_event_capacity : public region_creation_event
280 public:
281 region_creation_event_capacity (tree capacity,
282 const event_loc_info &loc_info)
283 : region_creation_event (loc_info),
284 m_capacity (capacity)
286 gcc_assert (m_capacity);
289 label_text get_desc (bool can_colorize) const final override;
291 private:
292 tree m_capacity;
295 /* Concrete subclass of region_creation_event.
296 Generates a message based on the capacity of the region
297 e.g. "allocated 100 bytes here". */
299 class region_creation_event_allocation_size : public region_creation_event
301 public:
302 region_creation_event_allocation_size (tree capacity,
303 const event_loc_info &loc_info)
304 : region_creation_event (loc_info),
305 m_capacity (capacity)
308 label_text get_desc (bool can_colorize) const final override;
310 private:
311 tree m_capacity;
314 /* Concrete subclass of region_creation_event.
315 Generates a debug message intended for analyzer developers. */
317 class region_creation_event_debug : public region_creation_event
319 public:
320 region_creation_event_debug (const region *reg, tree capacity,
321 const event_loc_info &loc_info)
322 : region_creation_event (loc_info),
323 m_reg (reg), m_capacity (capacity)
327 label_text get_desc (bool can_colorize) const final override;
329 private:
330 const region *m_reg;
331 tree m_capacity;
334 /* An event subclass describing the entry to a function. */
336 class function_entry_event : public checker_event
338 public:
339 function_entry_event (const event_loc_info &loc_info)
340 : checker_event (EK_FUNCTION_ENTRY, loc_info)
344 function_entry_event (const program_point &dst_point);
346 label_text get_desc (bool can_colorize) const override;
347 meaning get_meaning () const override;
349 bool is_function_entry_p () const final override { return true; }
352 /* Subclass of checker_event describing a state change. */
354 class state_change_event : public checker_event
356 public:
357 state_change_event (const supernode *node, const gimple *stmt,
358 int stack_depth,
359 const state_machine &sm,
360 const svalue *sval,
361 state_machine::state_t from,
362 state_machine::state_t to,
363 const svalue *origin,
364 const program_state &dst_state,
365 const exploded_node *enode);
367 label_text get_desc (bool can_colorize) const final override;
368 meaning get_meaning () const override;
370 function *get_dest_function () const
372 return m_dst_state.get_current_function ();
375 const exploded_node *get_exploded_node () const { return m_enode; }
377 const supernode *m_node;
378 const gimple *m_stmt;
379 const state_machine &m_sm;
380 const svalue *m_sval;
381 state_machine::state_t m_from;
382 state_machine::state_t m_to;
383 const svalue *m_origin;
384 program_state m_dst_state;
385 const exploded_node *m_enode;
388 /* Subclass of checker_event; parent class for subclasses that relate to
389 a superedge. */
391 class superedge_event : public checker_event
393 public:
394 /* Mark this edge event as being either an interprocedural call or
395 return in which VAR is in STATE, and that this is critical to the
396 diagnostic (so that get_desc can attempt to get a better description
397 from any pending_diagnostic). */
398 void record_critical_state (tree var, state_machine::state_t state)
400 m_var = var;
401 m_critical_state = state;
404 const callgraph_superedge& get_callgraph_superedge () const;
406 bool should_filter_p (int verbosity) const;
408 protected:
409 superedge_event (enum event_kind kind, const exploded_edge &eedge,
410 const event_loc_info &loc_info);
412 public:
413 const exploded_edge &m_eedge;
414 const superedge *m_sedge;
415 tree m_var;
416 state_machine::state_t m_critical_state;
419 /* An abstract event subclass for when a CFG edge is followed; it has two
420 subclasses, representing the start of the edge and the end of the
421 edge, which come in pairs. */
423 class cfg_edge_event : public superedge_event
425 public:
426 meaning get_meaning () const override;
428 const cfg_superedge& get_cfg_superedge () const;
430 protected:
431 cfg_edge_event (enum event_kind kind, const exploded_edge &eedge,
432 const event_loc_info &loc_info);
435 /* A concrete event subclass for the start of a CFG edge
436 e.g. "following 'false' branch...'. */
438 class start_cfg_edge_event : public cfg_edge_event
440 public:
441 start_cfg_edge_event (const exploded_edge &eedge,
442 const event_loc_info &loc_info)
443 : cfg_edge_event (EK_START_CFG_EDGE, eedge, loc_info)
447 label_text get_desc (bool can_colorize) const final override;
449 private:
450 label_text maybe_describe_condition (bool can_colorize) const;
452 static label_text maybe_describe_condition (bool can_colorize,
453 tree lhs,
454 enum tree_code op,
455 tree rhs);
456 static bool should_print_expr_p (tree);
459 /* A concrete event subclass for the end of a CFG edge
460 e.g. "...to here'. */
462 class end_cfg_edge_event : public cfg_edge_event
464 public:
465 end_cfg_edge_event (const exploded_edge &eedge,
466 const event_loc_info &loc_info)
467 : cfg_edge_event (EK_END_CFG_EDGE, eedge, loc_info)
471 label_text get_desc (bool /*can_colorize*/) const final override
473 return label_text::borrow ("...to here");
477 /* A concrete event subclass for an interprocedural call. */
479 class call_event : public superedge_event
481 public:
482 call_event (const exploded_edge &eedge,
483 const event_loc_info &loc_info);
485 label_text get_desc (bool can_colorize) const override;
486 meaning get_meaning () const override;
488 bool is_call_p () const final override;
490 protected:
491 tree get_caller_fndecl () const;
492 tree get_callee_fndecl () const;
494 const supernode *m_src_snode;
495 const supernode *m_dest_snode;
498 /* A concrete event subclass for an interprocedural return. */
500 class return_event : public superedge_event
502 public:
503 return_event (const exploded_edge &eedge,
504 const event_loc_info &loc_info);
506 label_text get_desc (bool can_colorize) const final override;
507 meaning get_meaning () const override;
509 bool is_return_p () const final override;
511 const supernode *m_src_snode;
512 const supernode *m_dest_snode;
515 /* A concrete event subclass for the start of a consolidated run of CFG
516 edges all either TRUE or FALSE e.g. "following 'false' branch...'. */
518 class start_consolidated_cfg_edges_event : public checker_event
520 public:
521 start_consolidated_cfg_edges_event (const event_loc_info &loc_info,
522 bool edge_sense)
523 : checker_event (EK_START_CONSOLIDATED_CFG_EDGES, loc_info),
524 m_edge_sense (edge_sense)
528 label_text get_desc (bool can_colorize) const final override;
529 meaning get_meaning () const override;
531 private:
532 bool m_edge_sense;
535 /* A concrete event subclass for the end of a consolidated run of
536 CFG edges e.g. "...to here'. */
538 class end_consolidated_cfg_edges_event : public checker_event
540 public:
541 end_consolidated_cfg_edges_event (const event_loc_info &loc_info)
542 : checker_event (EK_END_CONSOLIDATED_CFG_EDGES, loc_info)
546 label_text get_desc (bool /*can_colorize*/) const final override
548 return label_text::borrow ("...to here");
552 /* A concrete event subclass for describing an inlined call event
553 e.g. "inlined call to 'callee' from 'caller'". */
555 class inlined_call_event : public checker_event
557 public:
558 inlined_call_event (location_t loc,
559 tree apparent_callee_fndecl,
560 tree apparent_caller_fndecl,
561 int actual_depth,
562 int stack_depth_adjustment)
563 : checker_event (EK_INLINED_CALL,
564 event_loc_info (loc,
565 apparent_caller_fndecl,
566 actual_depth + stack_depth_adjustment)),
567 m_apparent_callee_fndecl (apparent_callee_fndecl),
568 m_apparent_caller_fndecl (apparent_caller_fndecl)
570 gcc_assert (LOCATION_BLOCK (loc) == NULL);
573 label_text get_desc (bool /*can_colorize*/) const final override;
574 meaning get_meaning () const override;
576 private:
577 tree m_apparent_callee_fndecl;
578 tree m_apparent_caller_fndecl;
581 /* A concrete event subclass for a setjmp or sigsetjmp call. */
583 class setjmp_event : public checker_event
585 public:
586 setjmp_event (const event_loc_info &loc_info,
587 const exploded_node *enode,
588 const gcall *setjmp_call)
589 : checker_event (EK_SETJMP, loc_info),
590 m_enode (enode), m_setjmp_call (setjmp_call)
594 label_text get_desc (bool can_colorize) const final override;
596 void prepare_for_emission (checker_path *path,
597 pending_diagnostic *pd,
598 diagnostic_event_id_t emission_id) final override;
600 private:
601 const exploded_node *m_enode;
602 const gcall *m_setjmp_call;
605 /* An abstract event subclass for rewinding from a longjmp to a setjmp
606 (or siglongjmp to sigsetjmp).
608 Base class for two from/to subclasses, showing the two halves of the
609 rewind. */
611 class rewind_event : public checker_event
613 public:
614 tree get_longjmp_caller () const;
615 tree get_setjmp_caller () const;
616 const exploded_edge *get_eedge () const { return m_eedge; }
618 protected:
619 rewind_event (const exploded_edge *eedge,
620 enum event_kind kind,
621 const event_loc_info &loc_info,
622 const rewind_info_t *rewind_info);
623 const rewind_info_t *m_rewind_info;
625 private:
626 const exploded_edge *m_eedge;
629 /* A concrete event subclass for rewinding from a longjmp to a setjmp,
630 showing the longjmp (or siglongjmp). */
632 class rewind_from_longjmp_event : public rewind_event
634 public:
635 rewind_from_longjmp_event (const exploded_edge *eedge,
636 const event_loc_info &loc_info,
637 const rewind_info_t *rewind_info)
638 : rewind_event (eedge, EK_REWIND_FROM_LONGJMP, loc_info,
639 rewind_info)
643 label_text get_desc (bool can_colorize) const final override;
646 /* A concrete event subclass for rewinding from a longjmp to a setjmp,
647 showing the setjmp (or sigsetjmp). */
649 class rewind_to_setjmp_event : public rewind_event
651 public:
652 rewind_to_setjmp_event (const exploded_edge *eedge,
653 const event_loc_info &loc_info,
654 const rewind_info_t *rewind_info)
655 : rewind_event (eedge, EK_REWIND_TO_SETJMP, loc_info,
656 rewind_info)
660 label_text get_desc (bool can_colorize) const final override;
662 void prepare_for_emission (checker_path *path,
663 pending_diagnostic *pd,
664 diagnostic_event_id_t emission_id) final override;
666 private:
667 diagnostic_event_id_t m_original_setjmp_event_id;
670 /* Concrete subclass of checker_event for use at the end of a path:
671 a repeat of the warning message at the end of the path (perhaps with
672 references to pertinent events that occurred on the way), at the point
673 where the problem occurs. */
675 class warning_event : public checker_event
677 public:
678 warning_event (const event_loc_info &loc_info,
679 const exploded_node *enode,
680 const state_machine *sm,
681 tree var, state_machine::state_t state)
682 : checker_event (EK_WARNING, loc_info),
683 m_enode (enode),
684 m_sm (sm), m_var (var), m_state (state)
688 label_text get_desc (bool can_colorize) const final override;
689 meaning get_meaning () const override;
691 const exploded_node *get_exploded_node () const { return m_enode; }
693 private:
694 const exploded_node *m_enode;
695 const state_machine *m_sm;
696 tree m_var;
697 state_machine::state_t m_state;
700 } // namespace ana
702 #endif /* GCC_ANALYZER_CHECKER_EVENT_H */