Branch data Line data Source code
1 : : /* Subclasses of diagnostics::paths::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 : : #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_edge,
46 : : return_edge,
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_edge)
80 : : return_edge (event_kind::return_edge)
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 : 180 : class checker_event : public diagnostics::paths::event
98 : : {
99 : : public:
100 : : /* Implementation of diagnostics::paths::event. */
101 : :
102 : 58831 : location_t get_location () const final override { return m_loc; }
103 : 15958 : int get_stack_depth () const final override { return m_effective_depth; }
104 : : diagnostics::logical_locations::key
105 : 4910 : get_logical_location () const final override
106 : : {
107 : 4910 : return m_logical_loc;
108 : : }
109 : : meaning get_meaning () const override;
110 : 2857 : bool connect_to_next_event_p () const override { return false; }
111 : 3687 : diagnostics::paths::thread_id_t get_thread_id () const final override
112 : : {
113 : 3687 : 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 : 100916 : enum event_kind get_kind () const { return m_kind; }
123 : 11423 : tree get_fndecl () const { return m_effective_fndecl; }
124 : :
125 : 5607 : 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 : 22701 : virtual bool is_call_p () const { return false; }
131 : 8 : virtual bool is_function_entry_p () const { return false; }
132 : 17399 : 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 : 290 : const diagnostics::paths::event_id_t *get_id_ptr () const
142 : : {
143 : 290 : return &m_emission_id;
144 : : }
145 : :
146 : : void dump (pretty_printer *pp) const;
147 : : void debug () const;
148 : :
149 : 17146 : 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 : 160 : debug_event (const event_loc_info &loc_info,
177 : : const char *desc)
178 : 160 : : checker_event (event_kind::debug, loc_info),
179 : 160 : m_desc (xstrdup (desc))
180 : : {
181 : 160 : }
182 : 160 : ~debug_event ()
183 : : {
184 : 160 : free (m_desc);
185 : 160 : }
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 : 619 : custom_event (const event_loc_info &loc_info)
200 : 614 : : 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 : 592 : region_creation_event_memory_space (enum memory_space mem_space,
277 : : const event_loc_info &loc_info)
278 : 592 : : region_creation_event (loc_info),
279 : 592 : 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 : 800 : region_creation_event_capacity (tree capacity,
297 : : const event_loc_info &loc_info)
298 : 800 : : region_creation_event (loc_info),
299 : 800 : m_capacity (capacity)
300 : : {
301 : 800 : gcc_assert (m_capacity);
302 : 800 : }
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 : 91 : region_creation_event_allocation_size (tree capacity,
318 : : const event_loc_info &loc_info)
319 : 91 : : region_creation_event (loc_info),
320 : 91 : 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 : 1026 : 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 supernode *node, const gimple *stmt,
385 : : int stack_depth,
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 : 164 : const exploded_node *get_exploded_node () const { return m_enode; }
409 : :
410 : : const supernode *m_node;
411 : : const gimple *m_stmt;
412 : : const state_machine &m_sm;
413 : : const svalue *m_sval;
414 : : state_machine::state_t m_from;
415 : : state_machine::state_t m_to;
416 : : const svalue *m_origin;
417 : : program_state m_dst_state;
418 : : const exploded_node *m_enode;
419 : : };
420 : :
421 : : /* Subclass of checker_event; parent class for subclasses that relate to
422 : : a superedge. */
423 : :
424 : 0 : class superedge_event : public checker_event
425 : : {
426 : : public:
427 : : void
428 : : maybe_add_sarif_properties (diagnostics::sarif_builder &,
429 : : diagnostics::sarif_object &thread_flow_loc_obj)
430 : : const override;
431 : :
432 : : /* Mark this edge event as being either an interprocedural call or
433 : : return in which VAR is in STATE, and that this is critical to the
434 : : diagnostic (so that print_desc can attempt to get a better description
435 : : from any pending_diagnostic). */
436 : 269 : void record_critical_state (tree var, state_machine::state_t state)
437 : : {
438 : 269 : m_var = var;
439 : 269 : m_critical_state = state;
440 : 269 : }
441 : :
442 : : const callgraph_superedge& get_callgraph_superedge () const;
443 : :
444 : : bool should_filter_p (int verbosity) const;
445 : :
446 : : const program_state *
447 : : get_program_state () const override;
448 : :
449 : : protected:
450 : : superedge_event (enum event_kind kind, const exploded_edge &eedge,
451 : : const event_loc_info &loc_info);
452 : :
453 : : public:
454 : : const exploded_edge &m_eedge;
455 : : const superedge *m_sedge;
456 : : tree m_var;
457 : : state_machine::state_t m_critical_state;
458 : : };
459 : :
460 : : /* An abstract event subclass for when a CFG edge is followed; it has two
461 : : subclasses, representing the start of the edge and the end of the
462 : : edge, which come in pairs. */
463 : :
464 : : class cfg_edge_event : public superedge_event
465 : : {
466 : : public:
467 : : meaning get_meaning () const override;
468 : :
469 : : const cfg_superedge& get_cfg_superedge () const;
470 : :
471 : : protected:
472 : : cfg_edge_event (enum event_kind kind, const exploded_edge &eedge,
473 : : const event_loc_info &loc_info);
474 : : };
475 : :
476 : : /* A concrete event subclass for the start of a CFG edge
477 : : e.g. "following 'false' branch...'. */
478 : :
479 : : class start_cfg_edge_event : public cfg_edge_event
480 : : {
481 : : public:
482 : 11148 : start_cfg_edge_event (const exploded_edge &eedge,
483 : : const event_loc_info &loc_info)
484 : 11148 : : cfg_edge_event (event_kind::start_cfg_edge, eedge, loc_info)
485 : : {
486 : : }
487 : :
488 : : void print_desc (pretty_printer &pp) const override;
489 : 482 : bool connect_to_next_event_p () const final override { return true; }
490 : :
491 : : protected:
492 : : label_text maybe_describe_condition (bool can_colorize) const;
493 : :
494 : : private:
495 : : static label_text maybe_describe_condition (bool can_colorize,
496 : : tree lhs,
497 : : enum tree_code op,
498 : : tree rhs);
499 : : static bool should_print_expr_p (tree);
500 : : };
501 : :
502 : : /* A concrete event subclass for the end of a CFG edge
503 : : e.g. "...to here'. */
504 : :
505 : : class end_cfg_edge_event : public cfg_edge_event
506 : : {
507 : : public:
508 : 11148 : end_cfg_edge_event (const exploded_edge &eedge,
509 : : const event_loc_info &loc_info)
510 : 11148 : : cfg_edge_event (event_kind::end_cfg_edge, eedge, loc_info)
511 : : {
512 : : }
513 : :
514 : 5022 : void print_desc (pretty_printer &pp) const final override
515 : : {
516 : 5022 : pp_string (&pp, "...to here");
517 : 5022 : }
518 : : };
519 : :
520 : : /* A concrete event subclass for catching an exception
521 : : e.g. "...catching 'struct io_error' here". */
522 : :
523 : : class catch_cfg_edge_event : public cfg_edge_event
524 : : {
525 : : public:
526 : 63 : catch_cfg_edge_event (const exploded_edge &eedge,
527 : : const event_loc_info &loc_info,
528 : : tree type)
529 : 63 : : cfg_edge_event (event_kind::catch_, eedge, loc_info),
530 : 63 : m_type (type)
531 : : {
532 : : }
533 : :
534 : 126 : void print_desc (pretty_printer &pp) const final override
535 : : {
536 : 126 : if (m_type)
537 : 102 : pp_printf (&pp, "...catching exception of type %qT here", m_type);
538 : : else
539 : 24 : pp_string (&pp, "...catching exception here");
540 : 126 : }
541 : :
542 : : private:
543 : : tree m_type;
544 : : };
545 : :
546 : : /* A concrete event subclass for an interprocedural call. */
547 : :
548 : 0 : class call_event : public superedge_event
549 : : {
550 : : public:
551 : : call_event (const exploded_edge &eedge,
552 : : const event_loc_info &loc_info);
553 : :
554 : : void print_desc (pretty_printer &pp) const override;
555 : : meaning get_meaning () const override;
556 : :
557 : : bool is_call_p () const final override;
558 : :
559 : : const program_state *
560 : : get_program_state () const final override;
561 : :
562 : : protected:
563 : : tree get_caller_fndecl () const;
564 : : tree get_callee_fndecl () const;
565 : :
566 : : const supernode *m_src_snode;
567 : : const supernode *m_dest_snode;
568 : : };
569 : :
570 : : /* A concrete event subclass for an interprocedural return. */
571 : :
572 : : class return_event : public superedge_event
573 : : {
574 : : public:
575 : : return_event (const exploded_edge &eedge,
576 : : const event_loc_info &loc_info);
577 : :
578 : : void print_desc (pretty_printer &pp) const final override;
579 : : meaning get_meaning () const override;
580 : :
581 : : bool is_return_p () const final override;
582 : :
583 : : const supernode *m_src_snode;
584 : : const supernode *m_dest_snode;
585 : : };
586 : :
587 : : /* A concrete event subclass for the start of a consolidated run of CFG
588 : : edges all either TRUE or FALSE e.g. "following 'false' branch...'. */
589 : :
590 : : class start_consolidated_cfg_edges_event : public checker_event
591 : : {
592 : : public:
593 : 91 : start_consolidated_cfg_edges_event (const event_loc_info &loc_info,
594 : : bool edge_sense)
595 : 91 : : checker_event (event_kind::start_consolidated_cfg_edges, loc_info),
596 : 91 : m_edge_sense (edge_sense)
597 : : {
598 : : }
599 : :
600 : : void print_desc (pretty_printer &pp) const final override;
601 : : meaning get_meaning () const override;
602 : 0 : bool connect_to_next_event_p () const final override { return true; }
603 : :
604 : : private:
605 : : bool m_edge_sense;
606 : : };
607 : :
608 : : /* A concrete event subclass for the end of a consolidated run of
609 : : CFG edges e.g. "...to here'. */
610 : :
611 : : class end_consolidated_cfg_edges_event : public checker_event
612 : : {
613 : : public:
614 : 91 : end_consolidated_cfg_edges_event (const event_loc_info &loc_info)
615 : 91 : : checker_event (event_kind::end_consolidated_cfg_edges, loc_info)
616 : : {
617 : : }
618 : :
619 : 165 : void print_desc (pretty_printer &pp) const final override
620 : : {
621 : 165 : pp_string (&pp, "...to here");
622 : 165 : }
623 : : };
624 : :
625 : : /* A concrete event subclass for describing an inlined call event
626 : : e.g. "inlined call to 'callee' from 'caller'". */
627 : :
628 : : class inlined_call_event : public checker_event
629 : : {
630 : : public:
631 : 170 : inlined_call_event (location_t loc,
632 : : tree apparent_callee_fndecl,
633 : : tree apparent_caller_fndecl,
634 : : int actual_depth,
635 : : int stack_depth_adjustment)
636 : 170 : : checker_event (event_kind::inlined_call,
637 : 170 : event_loc_info (loc,
638 : : apparent_caller_fndecl,
639 : 170 : actual_depth + stack_depth_adjustment)),
640 : 170 : m_apparent_callee_fndecl (apparent_callee_fndecl),
641 : 170 : m_apparent_caller_fndecl (apparent_caller_fndecl)
642 : : {
643 : 170 : gcc_assert (LOCATION_BLOCK (loc) == NULL);
644 : 170 : }
645 : :
646 : : void print_desc (pretty_printer &) const final override;
647 : : meaning get_meaning () const override;
648 : :
649 : : private:
650 : : tree m_apparent_callee_fndecl;
651 : : tree m_apparent_caller_fndecl;
652 : : };
653 : :
654 : : /* A concrete event subclass for a setjmp or sigsetjmp call. */
655 : :
656 : : class setjmp_event : public checker_event
657 : : {
658 : : public:
659 : 20 : setjmp_event (const event_loc_info &loc_info,
660 : : const exploded_node *enode,
661 : : const gcall &setjmp_call)
662 : 20 : : checker_event (event_kind::setjmp_, loc_info),
663 : 20 : m_enode (enode), m_setjmp_call (setjmp_call)
664 : : {
665 : : }
666 : :
667 : : void print_desc (pretty_printer &pp) const final override;
668 : :
669 : : void prepare_for_emission (checker_path *path,
670 : : pending_diagnostic *pd,
671 : : diagnostics::paths::event_id_t emission_id) final override;
672 : :
673 : : private:
674 : : const exploded_node *m_enode;
675 : : const gcall &m_setjmp_call;
676 : : };
677 : :
678 : : /* An abstract event subclass for rewinding from a longjmp to a setjmp
679 : : (or siglongjmp to sigsetjmp).
680 : :
681 : : Base class for two from/to subclasses, showing the two halves of the
682 : : rewind. */
683 : :
684 : : class rewind_event : public checker_event
685 : : {
686 : : public:
687 : : tree get_longjmp_caller () const;
688 : : tree get_setjmp_caller () const;
689 : : const exploded_edge *get_eedge () const { return m_eedge; }
690 : :
691 : : protected:
692 : : rewind_event (const exploded_edge *eedge,
693 : : enum event_kind kind,
694 : : const event_loc_info &loc_info,
695 : : const rewind_info_t *rewind_info);
696 : : const rewind_info_t *m_rewind_info;
697 : :
698 : : private:
699 : : const exploded_edge *m_eedge;
700 : : };
701 : :
702 : : /* A concrete event subclass for rewinding from a longjmp to a setjmp,
703 : : showing the longjmp (or siglongjmp). */
704 : :
705 : : class rewind_from_longjmp_event : public rewind_event
706 : : {
707 : : public:
708 : 15 : rewind_from_longjmp_event (const exploded_edge *eedge,
709 : : const event_loc_info &loc_info,
710 : : const rewind_info_t *rewind_info)
711 : 15 : : rewind_event (eedge, event_kind::rewind_from_longjmp, loc_info,
712 : 15 : rewind_info)
713 : : {
714 : : }
715 : :
716 : : void print_desc (pretty_printer &pp) const final override;
717 : : };
718 : :
719 : : /* A concrete event subclass for rewinding from a longjmp to a setjmp,
720 : : showing the setjmp (or sigsetjmp). */
721 : :
722 : : class rewind_to_setjmp_event : public rewind_event
723 : : {
724 : : public:
725 : 15 : rewind_to_setjmp_event (const exploded_edge *eedge,
726 : : const event_loc_info &loc_info,
727 : : const rewind_info_t *rewind_info)
728 : 15 : : rewind_event (eedge, event_kind::rewind_to_setjmp, loc_info,
729 : 15 : rewind_info)
730 : : {
731 : : }
732 : :
733 : : void print_desc (pretty_printer &pp) const final override;
734 : :
735 : : void prepare_for_emission (checker_path *path,
736 : : pending_diagnostic *pd,
737 : : diagnostics::paths::event_id_t emission_id) final override;
738 : :
739 : : private:
740 : : diagnostics::paths::event_id_t m_original_setjmp_event_id;
741 : : };
742 : :
743 : : /* An abstract subclass for throwing/rethrowing an exception. */
744 : :
745 : : class throw_event : public checker_event
746 : : {
747 : : public:
748 : 85 : throw_event (const event_loc_info &loc_info,
749 : : const exploded_node *enode,
750 : : const gcall &throw_call)
751 : 85 : : checker_event (event_kind::throw_, loc_info),
752 : 85 : m_enode (enode),
753 : 170 : m_throw_call (throw_call)
754 : : {
755 : : }
756 : :
757 : : protected:
758 : : const exploded_node *m_enode;
759 : : const gcall &m_throw_call;
760 : : };
761 : :
762 : : /* A concrete event subclass for an explicit "throw EXC;"
763 : : or "throw;" (actually, a call to __cxa_throw or __cxa_rethrow). */
764 : :
765 : : class explicit_throw_event : public throw_event
766 : : {
767 : : public:
768 : 63 : explicit_throw_event (const event_loc_info &loc_info,
769 : : const exploded_node *enode,
770 : : const gcall &throw_call,
771 : : tree type,
772 : : bool is_rethrow)
773 : 63 : : throw_event (loc_info, enode, throw_call),
774 : 63 : m_type (type),
775 : 63 : m_is_rethrow (is_rethrow)
776 : : {
777 : : }
778 : :
779 : : void print_desc (pretty_printer &pp) const final override;
780 : :
781 : : private:
782 : : tree m_type;
783 : : bool m_is_rethrow;
784 : : };
785 : :
786 : : /* A concrete event subclass for an exception being thrown
787 : : from within a call to a function we don't have the body of,
788 : : or where we don't know what function was called. */
789 : :
790 : : class throw_from_call_to_external_fn_event : public throw_event
791 : : {
792 : : public:
793 : 22 : throw_from_call_to_external_fn_event (const event_loc_info &loc_info,
794 : : const exploded_node *enode,
795 : : const gcall &throw_call,
796 : : tree fndecl)
797 : 22 : : throw_event (loc_info, enode, throw_call),
798 : 22 : m_fndecl (fndecl)
799 : : {
800 : : }
801 : :
802 : : void print_desc (pretty_printer &pp) const final override;
803 : :
804 : : private:
805 : : tree m_fndecl;
806 : : };
807 : :
808 : : /* A concrete event subclass for unwinding a stack frame when
809 : : processing an exception. */
810 : :
811 : : class unwind_event : public checker_event
812 : : {
813 : : public:
814 : 16 : unwind_event (const event_loc_info &loc_info)
815 : 16 : : checker_event (event_kind::unwind, loc_info),
816 : 16 : m_num_frames (1)
817 : : {
818 : : }
819 : :
820 : : void print_desc (pretty_printer &pp) const final override;
821 : :
822 : : int m_num_frames;
823 : : };
824 : :
825 : : /* Concrete subclass of checker_event for use at the end of a path:
826 : : a repeat of the warning message at the end of the path (perhaps with
827 : : references to pertinent events that occurred on the way), at the point
828 : : where the problem occurs. */
829 : :
830 : : class warning_event : public checker_event
831 : : {
832 : : public:
833 : 3980 : warning_event (const event_loc_info &loc_info,
834 : : const exploded_node *enode,
835 : : const state_machine *sm,
836 : : tree var, state_machine::state_t state,
837 : : const program_state *program_state_ = nullptr)
838 : 3980 : : checker_event (event_kind::warning, loc_info),
839 : 3980 : m_enode (enode),
840 : 3980 : m_sm (sm), m_var (var), m_state (state)
841 : : {
842 : 3980 : if (program_state_)
843 : 832 : m_program_state = std::make_unique<program_state> (*program_state_);
844 : 3761 : }
845 : :
846 : : void print_desc (pretty_printer &pp) const final override;
847 : : meaning get_meaning () const override;
848 : :
849 : : const program_state *
850 : : get_program_state () const final override;
851 : :
852 : 164 : const exploded_node *get_exploded_node () const { return m_enode; }
853 : :
854 : : private:
855 : : const exploded_node *m_enode;
856 : : const state_machine *m_sm;
857 : : tree m_var;
858 : : state_machine::state_t m_state;
859 : : /* Optional copy of program state, for when this is different from
860 : : m_enode's state: */
861 : : std::unique_ptr<program_state> m_program_state;
862 : : };
863 : :
864 : : } // namespace ana
865 : :
866 : : #endif /* GCC_ANALYZER_CHECKER_EVENT_H */
|