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