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