Line data Source code
1 : /* Subclasses of diagnostics::paths::event for analyzer diagnostics.
2 : Copyright (C) 2019-2026 Free Software Foundation, Inc.
3 : Contributed by David Malcolm <dmalcolm@redhat.com>.
4 :
5 : This file is part of GCC.
6 :
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.
11 :
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.
16 :
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/>. */
20 :
21 : #ifndef GCC_ANALYZER_CHECKER_EVENT_H
22 : #define GCC_ANALYZER_CHECKER_EVENT_H
23 :
24 : #include "tree-logical-location.h"
25 : #include "analyzer/program-state.h"
26 : #include "analyzer/event-loc-info.h"
27 : #include "diagnostics/digraphs.h"
28 :
29 : namespace ana {
30 :
31 : /* An enum for discriminating between the concrete subclasses of
32 : checker_event. */
33 :
34 : enum class event_kind
35 : {
36 : debug,
37 : custom,
38 : stmt,
39 : region_creation,
40 : function_entry,
41 : state_change,
42 : start_cfg_edge,
43 : end_cfg_edge,
44 : catch_,
45 : call_,
46 : return_,
47 : start_consolidated_cfg_edges,
48 : end_consolidated_cfg_edges,
49 : inlined_call,
50 : setjmp_,
51 : rewind_from_longjmp,
52 : rewind_to_setjmp,
53 : throw_,
54 : unwind,
55 : warning
56 : };
57 :
58 : extern const char *event_kind_to_string (enum event_kind ek);
59 :
60 : /* Event subclasses.
61 :
62 : The class hierarchy looks like this (using indentation to show
63 : inheritance, and with event_kinds shown for the concrete subclasses):
64 :
65 : diagnostics::paths::event
66 : checker_event
67 : debug_event (event_kind::debug)
68 : custom_event (event_kind::custom)
69 : precanned_custom_event
70 : statement_event (event_kind::stmt)
71 : region_creation_event (event_kind::region_creation)
72 : function_entry_event (event_kind::function_entry)
73 : state_change_event (event_kind::state_change)
74 : superedge_event
75 : cfg_edge_event
76 : start_cfg_edge_event (event_kind::start_cfg_edge)
77 : end_cfg_edge_event (event_kind::end_cfg_edge)
78 : catch_cfg_edge_event (event_kind::catch_cfg_edge)
79 : call_event (event_kind::call_)
80 : return_event (event_kind::return_)
81 : start_consolidated_cfg_edges_event (event_kind::start_consolidated_cfg_edges)
82 : end_consolidated_cfg_edges_event (event_kind::end_consolidated_cfg_edges)
83 : inlined_call_event (event_kind::inlined_call)
84 : setjmp_event (event_kind::setjmp_)
85 : rewind_event
86 : rewind_from_longjmp_event (event_kind::rewind_from_longjmp)
87 : rewind_to_setjmp_event (event_kind::rewind_to_setjmp)
88 : throw_event (event_kind:throw_)
89 : explicit_throw_event
90 : throw_from_call_to_external_fn_event
91 : unwind_event (event_kind::unwind)
92 : warning_event (event_kind::warning). */
93 :
94 : /* Abstract subclass of diagnostics::paths::event; the base class for use in
95 : checker_path (the analyzer's diagnostics::paths::path subclass). */
96 :
97 20 : class checker_event : public diagnostics::paths::event
98 : {
99 : public:
100 : /* Implementation of diagnostics::paths::event. */
101 :
102 57898 : location_t get_location () const final override { return m_loc; }
103 15513 : int get_stack_depth () const final override { return m_effective_depth; }
104 : diagnostics::logical_locations::key
105 4905 : get_logical_location () const final override
106 : {
107 4905 : return m_logical_loc;
108 : }
109 : meaning get_meaning () const override;
110 2873 : bool connect_to_next_event_p () const override { return false; }
111 3773 : diagnostics::paths::thread_id_t get_thread_id () const final override
112 : {
113 3773 : return 0;
114 : }
115 :
116 : void
117 : maybe_add_sarif_properties (diagnostics::sarif_builder &,
118 : diagnostics::sarif_object &thread_flow_loc_obj)
119 : const override;
120 :
121 : /* Additional functionality. */
122 68012 : enum event_kind get_kind () const { return m_kind; }
123 10972 : tree get_fndecl () const { return m_effective_fndecl; }
124 :
125 5459 : int get_original_stack_depth () const { return m_original_depth; }
126 :
127 : virtual void prepare_for_emission (checker_path *,
128 : pending_diagnostic *pd,
129 : diagnostics::paths::event_id_t emission_id);
130 20699 : virtual bool is_call_p () const { return false; }
131 8 : virtual bool is_function_entry_p () const { return false; }
132 16730 : virtual bool is_return_p () const { return false; }
133 :
134 : std::unique_ptr<diagnostics::digraphs::digraph>
135 : maybe_make_diagnostic_state_graph (bool debug) const final override;
136 :
137 : virtual const program_state *
138 0 : get_program_state () const { return nullptr; }
139 :
140 : /* For use with %@. */
141 304 : const diagnostics::paths::event_id_t *get_id_ptr () const
142 : {
143 304 : return &m_emission_id;
144 : }
145 :
146 : void dump (pretty_printer *pp) const;
147 : void debug () const;
148 :
149 16707 : void set_location (location_t loc) { m_loc = loc; }
150 :
151 : protected:
152 : checker_event (enum event_kind kind,
153 : const event_loc_info &loc_info);
154 :
155 : private:
156 : const checker_path *m_path;
157 : const enum event_kind m_kind;
158 : protected:
159 : location_t m_loc;
160 : tree m_original_fndecl;
161 : tree m_effective_fndecl;
162 : int m_original_depth;
163 : int m_effective_depth;
164 : pending_diagnostic *m_pending_diagnostic;
165 : diagnostics::paths::event_id_t m_emission_id; // only set once all pruning has occurred
166 : diagnostics::logical_locations::key m_logical_loc;
167 : };
168 :
169 : /* A concrete event subclass for a purely textual event, for use in
170 : debugging path creation and filtering. */
171 :
172 : class debug_event : public checker_event
173 : {
174 : public:
175 :
176 : debug_event (const event_loc_info &loc_info,
177 : const char *desc)
178 : : checker_event (event_kind::debug, loc_info),
179 : m_desc (xstrdup (desc))
180 : {
181 : }
182 0 : ~debug_event ()
183 : {
184 0 : free (m_desc);
185 0 : }
186 :
187 : void print_desc (pretty_printer &) const final override;
188 :
189 : private:
190 : char *m_desc;
191 : };
192 :
193 : /* An abstract event subclass for custom events. These are not filtered,
194 : as they are likely to be pertinent to the diagnostic. */
195 :
196 20 : class custom_event : public checker_event
197 : {
198 : protected:
199 575 : custom_event (const event_loc_info &loc_info)
200 570 : : checker_event (event_kind::custom, loc_info)
201 : {
202 : }
203 : };
204 :
205 : /* A concrete custom_event subclass with a precanned message. */
206 :
207 : class precanned_custom_event : public custom_event
208 : {
209 : public:
210 20 : precanned_custom_event (const event_loc_info &loc_info,
211 : const char *desc)
212 20 : : custom_event (loc_info),
213 20 : m_desc (xstrdup (desc))
214 : {
215 20 : }
216 20 : ~precanned_custom_event ()
217 : {
218 20 : free (m_desc);
219 20 : }
220 :
221 : void print_desc (pretty_printer &) const final override;
222 :
223 : private:
224 : char *m_desc;
225 : };
226 :
227 : /* A concrete event subclass describing the execution of a gimple statement,
228 : for use at high verbosity levels when debugging paths. */
229 :
230 : class statement_event : public checker_event
231 : {
232 : public:
233 : statement_event (const gimple *stmt, tree fndecl, int depth,
234 : const program_state &dst_state);
235 :
236 : void print_desc (pretty_printer &) const final override;
237 :
238 : const program_state *
239 0 : get_program_state () const final override
240 : {
241 0 : return &m_dst_state;
242 : }
243 :
244 : const gimple * const m_stmt;
245 : const program_state m_dst_state;
246 : };
247 :
248 : /* An abstract event subclass describing the creation of a region that
249 : is significant for a diagnostic.
250 :
251 : There are too many combinations to express region creation in one message,
252 : so we emit multiple region_creation_event instances when each pertinent
253 : region is created.
254 :
255 : The events are created by pending_diagnostic's add_region_creation_events
256 : vfunc, which by default creates a region_creation_event_memory_space, and
257 : if a capacity is known, a region_creation_event_capacity, giving e.g.:
258 : (1) region created on stack here
259 : (2) capacity: 100 bytes
260 : but this vfunc can be overridden to create other events if other wordings
261 : are more appropriate foa a given pending_diagnostic. */
262 :
263 : class region_creation_event : public checker_event
264 : {
265 : protected:
266 : region_creation_event (const event_loc_info &loc_info);
267 : };
268 :
269 : /* Concrete subclass of region_creation_event.
270 : Generates a message based on the memory space of the region
271 : e.g. "region created on stack here". */
272 :
273 : class region_creation_event_memory_space : public region_creation_event
274 : {
275 : public:
276 599 : region_creation_event_memory_space (enum memory_space mem_space,
277 : const event_loc_info &loc_info)
278 599 : : region_creation_event (loc_info),
279 599 : m_mem_space (mem_space)
280 : {
281 : }
282 :
283 : void print_desc (pretty_printer &pp) const final override;
284 :
285 : private:
286 : enum memory_space m_mem_space;
287 : };
288 :
289 : /* Concrete subclass of region_creation_event.
290 : Generates a message based on the capacity of the region
291 : e.g. "capacity: 100 bytes". */
292 :
293 : class region_creation_event_capacity : public region_creation_event
294 : {
295 : public:
296 809 : region_creation_event_capacity (tree capacity,
297 : const event_loc_info &loc_info)
298 809 : : region_creation_event (loc_info),
299 809 : m_capacity (capacity)
300 : {
301 809 : gcc_assert (m_capacity);
302 809 : }
303 :
304 : void print_desc (pretty_printer &pp) const final override;
305 :
306 : private:
307 : tree m_capacity;
308 : };
309 :
310 : /* Concrete subclass of region_creation_event.
311 : Generates a message based on the capacity of the region
312 : e.g. "allocated 100 bytes here". */
313 :
314 : class region_creation_event_allocation_size : public region_creation_event
315 : {
316 : public:
317 107 : region_creation_event_allocation_size (tree capacity,
318 : const event_loc_info &loc_info)
319 107 : : region_creation_event (loc_info),
320 107 : m_capacity (capacity)
321 : {}
322 :
323 : void print_desc (pretty_printer &pp) const final override;
324 :
325 : private:
326 : tree m_capacity;
327 : };
328 :
329 : /* Concrete subclass of region_creation_event.
330 : Generates a debug message intended for analyzer developers. */
331 :
332 : class region_creation_event_debug : public region_creation_event
333 : {
334 : public:
335 0 : region_creation_event_debug (const region *reg, tree capacity,
336 : const event_loc_info &loc_info)
337 0 : : region_creation_event (loc_info),
338 0 : m_reg (reg), m_capacity (capacity)
339 : {
340 : }
341 :
342 : void print_desc (pretty_printer &pp) const final override;
343 :
344 : private:
345 : const region *m_reg;
346 : tree m_capacity;
347 : };
348 :
349 : /* An event subclass describing the entry to a function. */
350 :
351 0 : class function_entry_event : public checker_event
352 : {
353 : public:
354 : function_entry_event (const event_loc_info &loc_info,
355 : const program_state &state)
356 : : checker_event (event_kind::function_entry, loc_info),
357 : m_state (state)
358 : {
359 : }
360 :
361 : function_entry_event (const program_point &dst_point,
362 : const program_state &state);
363 :
364 : void print_desc (pretty_printer &pp) const override;
365 : meaning get_meaning () const override;
366 :
367 924 : bool is_function_entry_p () const final override { return true; }
368 :
369 : const program_state *
370 4 : get_program_state () const final override
371 : {
372 4 : return &m_state;
373 : }
374 :
375 : private:
376 : const program_state &m_state;
377 : };
378 :
379 : /* Subclass of checker_event describing a state change. */
380 :
381 : class state_change_event : public checker_event
382 : {
383 : public:
384 : state_change_event (const event_loc_info &loc_info,
385 : const gimple *stmt,
386 : const state_machine &sm,
387 : const svalue *sval,
388 : state_machine::state_t from,
389 : state_machine::state_t to,
390 : const svalue *origin,
391 : const program_state &dst_state,
392 : const exploded_node *enode);
393 :
394 : void print_desc (pretty_printer &pp) const final override;
395 : meaning get_meaning () const override;
396 :
397 : const program_state *
398 3 : get_program_state () const final override
399 : {
400 3 : return &m_dst_state;
401 : }
402 :
403 22 : const function *get_dest_function () const
404 : {
405 22 : return m_dst_state.get_current_function ();
406 : }
407 :
408 160 : const exploded_node *get_exploded_node () const { return m_enode; }
409 :
410 : const gimple *m_stmt;
411 : const state_machine &m_sm;
412 : const svalue *m_sval;
413 : state_machine::state_t m_from;
414 : state_machine::state_t m_to;
415 : const svalue *m_origin;
416 : program_state m_dst_state;
417 : const exploded_node *m_enode;
418 : };
419 :
420 : /* Subclass of checker_event; parent class for subclasses that relate to
421 : a superedge. */
422 :
423 0 : class superedge_event : public checker_event
424 : {
425 : public:
426 : void
427 : maybe_add_sarif_properties (diagnostics::sarif_builder &,
428 : diagnostics::sarif_object &thread_flow_loc_obj)
429 : const override;
430 :
431 : bool should_filter_p (int verbosity) const;
432 :
433 : const program_state *
434 : get_program_state () const override;
435 :
436 : virtual const call_and_return_op *
437 : get_call_and_return_op () const;
438 :
439 : protected:
440 : superedge_event (enum event_kind kind, const exploded_edge &eedge,
441 : const event_loc_info &loc_info);
442 :
443 : public:
444 : const exploded_edge &m_eedge;
445 : const superedge *m_sedge;
446 : };
447 :
448 : /* An abstract event subclass for when a CFG edge is followed; it has two
449 : subclasses, representing the start of the edge and the end of the
450 : edge, which come in pairs. */
451 :
452 : class cfg_edge_event : public superedge_event
453 : {
454 : public:
455 : meaning get_meaning () const override;
456 :
457 : ::edge get_cfg_edge () const;
458 :
459 : bool maybe_get_edge_sense (bool *out) const;
460 :
461 : protected:
462 : cfg_edge_event (enum event_kind kind,
463 : const exploded_edge &eedge,
464 : const event_loc_info &loc_info,
465 : const control_flow_op *op);
466 :
467 : const control_flow_op *m_op;
468 : };
469 :
470 : /* A concrete event subclass for the start of a CFG edge
471 : e.g. "following 'false' branch...'. */
472 :
473 : class start_cfg_edge_event : public cfg_edge_event
474 : {
475 : public:
476 2772 : start_cfg_edge_event (const exploded_edge &eedge,
477 : const event_loc_info &loc_info,
478 : const control_flow_op *op)
479 2772 : : cfg_edge_event (event_kind::start_cfg_edge, eedge, loc_info, op)
480 : {
481 : }
482 :
483 : void print_desc (pretty_printer &pp) const override;
484 482 : bool connect_to_next_event_p () const final override { return true; }
485 :
486 : private:
487 : static bool should_print_expr_p (tree);
488 : };
489 :
490 : /* A concrete event subclass for the end of a CFG edge
491 : e.g. "...to here'. */
492 :
493 : class end_cfg_edge_event : public cfg_edge_event
494 : {
495 : public:
496 2772 : end_cfg_edge_event (const exploded_edge &eedge,
497 : const event_loc_info &loc_info,
498 : const control_flow_op *op)
499 2772 : : cfg_edge_event (event_kind::end_cfg_edge, eedge, loc_info, op)
500 : {
501 : }
502 :
503 4832 : void print_desc (pretty_printer &pp) const final override
504 : {
505 4832 : pp_string (&pp, "...to here");
506 4832 : }
507 : };
508 :
509 : /* A concrete event subclass for catching an exception
510 : e.g. "...catching 'struct io_error' here". */
511 :
512 : class catch_cfg_edge_event : public cfg_edge_event
513 : {
514 : public:
515 63 : catch_cfg_edge_event (const exploded_edge &eedge,
516 : const event_loc_info &loc_info,
517 : const control_flow_op &op,
518 : tree type)
519 63 : : cfg_edge_event (event_kind::catch_, eedge, loc_info, &op),
520 63 : m_type (type)
521 : {
522 : }
523 :
524 138 : void print_desc (pretty_printer &pp) const final override
525 : {
526 138 : if (m_type)
527 114 : pp_printf (&pp, "...catching exception of type %qT here", m_type);
528 : else
529 24 : pp_string (&pp, "...catching exception here");
530 138 : }
531 :
532 : meaning get_meaning () const override;
533 :
534 : private:
535 : tree m_type;
536 : };
537 :
538 : struct critical_state
539 : {
540 1794 : critical_state ()
541 1794 : : m_var (NULL_TREE),
542 601 : m_state (nullptr)
543 : {
544 : }
545 309 : critical_state (tree var, state_machine::state_t state)
546 : : m_var (var),
547 : m_state (state)
548 : {
549 : }
550 :
551 : tree m_var;
552 : state_machine::state_t m_state;
553 : };
554 :
555 : /* A concrete event subclass for an interprocedural call. */
556 :
557 0 : class call_event : public superedge_event
558 : {
559 : public:
560 : call_event (const exploded_edge &eedge,
561 : const event_loc_info &loc_info);
562 :
563 : void print_desc (pretty_printer &pp) const override;
564 : meaning get_meaning () const override;
565 :
566 : bool is_call_p () const final override;
567 :
568 : const program_state *
569 : get_program_state () const final override;
570 :
571 : /* Mark this edge event as being either an interprocedural call or
572 : return in which VAR is in STATE, and that this is critical to the
573 : diagnostic (so that print_desc can attempt to get a better description
574 : from any pending_diagnostic). */
575 215 : void record_critical_state (tree var, state_machine::state_t state)
576 : {
577 215 : m_critical_state = critical_state (var, state);
578 215 : }
579 :
580 : protected:
581 : tree get_caller_fndecl () const;
582 : tree get_callee_fndecl () const;
583 :
584 : const supernode *m_src_snode;
585 : const supernode *m_dest_snode;
586 : critical_state m_critical_state;
587 : };
588 :
589 : /* A concrete event subclass for an interprocedural return. */
590 :
591 : class return_event : public checker_event
592 : {
593 : public:
594 : return_event (const exploded_edge &eedge,
595 : const event_loc_info &loc_info);
596 :
597 : void print_desc (pretty_printer &pp) const final override;
598 : meaning get_meaning () const override;
599 :
600 : bool is_return_p () const final override;
601 :
602 : const call_and_return_op *
603 431 : get_call_and_return_op () const
604 : {
605 431 : return m_call_and_return_op;
606 : }
607 :
608 : const program_state *
609 : get_program_state () const override;
610 :
611 : /* Mark this edge event as being either an interprocedural call or
612 : return in which VAR is in STATE, and that this is critical to the
613 : diagnostic (so that print_desc can attempt to get a better description
614 : from any pending_diagnostic). */
615 94 : void record_critical_state (tree var, state_machine::state_t state)
616 : {
617 94 : m_critical_state = critical_state (var, state);
618 94 : }
619 :
620 : const exploded_edge &m_eedge;
621 : const supernode *m_src_snode;
622 : const supernode *m_dest_snode;
623 : const call_and_return_op *m_call_and_return_op;
624 : critical_state m_critical_state;
625 : };
626 :
627 : /* A concrete event subclass for the start of a consolidated run of CFG
628 : edges all either TRUE or FALSE e.g. "following 'false' branch...'. */
629 :
630 : class start_consolidated_cfg_edges_event : public checker_event
631 : {
632 : public:
633 108 : start_consolidated_cfg_edges_event (const event_loc_info &loc_info,
634 : bool edge_sense)
635 108 : : checker_event (event_kind::start_consolidated_cfg_edges, loc_info),
636 108 : m_edge_sense (edge_sense)
637 : {
638 : }
639 :
640 : void print_desc (pretty_printer &pp) const final override;
641 : meaning get_meaning () const override;
642 0 : bool connect_to_next_event_p () const final override { return true; }
643 :
644 : private:
645 : bool m_edge_sense;
646 : };
647 :
648 : /* A concrete event subclass for the end of a consolidated run of
649 : CFG edges e.g. "...to here'. */
650 :
651 : class end_consolidated_cfg_edges_event : public checker_event
652 : {
653 : public:
654 108 : end_consolidated_cfg_edges_event (const event_loc_info &loc_info)
655 108 : : checker_event (event_kind::end_consolidated_cfg_edges, loc_info)
656 : {
657 : }
658 :
659 200 : void print_desc (pretty_printer &pp) const final override
660 : {
661 200 : pp_string (&pp, "...to here");
662 200 : }
663 : };
664 :
665 : /* A concrete event subclass for describing an inlined call event
666 : e.g. "inlined call to 'callee' from 'caller'". */
667 :
668 : class inlined_call_event : public checker_event
669 : {
670 : public:
671 165 : inlined_call_event (location_t loc,
672 : tree apparent_callee_fndecl,
673 : tree apparent_caller_fndecl,
674 : int actual_depth,
675 : int stack_depth_adjustment)
676 165 : : checker_event (event_kind::inlined_call,
677 165 : event_loc_info (loc,
678 : apparent_caller_fndecl,
679 165 : actual_depth + stack_depth_adjustment)),
680 165 : m_apparent_callee_fndecl (apparent_callee_fndecl),
681 165 : m_apparent_caller_fndecl (apparent_caller_fndecl)
682 : {
683 165 : gcc_assert (LOCATION_BLOCK (loc) == NULL);
684 165 : }
685 :
686 : void print_desc (pretty_printer &) const final override;
687 : meaning get_meaning () const override;
688 :
689 : private:
690 : tree m_apparent_callee_fndecl;
691 : tree m_apparent_caller_fndecl;
692 : };
693 :
694 : /* A concrete event subclass for a setjmp or sigsetjmp call. */
695 :
696 : class setjmp_event : public checker_event
697 : {
698 : public:
699 20 : setjmp_event (const event_loc_info &loc_info,
700 : const exploded_node *enode,
701 : const gcall &setjmp_call)
702 20 : : checker_event (event_kind::setjmp_, loc_info),
703 20 : m_enode (enode), m_setjmp_call (setjmp_call)
704 : {
705 : }
706 :
707 : void print_desc (pretty_printer &pp) const final override;
708 :
709 : meaning get_meaning () const override;
710 :
711 : void prepare_for_emission (checker_path *path,
712 : pending_diagnostic *pd,
713 : diagnostics::paths::event_id_t emission_id) final override;
714 :
715 : private:
716 : const exploded_node *m_enode;
717 : const gcall &m_setjmp_call;
718 : };
719 :
720 : /* An abstract event subclass for rewinding from a longjmp to a setjmp
721 : (or siglongjmp to sigsetjmp).
722 :
723 : Base class for two from/to subclasses, showing the two halves of the
724 : rewind. */
725 :
726 : class rewind_event : public checker_event
727 : {
728 : public:
729 : tree get_longjmp_caller () const;
730 : tree get_setjmp_caller () const;
731 : const exploded_edge *get_eedge () const { return m_eedge; }
732 :
733 : meaning get_meaning () const override;
734 :
735 : protected:
736 : rewind_event (const exploded_edge *eedge,
737 : enum event_kind kind,
738 : const event_loc_info &loc_info,
739 : const rewind_info_t *rewind_info);
740 : const rewind_info_t *m_rewind_info;
741 :
742 : private:
743 : const exploded_edge *m_eedge;
744 : };
745 :
746 : /* A concrete event subclass for rewinding from a longjmp to a setjmp,
747 : showing the longjmp (or siglongjmp). */
748 :
749 : class rewind_from_longjmp_event : public rewind_event
750 : {
751 : public:
752 15 : rewind_from_longjmp_event (const exploded_edge *eedge,
753 : const event_loc_info &loc_info,
754 : const rewind_info_t *rewind_info)
755 15 : : rewind_event (eedge, event_kind::rewind_from_longjmp, loc_info,
756 15 : rewind_info)
757 : {
758 : }
759 :
760 : void print_desc (pretty_printer &pp) const final override;
761 : };
762 :
763 : /* A concrete event subclass for rewinding from a longjmp to a setjmp,
764 : showing the setjmp (or sigsetjmp). */
765 :
766 : class rewind_to_setjmp_event : public rewind_event
767 : {
768 : public:
769 15 : rewind_to_setjmp_event (const exploded_edge *eedge,
770 : const event_loc_info &loc_info,
771 : const rewind_info_t *rewind_info)
772 15 : : rewind_event (eedge, event_kind::rewind_to_setjmp, loc_info,
773 15 : rewind_info)
774 : {
775 : }
776 :
777 : void print_desc (pretty_printer &pp) const final override;
778 :
779 : void prepare_for_emission (checker_path *path,
780 : pending_diagnostic *pd,
781 : diagnostics::paths::event_id_t emission_id) final override;
782 :
783 : private:
784 : diagnostics::paths::event_id_t m_original_setjmp_event_id;
785 : };
786 :
787 : /* An abstract subclass for throwing/rethrowing an exception. */
788 :
789 : class throw_event : public checker_event
790 : {
791 : public:
792 92 : throw_event (const event_loc_info &loc_info,
793 : const exploded_node *enode,
794 : const gcall &throw_call)
795 92 : : checker_event (event_kind::throw_, loc_info),
796 92 : m_enode (enode),
797 184 : m_throw_call (throw_call)
798 : {
799 : }
800 :
801 : meaning get_meaning () const override;
802 :
803 : protected:
804 : const exploded_node *m_enode;
805 : const gcall &m_throw_call;
806 : };
807 :
808 : /* A concrete event subclass for an explicit "throw EXC;"
809 : or "throw;" (actually, a call to __cxa_throw or __cxa_rethrow). */
810 :
811 : class explicit_throw_event : public throw_event
812 : {
813 : public:
814 69 : explicit_throw_event (const event_loc_info &loc_info,
815 : const exploded_node *enode,
816 : const gcall &throw_call,
817 : tree type,
818 : bool is_rethrow)
819 69 : : throw_event (loc_info, enode, throw_call),
820 69 : m_type (type),
821 69 : m_is_rethrow (is_rethrow)
822 : {
823 : }
824 :
825 : void print_desc (pretty_printer &pp) const final override;
826 :
827 : private:
828 : tree m_type;
829 : bool m_is_rethrow;
830 : };
831 :
832 : /* A concrete event subclass for an exception being thrown
833 : from within a call to a function we don't have the body of,
834 : or where we don't know what function was called. */
835 :
836 : class throw_from_call_to_external_fn_event : public throw_event
837 : {
838 : public:
839 23 : throw_from_call_to_external_fn_event (const event_loc_info &loc_info,
840 : const exploded_node *enode,
841 : const gcall &throw_call,
842 : tree fndecl)
843 23 : : throw_event (loc_info, enode, throw_call),
844 23 : m_fndecl (fndecl)
845 : {
846 : }
847 :
848 : void print_desc (pretty_printer &pp) const final override;
849 :
850 : private:
851 : tree m_fndecl;
852 : };
853 :
854 : /* A concrete event subclass for unwinding a stack frame when
855 : processing an exception. */
856 :
857 : class unwind_event : public checker_event
858 : {
859 : public:
860 16 : unwind_event (const event_loc_info &loc_info)
861 16 : : checker_event (event_kind::unwind, loc_info),
862 16 : m_num_frames (1)
863 : {
864 : }
865 :
866 : meaning get_meaning () const override;
867 :
868 : void print_desc (pretty_printer &pp) const final override;
869 :
870 : int m_num_frames;
871 : };
872 :
873 : /* Concrete subclass of checker_event for use at the end of a path:
874 : a repeat of the warning message at the end of the path (perhaps with
875 : references to pertinent events that occurred on the way), at the point
876 : where the problem occurs. */
877 :
878 : class warning_event : public checker_event
879 : {
880 : public:
881 3991 : warning_event (const event_loc_info &loc_info,
882 : const exploded_node *enode,
883 : const state_machine *sm,
884 : tree var, state_machine::state_t state,
885 : const program_state *program_state_ = nullptr)
886 3991 : : checker_event (event_kind::warning, loc_info),
887 3991 : m_enode (enode),
888 3991 : m_sm (sm), m_var (var), m_state (state)
889 : {
890 3991 : if (program_state_)
891 807 : m_program_state = std::make_unique<program_state> (*program_state_);
892 3753 : }
893 :
894 : void print_desc (pretty_printer &pp) const final override;
895 : meaning get_meaning () const override;
896 :
897 : const program_state *
898 : get_program_state () const final override;
899 :
900 164 : const exploded_node *get_exploded_node () const { return m_enode; }
901 :
902 : private:
903 : const exploded_node *m_enode;
904 : const state_machine *m_sm;
905 : tree m_var;
906 : state_machine::state_t m_state;
907 : /* Optional copy of program state, for when this is different from
908 : m_enode's state: */
909 : std::unique_ptr<program_state> m_program_state;
910 : };
911 :
912 : } // namespace ana
913 :
914 : #endif /* GCC_ANALYZER_CHECKER_EVENT_H */
|