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