sreal: Fix typo in function name
[official-gcc.git] / gcc / analyzer / checker-event.cc
blob3612df7bd1d36914cf5f00a0c0e3f87a503a5290
1 /* Subclasses of diagnostic_event for analyzer diagnostics.
2 Copyright (C) 2019-2023 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 #define INCLUDE_MEMORY
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tree.h"
26 #include "function.h"
27 #include "basic-block.h"
28 #include "gimple.h"
29 #include "diagnostic-core.h"
30 #include "gimple-pretty-print.h"
31 #include "fold-const.h"
32 #include "diagnostic-path.h"
33 #include "options.h"
34 #include "cgraph.h"
35 #include "cfg.h"
36 #include "digraph.h"
37 #include "diagnostic-event-id.h"
38 #include "analyzer/analyzer.h"
39 #include "analyzer/analyzer-logging.h"
40 #include "analyzer/sm.h"
41 #include "sbitmap.h"
42 #include "bitmap.h"
43 #include "ordered-hash-map.h"
44 #include "analyzer/call-string.h"
45 #include "analyzer/program-point.h"
46 #include "analyzer/store.h"
47 #include "analyzer/region-model.h"
48 #include "analyzer/program-state.h"
49 #include "analyzer/checker-path.h"
50 #include "gimple-iterator.h"
51 #include "inlining-iterator.h"
52 #include "analyzer/supergraph.h"
53 #include "analyzer/pending-diagnostic.h"
54 #include "analyzer/diagnostic-manager.h"
55 #include "analyzer/constraint-manager.h"
56 #include "analyzer/checker-event.h"
57 #include "analyzer/exploded-graph.h"
59 #if ENABLE_ANALYZER
61 namespace ana {
63 /* Get a string for EK. */
65 const char *
66 event_kind_to_string (enum event_kind ek)
68 switch (ek)
70 default:
71 gcc_unreachable ();
72 case EK_DEBUG:
73 return "EK_DEBUG";
74 case EK_CUSTOM:
75 return "EK_CUSTOM";
76 case EK_STMT:
77 return "EK_STMT";
78 case EK_REGION_CREATION:
79 return "EK_REGION_CREATION";
80 case EK_FUNCTION_ENTRY:
81 return "EK_FUNCTION_ENTRY";
82 case EK_STATE_CHANGE:
83 return "EK_STATE_CHANGE";
84 case EK_START_CFG_EDGE:
85 return "EK_START_CFG_EDGE";
86 case EK_END_CFG_EDGE:
87 return "EK_END_CFG_EDGE";
88 case EK_CALL_EDGE:
89 return "EK_CALL_EDGE";
90 case EK_RETURN_EDGE:
91 return "EK_RETURN_EDGE";
92 case EK_START_CONSOLIDATED_CFG_EDGES:
93 return "EK_START_CONSOLIDATED_CFG_EDGES";
94 case EK_END_CONSOLIDATED_CFG_EDGES:
95 return "EK_END_CONSOLIDATED_CFG_EDGES";
96 case EK_INLINED_CALL:
97 return "EK_INLINED_CALL";
98 case EK_SETJMP:
99 return "EK_SETJMP";
100 case EK_REWIND_FROM_LONGJMP:
101 return "EK_REWIND_FROM_LONGJMP";
102 case EK_REWIND_TO_SETJMP:
103 return "EK_REWIND_TO_SETJMP";
104 case EK_WARNING:
105 return "EK_WARNING";
109 /* A class for fixing up fndecls and stack depths in checker_event, based
110 on inlining records.
112 The early inliner runs before the analyzer, which can lead to confusing
113 output.
115 Tne base fndecl and depth within a checker_event are from call strings
116 in program_points, which reflect the call strings after inlining.
117 This class lets us offset the depth and fix up the reported fndecl and
118 stack depth to better reflect the user's original code. */
120 class inlining_info
122 public:
123 inlining_info (location_t loc)
125 inlining_iterator iter (loc);
126 m_inner_fndecl = iter.get_fndecl ();
127 int num_frames = 0;
128 while (!iter.done_p ())
130 m_outer_fndecl = iter.get_fndecl ();
131 num_frames++;
132 iter.next ();
134 if (num_frames > 1)
135 m_extra_frames = num_frames - 1;
136 else
137 m_extra_frames = 0;
140 tree get_inner_fndecl () const { return m_inner_fndecl; }
141 int get_extra_frames () const { return m_extra_frames; }
143 private:
144 tree m_outer_fndecl;
145 tree m_inner_fndecl;
146 int m_extra_frames;
149 /* class checker_event : public diagnostic_event. */
151 /* checker_event's ctor. */
153 checker_event::checker_event (enum event_kind kind,
154 const event_loc_info &loc_info)
155 : m_kind (kind), m_loc (loc_info.m_loc),
156 m_original_fndecl (loc_info.m_fndecl),
157 m_effective_fndecl (loc_info.m_fndecl),
158 m_original_depth (loc_info.m_depth),
159 m_effective_depth (loc_info.m_depth),
160 m_pending_diagnostic (NULL), m_emission_id (),
161 m_logical_loc (loc_info.m_fndecl)
163 /* Update effective fndecl and depth if inlining has been recorded. */
164 if (flag_analyzer_undo_inlining)
166 inlining_info info (m_loc);
167 if (info.get_inner_fndecl ())
169 m_effective_fndecl = info.get_inner_fndecl ();
170 m_effective_depth += info.get_extra_frames ();
171 m_logical_loc = tree_logical_location (m_effective_fndecl);
176 /* No-op implementation of diagnostic_event::get_meaning vfunc for
177 checker_event: checker events have no meaning by default. */
179 diagnostic_event::meaning
180 checker_event::get_meaning () const
182 return meaning ();
185 /* Dump this event to PP (for debugging/logging purposes). */
187 void
188 checker_event::dump (pretty_printer *pp) const
190 label_text event_desc (get_desc (false));
191 pp_printf (pp, "\"%s\" (depth %i",
192 event_desc.get (), m_effective_depth);
194 if (m_effective_depth != m_original_depth)
195 pp_printf (pp, " corrected from %i",
196 m_original_depth);
197 if (m_effective_fndecl)
199 pp_printf (pp, ", fndecl %qE", m_effective_fndecl);
200 if (m_effective_fndecl != m_original_fndecl)
201 pp_printf (pp, " corrected from %qE", m_original_fndecl);
203 pp_printf (pp, ", m_loc=%x)",
204 get_location ());
207 /* Dump this event to stderr (for debugging/logging purposes). */
209 DEBUG_FUNCTION void
210 checker_event::debug () const
212 pretty_printer pp;
213 pp_format_decoder (&pp) = default_tree_printer;
214 pp_show_color (&pp) = pp_show_color (global_dc->printer);
215 pp.buffer->stream = stderr;
216 dump (&pp);
217 pp_newline (&pp);
218 pp_flush (&pp);
221 /* Hook for being notified when this event has its final id EMISSION_ID
222 and is about to emitted for PD.
224 Base implementation of checker_event::prepare_for_emission vfunc;
225 subclasses that override this should chain up to it.
227 Record PD and EMISSION_ID, and call the get_desc vfunc, so that any
228 side-effects of the call to get_desc take place before
229 pending_diagnostic::emit is called.
231 For example, state_change_event::get_desc can call
232 pending_diagnostic::describe_state_change; free_of_non_heap can use this
233 to tweak the message (TODO: would be neater to simply capture the
234 pertinent data within the sm-state). */
236 void
237 checker_event::prepare_for_emission (checker_path *,
238 pending_diagnostic *pd,
239 diagnostic_event_id_t emission_id)
241 m_pending_diagnostic = pd;
242 m_emission_id = emission_id;
244 label_text desc = get_desc (false);
247 /* class debug_event : public checker_event. */
249 /* Implementation of diagnostic_event::get_desc vfunc for
250 debug_event.
251 Use the saved string as the event's description. */
253 label_text
254 debug_event::get_desc (bool) const
256 return label_text::borrow (m_desc);
259 /* class precanned_custom_event : public custom_event. */
261 /* Implementation of diagnostic_event::get_desc vfunc for
262 precanned_custom_event.
263 Use the saved string as the event's description. */
265 label_text
266 precanned_custom_event::get_desc (bool) const
268 return label_text::borrow (m_desc);
271 /* class statement_event : public checker_event. */
273 /* statement_event's ctor. */
275 statement_event::statement_event (const gimple *stmt, tree fndecl, int depth,
276 const program_state &dst_state)
277 : checker_event (EK_STMT,
278 event_loc_info (gimple_location (stmt), fndecl, depth)),
279 m_stmt (stmt),
280 m_dst_state (dst_state)
284 /* Implementation of diagnostic_event::get_desc vfunc for
285 statement_event.
286 Use the statement's dump form as the event's description. */
288 label_text
289 statement_event::get_desc (bool) const
291 pretty_printer pp;
292 pp_string (&pp, "stmt: ");
293 pp_gimple_stmt_1 (&pp, m_stmt, 0, (dump_flags_t)0);
294 return label_text::take (xstrdup (pp_formatted_text (&pp)));
297 /* class region_creation_event : public checker_event. */
299 region_creation_event::region_creation_event (const event_loc_info &loc_info)
300 : checker_event (EK_REGION_CREATION, loc_info)
304 /* The various region_creation_event subclasses' get_desc
305 implementations. */
307 label_text
308 region_creation_event_memory_space::get_desc (bool) const
310 switch (m_mem_space)
312 default:
313 return label_text::borrow ("region created here");
314 case MEMSPACE_STACK:
315 return label_text::borrow ("region created on stack here");
316 case MEMSPACE_HEAP:
317 return label_text::borrow ("region created on heap here");
321 label_text
322 region_creation_event_capacity::get_desc (bool can_colorize) const
324 gcc_assert (m_capacity);
325 if (TREE_CODE (m_capacity) == INTEGER_CST)
327 unsigned HOST_WIDE_INT hwi = tree_to_uhwi (m_capacity);
328 return make_label_text_n (can_colorize,
329 hwi,
330 "capacity: %wu byte",
331 "capacity: %wu bytes",
332 hwi);
334 else
335 return make_label_text (can_colorize,
336 "capacity: %qE bytes", m_capacity);
339 label_text
340 region_creation_event_allocation_size::get_desc (bool can_colorize) const
342 if (m_capacity)
344 if (TREE_CODE (m_capacity) == INTEGER_CST)
345 return make_label_text_n (can_colorize,
346 tree_to_uhwi (m_capacity),
347 "allocated %E byte here",
348 "allocated %E bytes here",
349 m_capacity);
350 else
351 return make_label_text (can_colorize,
352 "allocated %qE bytes here",
353 m_capacity);
355 return make_label_text (can_colorize, "allocated here");
358 label_text
359 region_creation_event_debug::get_desc (bool) const
361 pretty_printer pp;
362 pp_format_decoder (&pp) = default_tree_printer;
363 pp_string (&pp, "region creation: ");
364 m_reg->dump_to_pp (&pp, true);
365 if (m_capacity)
366 pp_printf (&pp, " capacity: %qE", m_capacity);
367 return label_text::take (xstrdup (pp_formatted_text (&pp)));
370 /* class function_entry_event : public checker_event. */
372 function_entry_event::function_entry_event (const program_point &dst_point)
373 : checker_event (EK_FUNCTION_ENTRY,
374 event_loc_info (dst_point.get_supernode
375 ()->get_start_location (),
376 dst_point.get_fndecl (),
377 dst_point.get_stack_depth ()))
381 /* Implementation of diagnostic_event::get_desc vfunc for
382 function_entry_event.
384 Use a string such as "entry to 'foo'" as the event's description. */
386 label_text
387 function_entry_event::get_desc (bool can_colorize) const
389 return make_label_text (can_colorize, "entry to %qE", m_effective_fndecl);
392 /* Implementation of diagnostic_event::get_meaning vfunc for
393 function entry. */
395 diagnostic_event::meaning
396 function_entry_event::get_meaning () const
398 return meaning (VERB_enter, NOUN_function);
401 /* class state_change_event : public checker_event. */
403 /* state_change_event's ctor. */
405 state_change_event::state_change_event (const supernode *node,
406 const gimple *stmt,
407 int stack_depth,
408 const state_machine &sm,
409 const svalue *sval,
410 state_machine::state_t from,
411 state_machine::state_t to,
412 const svalue *origin,
413 const program_state &dst_state,
414 const exploded_node *enode)
415 : checker_event (EK_STATE_CHANGE,
416 event_loc_info (stmt->location,
417 node->m_fun->decl,
418 stack_depth)),
419 m_node (node), m_stmt (stmt), m_sm (sm),
420 m_sval (sval), m_from (from), m_to (to),
421 m_origin (origin),
422 m_dst_state (dst_state),
423 m_enode (enode)
427 /* Implementation of diagnostic_event::get_desc vfunc for
428 state_change_event.
430 Attempt to generate a nicer human-readable description.
431 For greatest precision-of-wording, give the pending diagnostic
432 a chance to describe this state change (in terms of the
433 diagnostic).
434 Note that we only have a pending_diagnostic set on the event once
435 the diagnostic is about to being emitted, so the description for
436 an event can change. */
438 label_text
439 state_change_event::get_desc (bool can_colorize) const
441 if (m_pending_diagnostic)
443 region_model *model = m_dst_state.m_region_model;
444 tree var = model->get_representative_tree (m_sval);
445 tree origin = model->get_representative_tree (m_origin);
446 label_text custom_desc
447 = m_pending_diagnostic->describe_state_change
448 (evdesc::state_change (can_colorize, var, origin,
449 m_from, m_to, m_emission_id, *this));
450 if (custom_desc.get ())
452 if (flag_analyzer_verbose_state_changes)
454 /* Get any "meaning" of event. */
455 diagnostic_event::meaning meaning = get_meaning ();
456 pretty_printer meaning_pp;
457 meaning.dump_to_pp (&meaning_pp);
459 /* Append debug version. */
460 if (m_origin)
461 return make_label_text
462 (can_colorize,
463 "%s (state of %qE: %qs -> %qs, origin: %qE, meaning: %s)",
464 custom_desc.get (),
465 var,
466 m_from->get_name (),
467 m_to->get_name (),
468 origin,
469 pp_formatted_text (&meaning_pp));
470 else
471 return make_label_text
472 (can_colorize,
473 "%s (state of %qE: %qs -> %qs, NULL origin, meaning: %s)",
474 custom_desc.get (),
475 var,
476 m_from->get_name (),
477 m_to->get_name (),
478 pp_formatted_text (&meaning_pp));
480 else
481 return custom_desc;
485 /* Fallback description. */
486 if (m_sval)
488 label_text sval_desc = m_sval->get_desc ();
489 if (m_origin)
491 label_text origin_desc = m_origin->get_desc ();
492 return make_label_text
493 (can_colorize,
494 "state of %qs: %qs -> %qs (origin: %qs)",
495 sval_desc.get (),
496 m_from->get_name (),
497 m_to->get_name (),
498 origin_desc.get ());
500 else
501 return make_label_text
502 (can_colorize,
503 "state of %qs: %qs -> %qs (NULL origin)",
504 sval_desc.get (),
505 m_from->get_name (),
506 m_to->get_name ());
508 else
510 gcc_assert (m_origin == NULL);
511 return make_label_text
512 (can_colorize,
513 "global state: %qs -> %qs",
514 m_from->get_name (),
515 m_to->get_name ());
519 /* Implementation of diagnostic_event::get_meaning vfunc for
520 state change events: delegate to the pending_diagnostic to
521 get any meaning. */
523 diagnostic_event::meaning
524 state_change_event::get_meaning () const
526 if (m_pending_diagnostic)
528 region_model *model = m_dst_state.m_region_model;
529 tree var = model->get_representative_tree (m_sval);
530 tree origin = model->get_representative_tree (m_origin);
531 return m_pending_diagnostic->get_meaning_for_state_change
532 (evdesc::state_change (false, var, origin,
533 m_from, m_to, m_emission_id, *this));
535 else
536 return meaning ();
539 /* class superedge_event : public checker_event. */
541 /* Get the callgraph_superedge for this superedge_event, which must be
542 for an interprocedural edge, rather than a CFG edge. */
544 const callgraph_superedge&
545 superedge_event::get_callgraph_superedge () const
547 gcc_assert (m_sedge->m_kind != SUPEREDGE_CFG_EDGE);
548 return *m_sedge->dyn_cast_callgraph_superedge ();
551 /* Determine if this event should be filtered at the given verbosity
552 level. */
554 bool
555 superedge_event::should_filter_p (int verbosity) const
557 switch (m_sedge->m_kind)
559 case SUPEREDGE_CFG_EDGE:
561 if (verbosity < 2)
562 return true;
564 if (verbosity < 4)
566 /* Filter events with empty descriptions. This ought to filter
567 FALLTHRU, but retain true/false/switch edges. */
568 label_text desc = get_desc (false);
569 gcc_assert (desc.get ());
570 if (desc.get ()[0] == '\0')
571 return true;
574 break;
576 default:
577 break;
579 return false;
582 /* superedge_event's ctor. */
584 superedge_event::superedge_event (enum event_kind kind,
585 const exploded_edge &eedge,
586 const event_loc_info &loc_info)
587 : checker_event (kind, loc_info),
588 m_eedge (eedge), m_sedge (eedge.m_sedge),
589 m_var (NULL_TREE), m_critical_state (0)
593 /* class cfg_edge_event : public superedge_event. */
595 /* Get the cfg_superedge for this cfg_edge_event. */
597 const cfg_superedge &
598 cfg_edge_event::get_cfg_superedge () const
600 return *m_sedge->dyn_cast_cfg_superedge ();
603 /* cfg_edge_event's ctor. */
605 cfg_edge_event::cfg_edge_event (enum event_kind kind,
606 const exploded_edge &eedge,
607 const event_loc_info &loc_info)
608 : superedge_event (kind, eedge, loc_info)
610 gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_CFG_EDGE);
613 /* Implementation of diagnostic_event::get_meaning vfunc for
614 CFG edge events. */
616 diagnostic_event::meaning
617 cfg_edge_event::get_meaning () const
619 const cfg_superedge& cfg_sedge = get_cfg_superedge ();
620 if (cfg_sedge.true_value_p ())
621 return meaning (VERB_branch, PROPERTY_true);
622 else if (cfg_sedge.false_value_p ())
623 return meaning (VERB_branch, PROPERTY_false);
624 else
625 return meaning ();
628 /* class start_cfg_edge_event : public cfg_edge_event. */
630 /* Implementation of diagnostic_event::get_desc vfunc for
631 start_cfg_edge_event.
633 If -fanalyzer-verbose-edges, then generate low-level descriptions, such
635 "taking 'true' edge SN:7 -> SN:8".
637 Otherwise, generate strings using the label of the underlying CFG if
638 any, such as:
639 "following 'true' branch..." or
640 "following 'case 3' branch..."
641 "following 'default' branch..."
643 For conditionals, attempt to supply a description of the condition that
644 holds, such as:
645 "following 'false' branch (when 'ptr' is non-NULL)..."
647 Failing that, return an empty description (which will lead to this event
648 being filtered). */
650 label_text
651 start_cfg_edge_event::get_desc (bool can_colorize) const
653 bool user_facing = !flag_analyzer_verbose_edges;
654 label_text edge_desc (m_sedge->get_description (user_facing));
655 if (user_facing)
657 if (edge_desc.get () && strlen (edge_desc.get ()) > 0)
659 label_text cond_desc = maybe_describe_condition (can_colorize);
660 label_text result;
661 if (cond_desc.get ())
662 return make_label_text (can_colorize,
663 "following %qs branch (%s)...",
664 edge_desc.get (), cond_desc.get ());
665 else
666 return make_label_text (can_colorize,
667 "following %qs branch...",
668 edge_desc.get ());
670 else
671 return label_text::borrow ("");
673 else
675 if (strlen (edge_desc.get ()) > 0)
676 return make_label_text (can_colorize,
677 "taking %qs edge SN:%i -> SN:%i",
678 edge_desc.get (),
679 m_sedge->m_src->m_index,
680 m_sedge->m_dest->m_index);
681 else
682 return make_label_text (can_colorize,
683 "taking edge SN:%i -> SN:%i",
684 m_sedge->m_src->m_index,
685 m_sedge->m_dest->m_index);
689 /* Attempt to generate a description of any condition that holds at this edge.
691 The intent is to make the user-facing messages more clear, especially for
692 cases where there's a single or double-negative, such as
693 when describing the false branch of an inverted condition.
695 For example, rather than printing just:
697 | if (!ptr)
700 | (1) following 'false' branch...
702 it's clearer to spell out the condition that holds:
704 | if (!ptr)
707 | (1) following 'false' branch (when 'ptr' is non-NULL)...
708 ^^^^^^^^^^^^^^^^^^^^^^
710 In the above example, this function would generate the highlighted
711 string: "when 'ptr' is non-NULL".
713 If the edge is not a condition, or it's not clear that a description of
714 the condition would be helpful to the user, return NULL. */
716 label_text
717 start_cfg_edge_event::maybe_describe_condition (bool can_colorize) const
719 const cfg_superedge& cfg_sedge = get_cfg_superedge ();
721 if (cfg_sedge.true_value_p () || cfg_sedge.false_value_p ())
723 const gimple *last_stmt = m_sedge->m_src->get_last_stmt ();
724 if (const gcond *cond_stmt = dyn_cast <const gcond *> (last_stmt))
726 enum tree_code op = gimple_cond_code (cond_stmt);
727 tree lhs = gimple_cond_lhs (cond_stmt);
728 tree rhs = gimple_cond_rhs (cond_stmt);
729 if (cfg_sedge.false_value_p ())
730 op = invert_tree_comparison (op, false /* honor_nans */);
731 return maybe_describe_condition (can_colorize,
732 lhs, op, rhs);
735 return label_text::borrow (NULL);
738 /* Subroutine of maybe_describe_condition above.
740 Attempt to generate a user-facing description of the condition
741 LHS OP RHS, but only if it is likely to make it easier for the
742 user to understand a condition. */
744 label_text
745 start_cfg_edge_event::maybe_describe_condition (bool can_colorize,
746 tree lhs,
747 enum tree_code op,
748 tree rhs)
750 /* In theory we could just build a tree via
751 fold_build2 (op, boolean_type_node, lhs, rhs)
752 and print it with %qE on it, but this leads to warts such as
753 parenthesizing vars, such as '(i) <= 9', and uses of '<unknown>'. */
755 /* Special-case: describe testing the result of strcmp, as figuring
756 out what the "true" or "false" path is can be confusing to the user. */
757 if (TREE_CODE (lhs) == SSA_NAME
758 && zerop (rhs))
760 if (gcall *call = dyn_cast <gcall *> (SSA_NAME_DEF_STMT (lhs)))
761 if (is_special_named_call_p (call, "strcmp", 2))
763 if (op == EQ_EXPR)
764 return label_text::borrow ("when the strings are equal");
765 if (op == NE_EXPR)
766 return label_text::borrow ("when the strings are non-equal");
770 /* Only attempt to generate text for sufficiently simple expressions. */
771 if (!should_print_expr_p (lhs))
772 return label_text::borrow (NULL);
773 if (!should_print_expr_p (rhs))
774 return label_text::borrow (NULL);
776 /* Special cases for pointer comparisons against NULL. */
777 if (POINTER_TYPE_P (TREE_TYPE (lhs))
778 && POINTER_TYPE_P (TREE_TYPE (rhs))
779 && zerop (rhs))
781 if (op == EQ_EXPR)
782 return make_label_text (can_colorize, "when %qE is NULL",
783 lhs);
784 if (op == NE_EXPR)
785 return make_label_text (can_colorize, "when %qE is non-NULL",
786 lhs);
789 return make_label_text (can_colorize, "when %<%E %s %E%>",
790 lhs, op_symbol_code (op), rhs);
793 /* Subroutine of maybe_describe_condition.
795 Return true if EXPR is we will get suitable user-facing output
796 from %E on it. */
798 bool
799 start_cfg_edge_event::should_print_expr_p (tree expr)
801 if (TREE_CODE (expr) == SSA_NAME)
803 if (SSA_NAME_VAR (expr))
804 return should_print_expr_p (SSA_NAME_VAR (expr));
805 else
806 return false;
809 if (DECL_P (expr))
810 return true;
812 if (CONSTANT_CLASS_P (expr))
813 return true;
815 return false;
818 /* class call_event : public superedge_event. */
820 /* call_event's ctor. */
822 call_event::call_event (const exploded_edge &eedge,
823 const event_loc_info &loc_info)
824 : superedge_event (EK_CALL_EDGE, eedge, loc_info)
826 if (eedge.m_sedge)
827 gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_CALL);
829 m_src_snode = eedge.m_src->get_supernode ();
830 m_dest_snode = eedge.m_dest->get_supernode ();
833 /* Implementation of diagnostic_event::get_desc vfunc for
834 call_event.
836 If this call event passes critical state for an sm-based warning,
837 allow the diagnostic to generate a precise description, such as:
839 "passing freed pointer 'ptr' in call to 'foo' from 'bar'"
841 Otherwise, generate a description of the form
842 "calling 'foo' from 'bar'". */
844 label_text
845 call_event::get_desc (bool can_colorize) const
847 if (m_critical_state && m_pending_diagnostic)
849 gcc_assert (m_var);
850 tree var = fixup_tree_for_diagnostic (m_var);
851 label_text custom_desc
852 = m_pending_diagnostic->describe_call_with_state
853 (evdesc::call_with_state (can_colorize,
854 m_src_snode->m_fun->decl,
855 m_dest_snode->m_fun->decl,
856 var,
857 m_critical_state));
858 if (custom_desc.get ())
859 return custom_desc;
862 return make_label_text (can_colorize,
863 "calling %qE from %qE",
864 get_callee_fndecl (),
865 get_caller_fndecl ());
868 /* Implementation of diagnostic_event::get_meaning vfunc for
869 function call events. */
871 diagnostic_event::meaning
872 call_event::get_meaning () const
874 return meaning (VERB_call, NOUN_function);
877 /* Override of checker_event::is_call_p for calls. */
879 bool
880 call_event::is_call_p () const
882 return true;
885 tree
886 call_event::get_caller_fndecl () const
888 return m_src_snode->m_fun->decl;
891 tree
892 call_event::get_callee_fndecl () const
894 return m_dest_snode->m_fun->decl;
897 /* class return_event : public superedge_event. */
899 /* return_event's ctor. */
901 return_event::return_event (const exploded_edge &eedge,
902 const event_loc_info &loc_info)
903 : superedge_event (EK_RETURN_EDGE, eedge, loc_info)
905 if (eedge.m_sedge)
906 gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_RETURN);
908 m_src_snode = eedge.m_src->get_supernode ();
909 m_dest_snode = eedge.m_dest->get_supernode ();
912 /* Implementation of diagnostic_event::get_desc vfunc for
913 return_event.
915 If this return event returns critical state for an sm-based warning,
916 allow the diagnostic to generate a precise description, such as:
918 "possible of NULL to 'foo' from 'bar'"
920 Otherwise, generate a description of the form
921 "returning to 'foo' from 'bar'. */
923 label_text
924 return_event::get_desc (bool can_colorize) const
926 /* For greatest precision-of-wording, if this is returning the
927 state involved in the pending diagnostic, give the pending
928 diagnostic a chance to describe this return (in terms of
929 itself). */
930 if (m_critical_state && m_pending_diagnostic)
932 label_text custom_desc
933 = m_pending_diagnostic->describe_return_of_state
934 (evdesc::return_of_state (can_colorize,
935 m_dest_snode->m_fun->decl,
936 m_src_snode->m_fun->decl,
937 m_critical_state));
938 if (custom_desc.get ())
939 return custom_desc;
941 return make_label_text (can_colorize,
942 "returning to %qE from %qE",
943 m_dest_snode->m_fun->decl,
944 m_src_snode->m_fun->decl);
947 /* Implementation of diagnostic_event::get_meaning vfunc for
948 function return events. */
950 diagnostic_event::meaning
951 return_event::get_meaning () const
953 return meaning (VERB_return, NOUN_function);
956 /* Override of checker_event::is_return_p for returns. */
958 bool
959 return_event::is_return_p () const
961 return true;
964 /* class start_consolidated_cfg_edges_event : public checker_event. */
966 label_text
967 start_consolidated_cfg_edges_event::get_desc (bool can_colorize) const
969 return make_label_text (can_colorize,
970 "following %qs branch...",
971 m_edge_sense ? "true" : "false");
974 /* Implementation of diagnostic_event::get_meaning vfunc for
975 start_consolidated_cfg_edges_event. */
977 diagnostic_event::meaning
978 start_consolidated_cfg_edges_event::get_meaning () const
980 return meaning (VERB_branch,
981 (m_edge_sense ? PROPERTY_true : PROPERTY_false));
984 /* class inlined_call_event : public checker_event. */
986 label_text
987 inlined_call_event::get_desc (bool can_colorize) const
989 return make_label_text (can_colorize,
990 "inlined call to %qE from %qE",
991 m_apparent_callee_fndecl,
992 m_apparent_caller_fndecl);
995 /* Implementation of diagnostic_event::get_meaning vfunc for
996 reconstructed inlined function calls. */
998 diagnostic_event::meaning
999 inlined_call_event::get_meaning () const
1001 return meaning (VERB_call, NOUN_function);
1004 /* class setjmp_event : public checker_event. */
1006 /* Implementation of diagnostic_event::get_desc vfunc for
1007 setjmp_event. */
1009 label_text
1010 setjmp_event::get_desc (bool can_colorize) const
1012 return make_label_text (can_colorize,
1013 "%qs called here",
1014 get_user_facing_name (m_setjmp_call));
1017 /* Implementation of checker_event::prepare_for_emission vfunc for setjmp_event.
1019 Record this setjmp's event ID into the path, so that rewind events can
1020 use it. */
1022 void
1023 setjmp_event::prepare_for_emission (checker_path *path,
1024 pending_diagnostic *pd,
1025 diagnostic_event_id_t emission_id)
1027 checker_event::prepare_for_emission (path, pd, emission_id);
1028 path->record_setjmp_event (m_enode, emission_id);
1031 /* class rewind_event : public checker_event. */
1033 /* Get the fndecl containing the site of the longjmp call. */
1035 tree
1036 rewind_event::get_longjmp_caller () const
1038 return m_eedge->m_src->get_function ()->decl;
1041 /* Get the fndecl containing the site of the setjmp call. */
1043 tree
1044 rewind_event::get_setjmp_caller () const
1046 return m_eedge->m_dest->get_function ()->decl;
1049 /* rewind_event's ctor. */
1051 rewind_event::rewind_event (const exploded_edge *eedge,
1052 enum event_kind kind,
1053 const event_loc_info &loc_info,
1054 const rewind_info_t *rewind_info)
1055 : checker_event (kind, loc_info),
1056 m_rewind_info (rewind_info),
1057 m_eedge (eedge)
1059 gcc_assert (m_eedge->m_custom_info.get () == m_rewind_info);
1062 /* class rewind_from_longjmp_event : public rewind_event. */
1064 /* Implementation of diagnostic_event::get_desc vfunc for
1065 rewind_from_longjmp_event. */
1067 label_text
1068 rewind_from_longjmp_event::get_desc (bool can_colorize) const
1070 const char *src_name
1071 = get_user_facing_name (m_rewind_info->get_longjmp_call ());
1073 if (get_longjmp_caller () == get_setjmp_caller ())
1074 /* Special-case: purely intraprocedural rewind. */
1075 return make_label_text (can_colorize,
1076 "rewinding within %qE from %qs...",
1077 get_longjmp_caller (),
1078 src_name);
1079 else
1080 return make_label_text (can_colorize,
1081 "rewinding from %qs in %qE...",
1082 src_name,
1083 get_longjmp_caller ());
1086 /* class rewind_to_setjmp_event : public rewind_event. */
1088 /* Implementation of diagnostic_event::get_desc vfunc for
1089 rewind_to_setjmp_event. */
1091 label_text
1092 rewind_to_setjmp_event::get_desc (bool can_colorize) const
1094 const char *dst_name
1095 = get_user_facing_name (m_rewind_info->get_setjmp_call ());
1097 /* If we can, identify the ID of the setjmp_event. */
1098 if (m_original_setjmp_event_id.known_p ())
1100 if (get_longjmp_caller () == get_setjmp_caller ())
1101 /* Special-case: purely intraprocedural rewind. */
1102 return make_label_text (can_colorize,
1103 "...to %qs (saved at %@)",
1104 dst_name,
1105 &m_original_setjmp_event_id);
1106 else
1107 return make_label_text (can_colorize,
1108 "...to %qs in %qE (saved at %@)",
1109 dst_name,
1110 get_setjmp_caller (),
1111 &m_original_setjmp_event_id);
1113 else
1115 if (get_longjmp_caller () == get_setjmp_caller ())
1116 /* Special-case: purely intraprocedural rewind. */
1117 return make_label_text (can_colorize,
1118 "...to %qs",
1119 dst_name,
1120 get_setjmp_caller ());
1121 else
1122 return make_label_text (can_colorize,
1123 "...to %qs in %qE",
1124 dst_name,
1125 get_setjmp_caller ());
1129 /* Implementation of checker_event::prepare_for_emission vfunc for
1130 rewind_to_setjmp_event.
1132 Attempt to look up the setjmp event ID that recorded the jmp_buf
1133 for this rewind. */
1135 void
1136 rewind_to_setjmp_event::prepare_for_emission (checker_path *path,
1137 pending_diagnostic *pd,
1138 diagnostic_event_id_t emission_id)
1140 checker_event::prepare_for_emission (path, pd, emission_id);
1141 path->get_setjmp_event (m_rewind_info->get_enode_origin (),
1142 &m_original_setjmp_event_id);
1145 /* class warning_event : public checker_event. */
1147 /* Implementation of diagnostic_event::get_desc vfunc for
1148 warning_event.
1150 If the pending diagnostic implements describe_final_event, use it,
1151 generating a precise description e.g.
1152 "second 'free' here; first 'free' was at (7)"
1154 Otherwise generate a generic description. */
1156 label_text
1157 warning_event::get_desc (bool can_colorize) const
1159 if (m_pending_diagnostic)
1161 tree var = fixup_tree_for_diagnostic (m_var);
1162 label_text ev_desc
1163 = m_pending_diagnostic->describe_final_event
1164 (evdesc::final_event (can_colorize, var, m_state, *this));
1165 if (ev_desc.get ())
1167 if (m_sm && flag_analyzer_verbose_state_changes)
1169 if (var)
1170 return make_label_text (can_colorize,
1171 "%s (%qE is in state %qs)",
1172 ev_desc.get (),
1173 var, m_state->get_name ());
1174 else
1175 return make_label_text (can_colorize,
1176 "%s (in global state %qs)",
1177 ev_desc.get (),
1178 m_state->get_name ());
1180 else
1181 return ev_desc;
1185 if (m_sm)
1187 if (m_var)
1188 return make_label_text (can_colorize,
1189 "here (%qE is in state %qs)",
1190 m_var, m_state->get_name ());
1191 else
1192 return make_label_text (can_colorize,
1193 "here (in global state %qs)",
1194 m_state->get_name ());
1196 else
1197 return label_text::borrow ("here");
1200 /* Implementation of diagnostic_event::get_meaning vfunc for
1201 warning_event. */
1203 diagnostic_event::meaning
1204 warning_event::get_meaning () const
1206 return meaning (VERB_danger, NOUN_unknown);
1209 } // namespace ana
1211 #endif /* #if ENABLE_ANALYZER */