c++: new-expression is potentially constant in C++20
[official-gcc.git] / gcc / analyzer / checker-path.cc
blob8aa5bf716d9cabc310b3d6cd062667ef457dad90
1 /* Subclasses of diagnostic_path and diagnostic_event for analyzer diagnostics.
2 Copyright (C) 2019-2022 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
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.
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.
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/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tree.h"
25 #include "function.h"
26 #include "basic-block.h"
27 #include "gimple.h"
28 #include "gimple-pretty-print.h"
29 #include "fold-const.h"
30 #include "function.h"
31 #include "diagnostic-path.h"
32 #include "options.h"
33 #include "cgraph.h"
34 #include "function.h"
35 #include "cfg.h"
36 #include "digraph.h"
37 #include "alloc-pool.h"
38 #include "fibonacci_heap.h"
39 #include "diagnostic-event-id.h"
40 #include "shortest-paths.h"
41 #include "json.h"
42 #include "analyzer/analyzer.h"
43 #include "analyzer/analyzer-logging.h"
44 #include "analyzer/sm.h"
45 #include "sbitmap.h"
46 #include "bitmap.h"
47 #include "tristate.h"
48 #include "ordered-hash-map.h"
49 #include "selftest.h"
50 #include "analyzer/call-string.h"
51 #include "analyzer/program-point.h"
52 #include "analyzer/store.h"
53 #include "analyzer/region-model.h"
54 #include "analyzer/program-state.h"
55 #include "analyzer/checker-path.h"
56 #include "gimple-iterator.h"
57 #include "analyzer/supergraph.h"
58 #include "analyzer/pending-diagnostic.h"
59 #include "analyzer/diagnostic-manager.h"
60 #include "analyzer/constraint-manager.h"
61 #include "analyzer/diagnostic-manager.h"
62 #include "analyzer/checker-path.h"
63 #include "analyzer/exploded-graph.h"
65 #if ENABLE_ANALYZER
67 namespace ana {
69 /* Get a string for EK. */
71 const char *
72 event_kind_to_string (enum event_kind ek)
74 switch (ek)
76 default:
77 gcc_unreachable ();
78 case EK_DEBUG:
79 return "EK_DEBUG";
80 case EK_CUSTOM:
81 return "EK_CUSTOM";
82 case EK_STMT:
83 return "EK_STMT";
84 case EK_REGION_CREATION:
85 return "EK_REGION_CREATION";
86 case EK_FUNCTION_ENTRY:
87 return "EK_FUNCTION_ENTRY";
88 case EK_STATE_CHANGE:
89 return "EK_STATE_CHANGE";
90 case EK_START_CFG_EDGE:
91 return "EK_START_CFG_EDGE";
92 case EK_END_CFG_EDGE:
93 return "EK_END_CFG_EDGE";
94 case EK_CALL_EDGE:
95 return "EK_CALL_EDGE";
96 case EK_RETURN_EDGE:
97 return "EK_RETURN_EDGE";
98 case EK_START_CONSOLIDATED_CFG_EDGES:
99 return "EK_START_CONSOLIDATED_CFG_EDGES";
100 case EK_END_CONSOLIDATED_CFG_EDGES:
101 return "EK_END_CONSOLIDATED_CFG_EDGES";
102 case EK_SETJMP:
103 return "EK_SETJMP";
104 case EK_REWIND_FROM_LONGJMP:
105 return "EK_REWIND_FROM_LONGJMP";
106 case EK_REWIND_TO_SETJMP:
107 return "EK_REWIND_TO_SETJMP";
108 case EK_WARNING:
109 return "EK_WARNING";
113 /* class checker_event : public diagnostic_event. */
115 /* No-op implementation of diagnostic_event::get_meaning vfunc for
116 checker_event: checker events have no meaning by default. */
118 diagnostic_event::meaning
119 checker_event::get_meaning () const
121 return meaning ();
124 /* Dump this event to PP (for debugging/logging purposes). */
126 void
127 checker_event::dump (pretty_printer *pp) const
129 label_text event_desc (get_desc (false));
130 pp_printf (pp, "\"%s\" (depth %i, m_loc=%x)",
131 event_desc.m_buffer,
132 get_stack_depth (),
133 get_location ());
134 event_desc.maybe_free ();
137 /* Hook for being notified when this event has its final id EMISSION_ID
138 and is about to emitted for PD.
140 Base implementation of checker_event::prepare_for_emission vfunc;
141 subclasses that override this should chain up to it.
143 Record PD and EMISSION_ID, and call the get_desc vfunc, so that any
144 side-effects of the call to get_desc take place before
145 pending_diagnostic::emit is called.
147 For example, state_change_event::get_desc can call
148 pending_diagnostic::describe_state_change; free_of_non_heap can use this
149 to tweak the message (TODO: would be neater to simply capture the
150 pertinent data within the sm-state). */
152 void
153 checker_event::prepare_for_emission (checker_path *,
154 pending_diagnostic *pd,
155 diagnostic_event_id_t emission_id)
157 m_pending_diagnostic = pd;
158 m_emission_id = emission_id;
160 label_text desc = get_desc (false);
161 desc.maybe_free ();
164 /* class debug_event : public checker_event. */
166 /* Implementation of diagnostic_event::get_desc vfunc for
167 debug_event.
168 Use the saved string as the event's description. */
170 label_text
171 debug_event::get_desc (bool) const
173 return label_text::borrow (m_desc);
176 /* class precanned_custom_event : public custom_event. */
178 /* Implementation of diagnostic_event::get_desc vfunc for
179 precanned_custom_event.
180 Use the saved string as the event's description. */
182 label_text
183 precanned_custom_event::get_desc (bool) const
185 return label_text::borrow (m_desc);
188 /* class statement_event : public checker_event. */
190 /* statement_event's ctor. */
192 statement_event::statement_event (const gimple *stmt, tree fndecl, int depth,
193 const program_state &dst_state)
194 : checker_event (EK_STMT, gimple_location (stmt), fndecl, depth),
195 m_stmt (stmt),
196 m_dst_state (dst_state)
200 /* Implementation of diagnostic_event::get_desc vfunc for
201 statement_event.
202 Use the statement's dump form as the event's description. */
204 label_text
205 statement_event::get_desc (bool) const
207 pretty_printer pp;
208 pp_string (&pp, "stmt: ");
209 pp_gimple_stmt_1 (&pp, m_stmt, 0, (dump_flags_t)0);
210 return label_text::take (xstrdup (pp_formatted_text (&pp)));
213 /* class region_creation_event : public checker_event. */
215 region_creation_event::region_creation_event (const region *reg,
216 location_t loc,
217 tree fndecl,
218 int depth)
219 : checker_event (EK_REGION_CREATION, loc, fndecl, depth),
220 m_reg (reg)
224 /* Implementation of diagnostic_event::get_desc vfunc for
225 region_creation_event. */
227 label_text
228 region_creation_event::get_desc (bool) const
230 switch (m_reg->get_memory_space ())
232 default:
233 return label_text::borrow ("region created here");
234 case MEMSPACE_STACK:
235 return label_text::borrow ("region created on stack here");
236 case MEMSPACE_HEAP:
237 return label_text::borrow ("region created on heap here");
241 /* class function_entry_event : public checker_event. */
243 /* Implementation of diagnostic_event::get_desc vfunc for
244 function_entry_event.
246 Use a string such as "entry to 'foo'" as the event's description. */
248 label_text
249 function_entry_event::get_desc (bool can_colorize) const
251 return make_label_text (can_colorize, "entry to %qE", m_fndecl);
254 /* Implementation of diagnostic_event::get_meaning vfunc for
255 function entry. */
257 diagnostic_event::meaning
258 function_entry_event::get_meaning () const
260 return meaning (VERB_enter, NOUN_function);
263 /* class state_change_event : public checker_event. */
265 /* state_change_event's ctor. */
267 state_change_event::state_change_event (const supernode *node,
268 const gimple *stmt,
269 int stack_depth,
270 const state_machine &sm,
271 const svalue *sval,
272 state_machine::state_t from,
273 state_machine::state_t to,
274 const svalue *origin,
275 const program_state &dst_state)
276 : checker_event (EK_STATE_CHANGE,
277 stmt->location, node->m_fun->decl,
278 stack_depth),
279 m_node (node), m_stmt (stmt), m_sm (sm),
280 m_sval (sval), m_from (from), m_to (to),
281 m_origin (origin),
282 m_dst_state (dst_state)
286 /* Implementation of diagnostic_event::get_desc vfunc for
287 state_change_event.
289 Attempt to generate a nicer human-readable description.
290 For greatest precision-of-wording, give the pending diagnostic
291 a chance to describe this state change (in terms of the
292 diagnostic).
293 Note that we only have a pending_diagnostic set on the event once
294 the diagnostic is about to being emitted, so the description for
295 an event can change. */
297 label_text
298 state_change_event::get_desc (bool can_colorize) const
300 if (m_pending_diagnostic)
302 region_model *model = m_dst_state.m_region_model;
303 tree var = model->get_representative_tree (m_sval);
304 tree origin = model->get_representative_tree (m_origin);
305 label_text custom_desc
306 = m_pending_diagnostic->describe_state_change
307 (evdesc::state_change (can_colorize, var, origin,
308 m_from, m_to, m_emission_id, *this));
309 if (custom_desc.m_buffer)
311 if (flag_analyzer_verbose_state_changes)
313 /* Get any "meaning" of event. */
314 diagnostic_event::meaning meaning = get_meaning ();
315 pretty_printer meaning_pp;
316 meaning.dump_to_pp (&meaning_pp);
318 /* Append debug version. */
319 label_text result;
320 if (m_origin)
321 result = make_label_text
322 (can_colorize,
323 "%s (state of %qE: %qs -> %qs, origin: %qE, meaning: %s)",
324 custom_desc.m_buffer,
325 var,
326 m_from->get_name (),
327 m_to->get_name (),
328 origin,
329 pp_formatted_text (&meaning_pp));
330 else
331 result = make_label_text
332 (can_colorize,
333 "%s (state of %qE: %qs -> %qs, NULL origin, meaning: %s)",
334 custom_desc.m_buffer,
335 var,
336 m_from->get_name (),
337 m_to->get_name (),
338 pp_formatted_text (&meaning_pp));
340 custom_desc.maybe_free ();
341 return result;
343 else
344 return custom_desc;
348 /* Fallback description. */
349 if (m_sval)
351 label_text sval_desc = m_sval->get_desc ();
352 label_text result;
353 if (m_origin)
355 label_text origin_desc = m_origin->get_desc ();
356 result = make_label_text
357 (can_colorize,
358 "state of %qs: %qs -> %qs (origin: %qs)",
359 sval_desc.m_buffer,
360 m_from->get_name (),
361 m_to->get_name (),
362 origin_desc.m_buffer);
363 origin_desc.maybe_free ();
365 else
366 result = make_label_text
367 (can_colorize,
368 "state of %qs: %qs -> %qs (NULL origin)",
369 sval_desc.m_buffer,
370 m_from->get_name (),
371 m_to->get_name ());
372 sval_desc.maybe_free ();
373 return result;
375 else
377 gcc_assert (m_origin == NULL);
378 return make_label_text
379 (can_colorize,
380 "global state: %qs -> %qs",
381 m_from->get_name (),
382 m_to->get_name ());
386 /* Implementation of diagnostic_event::get_meaning vfunc for
387 state change events: delegate to the pending_diagnostic to
388 get any meaning. */
390 diagnostic_event::meaning
391 state_change_event::get_meaning () const
393 if (m_pending_diagnostic)
395 region_model *model = m_dst_state.m_region_model;
396 tree var = model->get_representative_tree (m_sval);
397 tree origin = model->get_representative_tree (m_origin);
398 return m_pending_diagnostic->get_meaning_for_state_change
399 (evdesc::state_change (false, var, origin,
400 m_from, m_to, m_emission_id, *this));
402 else
403 return meaning ();
406 /* class superedge_event : public checker_event. */
408 /* Get the callgraph_superedge for this superedge_event, which must be
409 for an interprocedural edge, rather than a CFG edge. */
411 const callgraph_superedge&
412 superedge_event::get_callgraph_superedge () const
414 gcc_assert (m_sedge->m_kind != SUPEREDGE_CFG_EDGE);
415 return *m_sedge->dyn_cast_callgraph_superedge ();
418 /* Determine if this event should be filtered at the given verbosity
419 level. */
421 bool
422 superedge_event::should_filter_p (int verbosity) const
424 switch (m_sedge->m_kind)
426 case SUPEREDGE_CFG_EDGE:
428 if (verbosity < 2)
429 return true;
431 if (verbosity < 4)
433 /* Filter events with empty descriptions. This ought to filter
434 FALLTHRU, but retain true/false/switch edges. */
435 label_text desc = get_desc (false);
436 gcc_assert (desc.m_buffer);
437 if (desc.m_buffer[0] == '\0')
438 return true;
439 desc.maybe_free ();
442 break;
444 default:
445 break;
447 return false;
450 /* superedge_event's ctor. */
452 superedge_event::superedge_event (enum event_kind kind,
453 const exploded_edge &eedge,
454 location_t loc, tree fndecl, int depth)
455 : checker_event (kind, loc, fndecl, depth),
456 m_eedge (eedge), m_sedge (eedge.m_sedge),
457 m_var (NULL_TREE), m_critical_state (0)
461 /* class cfg_edge_event : public superedge_event. */
463 /* Get the cfg_superedge for this cfg_edge_event. */
465 const cfg_superedge &
466 cfg_edge_event::get_cfg_superedge () const
468 return *m_sedge->dyn_cast_cfg_superedge ();
471 /* cfg_edge_event's ctor. */
473 cfg_edge_event::cfg_edge_event (enum event_kind kind,
474 const exploded_edge &eedge,
475 location_t loc, tree fndecl, int depth)
476 : superedge_event (kind, eedge, loc, fndecl, depth)
478 gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_CFG_EDGE);
481 /* Implementation of diagnostic_event::get_meaning vfunc for
482 CFG edge events. */
484 diagnostic_event::meaning
485 cfg_edge_event::get_meaning () const
487 const cfg_superedge& cfg_sedge = get_cfg_superedge ();
488 if (cfg_sedge.true_value_p ())
489 return meaning (VERB_branch, PROPERTY_true);
490 else if (cfg_sedge.false_value_p ())
491 return meaning (VERB_branch, PROPERTY_false);
492 else
493 return meaning ();
496 /* class start_cfg_edge_event : public cfg_edge_event. */
498 /* Implementation of diagnostic_event::get_desc vfunc for
499 start_cfg_edge_event.
501 If -fanalyzer-verbose-edges, then generate low-level descriptions, such
503 "taking 'true' edge SN:7 -> SN:8".
505 Otherwise, generate strings using the label of the underlying CFG if
506 any, such as:
507 "following 'true' branch..." or
508 "following 'case 3' branch..."
509 "following 'default' branch..."
511 For conditionals, attempt to supply a description of the condition that
512 holds, such as:
513 "following 'false' branch (when 'ptr' is non-NULL)..."
515 Failing that, return an empty description (which will lead to this event
516 being filtered). */
518 label_text
519 start_cfg_edge_event::get_desc (bool can_colorize) const
521 bool user_facing = !flag_analyzer_verbose_edges;
522 char *edge_desc = m_sedge->get_description (user_facing);
523 if (user_facing)
525 if (edge_desc && strlen (edge_desc) > 0)
527 label_text cond_desc = maybe_describe_condition (can_colorize);
528 label_text result;
529 if (cond_desc.m_buffer)
531 result = make_label_text (can_colorize,
532 "following %qs branch (%s)...",
533 edge_desc, cond_desc.m_buffer);
534 cond_desc.maybe_free ();
536 else
538 result = make_label_text (can_colorize,
539 "following %qs branch...",
540 edge_desc);
542 free (edge_desc);
543 return result;
545 else
547 free (edge_desc);
548 return label_text::borrow ("");
551 else
553 if (strlen (edge_desc) > 0)
555 label_text result
556 = make_label_text (can_colorize,
557 "taking %qs edge SN:%i -> SN:%i",
558 edge_desc,
559 m_sedge->m_src->m_index,
560 m_sedge->m_dest->m_index);
561 free (edge_desc);
562 return result;
564 else
566 free (edge_desc);
567 return make_label_text (can_colorize,
568 "taking edge SN:%i -> SN:%i",
569 m_sedge->m_src->m_index,
570 m_sedge->m_dest->m_index);
575 /* Attempt to generate a description of any condition that holds at this edge.
577 The intent is to make the user-facing messages more clear, especially for
578 cases where there's a single or double-negative, such as
579 when describing the false branch of an inverted condition.
581 For example, rather than printing just:
583 | if (!ptr)
586 | (1) following 'false' branch...
588 it's clearer to spell out the condition that holds:
590 | if (!ptr)
593 | (1) following 'false' branch (when 'ptr' is non-NULL)...
594 ^^^^^^^^^^^^^^^^^^^^^^
596 In the above example, this function would generate the highlighted
597 string: "when 'ptr' is non-NULL".
599 If the edge is not a condition, or it's not clear that a description of
600 the condition would be helpful to the user, return NULL. */
602 label_text
603 start_cfg_edge_event::maybe_describe_condition (bool can_colorize) const
605 const cfg_superedge& cfg_sedge = get_cfg_superedge ();
607 if (cfg_sedge.true_value_p () || cfg_sedge.false_value_p ())
609 const gimple *last_stmt = m_sedge->m_src->get_last_stmt ();
610 if (const gcond *cond_stmt = dyn_cast <const gcond *> (last_stmt))
612 enum tree_code op = gimple_cond_code (cond_stmt);
613 tree lhs = gimple_cond_lhs (cond_stmt);
614 tree rhs = gimple_cond_rhs (cond_stmt);
615 if (cfg_sedge.false_value_p ())
616 op = invert_tree_comparison (op, false /* honor_nans */);
617 return maybe_describe_condition (can_colorize,
618 lhs, op, rhs);
621 return label_text::borrow (NULL);
624 /* Subroutine of maybe_describe_condition above.
626 Attempt to generate a user-facing description of the condition
627 LHS OP RHS, but only if it is likely to make it easier for the
628 user to understand a condition. */
630 label_text
631 start_cfg_edge_event::maybe_describe_condition (bool can_colorize,
632 tree lhs,
633 enum tree_code op,
634 tree rhs)
636 /* In theory we could just build a tree via
637 fold_build2 (op, boolean_type_node, lhs, rhs)
638 and print it with %qE on it, but this leads to warts such as
639 parenthesizing vars, such as '(i) <= 9', and uses of '<unknown>'. */
641 /* Special-case: describe testing the result of strcmp, as figuring
642 out what the "true" or "false" path is can be confusing to the user. */
643 if (TREE_CODE (lhs) == SSA_NAME
644 && zerop (rhs))
646 if (gcall *call = dyn_cast <gcall *> (SSA_NAME_DEF_STMT (lhs)))
647 if (is_special_named_call_p (call, "strcmp", 2))
649 if (op == EQ_EXPR)
650 return label_text::borrow ("when the strings are equal");
651 if (op == NE_EXPR)
652 return label_text::borrow ("when the strings are non-equal");
656 /* Only attempt to generate text for sufficiently simple expressions. */
657 if (!should_print_expr_p (lhs))
658 return label_text::borrow (NULL);
659 if (!should_print_expr_p (rhs))
660 return label_text::borrow (NULL);
662 /* Special cases for pointer comparisons against NULL. */
663 if (POINTER_TYPE_P (TREE_TYPE (lhs))
664 && POINTER_TYPE_P (TREE_TYPE (rhs))
665 && zerop (rhs))
667 if (op == EQ_EXPR)
668 return make_label_text (can_colorize, "when %qE is NULL",
669 lhs);
670 if (op == NE_EXPR)
671 return make_label_text (can_colorize, "when %qE is non-NULL",
672 lhs);
675 return make_label_text (can_colorize, "when %<%E %s %E%>",
676 lhs, op_symbol_code (op), rhs);
679 /* Subroutine of maybe_describe_condition.
681 Return true if EXPR is we will get suitable user-facing output
682 from %E on it. */
684 bool
685 start_cfg_edge_event::should_print_expr_p (tree expr)
687 if (TREE_CODE (expr) == SSA_NAME)
689 if (SSA_NAME_VAR (expr))
690 return should_print_expr_p (SSA_NAME_VAR (expr));
691 else
692 return false;
695 if (DECL_P (expr))
696 return true;
698 if (CONSTANT_CLASS_P (expr))
699 return true;
701 return false;
704 /* class call_event : public superedge_event. */
706 /* call_event's ctor. */
708 call_event::call_event (const exploded_edge &eedge,
709 location_t loc, tree fndecl, int depth)
710 : superedge_event (EK_CALL_EDGE, eedge, loc, fndecl, depth)
712 if (eedge.m_sedge)
713 gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_CALL);
715 m_src_snode = eedge.m_src->get_supernode ();
716 m_dest_snode = eedge.m_dest->get_supernode ();
719 /* Implementation of diagnostic_event::get_desc vfunc for
720 call_event.
722 If this call event passes critical state for an sm-based warning,
723 allow the diagnostic to generate a precise description, such as:
725 "passing freed pointer 'ptr' in call to 'foo' from 'bar'"
727 Otherwise, generate a description of the form
728 "calling 'foo' from 'bar'". */
730 label_text
731 call_event::get_desc (bool can_colorize) const
733 if (m_critical_state && m_pending_diagnostic)
735 gcc_assert (m_var);
736 tree var = fixup_tree_for_diagnostic (m_var);
737 label_text custom_desc
738 = m_pending_diagnostic->describe_call_with_state
739 (evdesc::call_with_state (can_colorize,
740 m_src_snode->m_fun->decl,
741 m_dest_snode->m_fun->decl,
742 var,
743 m_critical_state));
744 if (custom_desc.m_buffer)
745 return custom_desc;
748 return make_label_text (can_colorize,
749 "calling %qE from %qE",
750 get_callee_fndecl (),
751 get_caller_fndecl ());
754 /* Implementation of diagnostic_event::get_meaning vfunc for
755 function call events. */
757 diagnostic_event::meaning
758 call_event::get_meaning () const
760 return meaning (VERB_call, NOUN_function);
763 /* Override of checker_event::is_call_p for calls. */
765 bool
766 call_event::is_call_p () const
768 return true;
771 tree
772 call_event::get_caller_fndecl () const
774 return m_src_snode->m_fun->decl;
777 tree
778 call_event::get_callee_fndecl () const
780 return m_dest_snode->m_fun->decl;
783 /* class return_event : public superedge_event. */
785 /* return_event's ctor. */
787 return_event::return_event (const exploded_edge &eedge,
788 location_t loc, tree fndecl, int depth)
789 : superedge_event (EK_RETURN_EDGE, eedge, loc, fndecl, depth)
791 if (eedge.m_sedge)
792 gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_RETURN);
794 m_src_snode = eedge.m_src->get_supernode ();
795 m_dest_snode = eedge.m_dest->get_supernode ();
798 /* Implementation of diagnostic_event::get_desc vfunc for
799 return_event.
801 If this return event returns critical state for an sm-based warning,
802 allow the diagnostic to generate a precise description, such as:
804 "possible of NULL to 'foo' from 'bar'"
806 Otherwise, generate a description of the form
807 "returning to 'foo' from 'bar'. */
809 label_text
810 return_event::get_desc (bool can_colorize) const
812 /* For greatest precision-of-wording, if this is returning the
813 state involved in the pending diagnostic, give the pending
814 diagnostic a chance to describe this return (in terms of
815 itself). */
816 if (m_critical_state && m_pending_diagnostic)
818 label_text custom_desc
819 = m_pending_diagnostic->describe_return_of_state
820 (evdesc::return_of_state (can_colorize,
821 m_dest_snode->m_fun->decl,
822 m_src_snode->m_fun->decl,
823 m_critical_state));
824 if (custom_desc.m_buffer)
825 return custom_desc;
827 return make_label_text (can_colorize,
828 "returning to %qE from %qE",
829 m_dest_snode->m_fun->decl,
830 m_src_snode->m_fun->decl);
833 /* Implementation of diagnostic_event::get_meaning vfunc for
834 function return events. */
836 diagnostic_event::meaning
837 return_event::get_meaning () const
839 return meaning (VERB_return, NOUN_function);
842 /* Override of checker_event::is_return_p for returns. */
844 bool
845 return_event::is_return_p () const
847 return true;
850 /* class start_consolidated_cfg_edges_event : public checker_event. */
852 label_text
853 start_consolidated_cfg_edges_event::get_desc (bool can_colorize) const
855 return make_label_text (can_colorize,
856 "following %qs branch...",
857 m_edge_sense ? "true" : "false");
860 /* Implementation of diagnostic_event::get_meaning vfunc for
861 start_consolidated_cfg_edges_event. */
863 diagnostic_event::meaning
864 start_consolidated_cfg_edges_event::get_meaning () const
866 return meaning (VERB_branch,
867 (m_edge_sense ? PROPERTY_true : PROPERTY_false));
870 /* class setjmp_event : public checker_event. */
872 /* Implementation of diagnostic_event::get_desc vfunc for
873 setjmp_event. */
875 label_text
876 setjmp_event::get_desc (bool can_colorize) const
878 return make_label_text (can_colorize,
879 "%qs called here",
880 get_user_facing_name (m_setjmp_call));
883 /* Implementation of checker_event::prepare_for_emission vfunc for setjmp_event.
885 Record this setjmp's event ID into the path, so that rewind events can
886 use it. */
888 void
889 setjmp_event::prepare_for_emission (checker_path *path,
890 pending_diagnostic *pd,
891 diagnostic_event_id_t emission_id)
893 checker_event::prepare_for_emission (path, pd, emission_id);
894 path->record_setjmp_event (m_enode, emission_id);
897 /* class rewind_event : public checker_event. */
899 /* Get the fndecl containing the site of the longjmp call. */
901 tree
902 rewind_event::get_longjmp_caller () const
904 return m_eedge->m_src->get_function ()->decl;
907 /* Get the fndecl containing the site of the setjmp call. */
909 tree
910 rewind_event::get_setjmp_caller () const
912 return m_eedge->m_dest->get_function ()->decl;
915 /* rewind_event's ctor. */
917 rewind_event::rewind_event (const exploded_edge *eedge,
918 enum event_kind kind,
919 location_t loc, tree fndecl, int depth,
920 const rewind_info_t *rewind_info)
921 : checker_event (kind, loc, fndecl, depth),
922 m_rewind_info (rewind_info),
923 m_eedge (eedge)
925 gcc_assert (m_eedge->m_custom_info == m_rewind_info);
928 /* class rewind_from_longjmp_event : public rewind_event. */
930 /* Implementation of diagnostic_event::get_desc vfunc for
931 rewind_from_longjmp_event. */
933 label_text
934 rewind_from_longjmp_event::get_desc (bool can_colorize) const
936 const char *src_name
937 = get_user_facing_name (m_rewind_info->get_longjmp_call ());
939 if (get_longjmp_caller () == get_setjmp_caller ())
940 /* Special-case: purely intraprocedural rewind. */
941 return make_label_text (can_colorize,
942 "rewinding within %qE from %qs...",
943 get_longjmp_caller (),
944 src_name);
945 else
946 return make_label_text (can_colorize,
947 "rewinding from %qs in %qE...",
948 src_name,
949 get_longjmp_caller ());
952 /* class rewind_to_setjmp_event : public rewind_event. */
954 /* Implementation of diagnostic_event::get_desc vfunc for
955 rewind_to_setjmp_event. */
957 label_text
958 rewind_to_setjmp_event::get_desc (bool can_colorize) const
960 const char *dst_name
961 = get_user_facing_name (m_rewind_info->get_setjmp_call ());
963 /* If we can, identify the ID of the setjmp_event. */
964 if (m_original_setjmp_event_id.known_p ())
966 if (get_longjmp_caller () == get_setjmp_caller ())
967 /* Special-case: purely intraprocedural rewind. */
968 return make_label_text (can_colorize,
969 "...to %qs (saved at %@)",
970 dst_name,
971 &m_original_setjmp_event_id);
972 else
973 return make_label_text (can_colorize,
974 "...to %qs in %qE (saved at %@)",
975 dst_name,
976 get_setjmp_caller (),
977 &m_original_setjmp_event_id);
979 else
981 if (get_longjmp_caller () == get_setjmp_caller ())
982 /* Special-case: purely intraprocedural rewind. */
983 return make_label_text (can_colorize,
984 "...to %qs",
985 dst_name,
986 get_setjmp_caller ());
987 else
988 return make_label_text (can_colorize,
989 "...to %qs in %qE",
990 dst_name,
991 get_setjmp_caller ());
995 /* Implementation of checker_event::prepare_for_emission vfunc for
996 rewind_to_setjmp_event.
998 Attempt to look up the setjmp event ID that recorded the jmp_buf
999 for this rewind. */
1001 void
1002 rewind_to_setjmp_event::prepare_for_emission (checker_path *path,
1003 pending_diagnostic *pd,
1004 diagnostic_event_id_t emission_id)
1006 checker_event::prepare_for_emission (path, pd, emission_id);
1007 path->get_setjmp_event (m_rewind_info->get_enode_origin (),
1008 &m_original_setjmp_event_id);
1011 /* class warning_event : public checker_event. */
1013 /* Implementation of diagnostic_event::get_desc vfunc for
1014 warning_event.
1016 If the pending diagnostic implements describe_final_event, use it,
1017 generating a precise description e.g.
1018 "second 'free' here; first 'free' was at (7)"
1020 Otherwise generate a generic description. */
1022 label_text
1023 warning_event::get_desc (bool can_colorize) const
1025 if (m_pending_diagnostic)
1027 tree var = fixup_tree_for_diagnostic (m_var);
1028 label_text ev_desc
1029 = m_pending_diagnostic->describe_final_event
1030 (evdesc::final_event (can_colorize, var, m_state));
1031 if (ev_desc.m_buffer)
1033 if (m_sm && flag_analyzer_verbose_state_changes)
1035 label_text result;
1036 if (var)
1037 result = make_label_text (can_colorize,
1038 "%s (%qE is in state %qs)",
1039 ev_desc.m_buffer,
1040 var, m_state->get_name ());
1041 else
1042 result = make_label_text (can_colorize,
1043 "%s (in global state %qs)",
1044 ev_desc.m_buffer,
1045 m_state->get_name ());
1046 ev_desc.maybe_free ();
1047 return result;
1049 else
1050 return ev_desc;
1054 if (m_sm)
1056 if (m_var)
1057 return make_label_text (can_colorize,
1058 "here (%qE is in state %qs)",
1059 m_var, m_state->get_name ());
1060 else
1061 return make_label_text (can_colorize,
1062 "here (in global state %qs)",
1063 m_state->get_name ());
1065 else
1066 return label_text::borrow ("here");
1069 /* Implementation of diagnostic_event::get_meaning vfunc for
1070 warning_event. */
1072 diagnostic_event::meaning
1073 warning_event::get_meaning () const
1075 return meaning (VERB_danger, NOUN_unknown);
1078 /* Print a single-line representation of this path to PP. */
1080 void
1081 checker_path::dump (pretty_printer *pp) const
1083 pp_character (pp, '[');
1085 checker_event *e;
1086 int i;
1087 FOR_EACH_VEC_ELT (m_events, i, e)
1089 if (i > 0)
1090 pp_string (pp, ", ");
1091 label_text event_desc (e->get_desc (false));
1092 pp_printf (pp, "\"%s\"", event_desc.m_buffer);
1093 event_desc.maybe_free ();
1095 pp_character (pp, ']');
1098 /* Print a multiline form of this path to LOGGER, prefixing it with DESC. */
1100 void
1101 checker_path::maybe_log (logger *logger, const char *desc) const
1103 if (!logger)
1104 return;
1105 logger->start_log_line ();
1106 logger->log_partial ("%s: ", desc);
1107 dump (logger->get_printer ());
1108 logger->end_log_line ();
1109 for (unsigned i = 0; i < m_events.length (); i++)
1111 logger->start_log_line ();
1112 logger->log_partial ("%s[%i]: %s ", desc, i,
1113 event_kind_to_string (m_events[i]->m_kind));
1114 m_events[i]->dump (logger->get_printer ());
1115 logger->end_log_line ();
1119 /* Print a multiline form of this path to STDERR. */
1121 DEBUG_FUNCTION void
1122 checker_path::debug () const
1124 checker_event *e;
1125 int i;
1126 FOR_EACH_VEC_ELT (m_events, i, e)
1128 label_text event_desc (e->get_desc (false));
1129 fprintf (stderr,
1130 "[%i]: %s \"%s\"\n",
1132 event_kind_to_string (m_events[i]->m_kind),
1133 event_desc.m_buffer);
1134 event_desc.maybe_free ();
1138 /* Add region_creation_event instance to this path for REG,
1139 describing whether REG is on the stack or heap. */
1141 void
1142 checker_path::add_region_creation_event (const region *reg,
1143 location_t loc,
1144 tree fndecl, int depth)
1146 add_event (new region_creation_event (reg, loc, fndecl, depth));
1149 /* Add a warning_event to the end of this path. */
1151 void
1152 checker_path::add_final_event (const state_machine *sm,
1153 const exploded_node *enode, const gimple *stmt,
1154 tree var, state_machine::state_t state)
1156 checker_event *end_of_path
1157 = new warning_event (get_stmt_location (stmt, enode->get_function ()),
1158 enode->get_function ()->decl,
1159 enode->get_stack_depth (),
1160 sm, var, state);
1161 add_event (end_of_path);
1164 void
1165 checker_path::fixup_locations (pending_diagnostic *pd)
1167 for (checker_event *e : m_events)
1168 e->set_location (pd->fixup_location (e->get_location ()));
1171 /* Return true if there is a (start_cfg_edge_event, end_cfg_edge_event) pair
1172 at (IDX, IDX + 1). */
1174 bool
1175 checker_path::cfg_edge_pair_at_p (unsigned idx) const
1177 if (m_events.length () < idx + 1)
1178 return false;
1179 return (m_events[idx]->m_kind == EK_START_CFG_EDGE
1180 && m_events[idx + 1]->m_kind == EK_END_CFG_EDGE);
1183 } // namespace ana
1185 #endif /* #if ENABLE_ANALYZER */