annotate gcc/analyzer/diagnostic-manager.cc @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
145
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1 /* Classes for saving, deduplicating, and emitting analyzer diagnostics.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2 Copyright (C) 2019-2020 Free Software Foundation, Inc.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
4
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
5 This file is part of GCC.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
6
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
8 under the terms of the GNU General Public License as published by
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
9 the Free Software Foundation; either version 3, or (at your option)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
10 any later version.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
11
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
13 WITHOUT ANY WARRANTY; without even the implied warranty of
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
15 General Public License for more details.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
16
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
20
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
21 #include "config.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
22 #include "system.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
23 #include "coretypes.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
24 #include "tree.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
25 #include "pretty-print.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
26 #include "gcc-rich-location.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
27 #include "gimple-pretty-print.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
28 #include "function.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
29 #include "diagnostic-core.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
30 #include "diagnostic-event-id.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
31 #include "diagnostic-path.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
32 #include "alloc-pool.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
33 #include "fibonacci_heap.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
34 #include "shortest-paths.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
35 #include "sbitmap.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
36 #include "tristate.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
37 #include "selftest.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
38 #include "ordered-hash-map.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
39 #include "analyzer/analyzer.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
40 #include "analyzer/analyzer-logging.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
41 #include "analyzer/sm.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
42 #include "analyzer/pending-diagnostic.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
43 #include "analyzer/diagnostic-manager.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
44 #include "analyzer/region-model.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
45 #include "analyzer/constraint-manager.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
46 #include "cfg.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
47 #include "basic-block.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
48 #include "gimple.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
49 #include "gimple-iterator.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
50 #include "cgraph.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
51 #include "digraph.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
52 #include "analyzer/supergraph.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
53 #include "analyzer/call-string.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
54 #include "analyzer/program-point.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
55 #include "analyzer/program-state.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
56 #include "analyzer/exploded-graph.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
57 #include "analyzer/checker-path.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
58
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
59 #if ENABLE_ANALYZER
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
60
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
61 namespace ana {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
62
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
63 /* class saved_diagnostic. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
64
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
65 /* saved_diagnostic's ctor.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
66 Take ownership of D and STMT_FINDER. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
67
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
68 saved_diagnostic::saved_diagnostic (const state_machine *sm,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
69 const exploded_node *enode,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
70 const supernode *snode, const gimple *stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
71 stmt_finder *stmt_finder,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
72 tree var, state_machine::state_t state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
73 pending_diagnostic *d)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
74 : m_sm (sm), m_enode (enode), m_snode (snode), m_stmt (stmt),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
75 /* stmt_finder could be on-stack; we want our own copy that can
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
76 outlive that. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
77 m_stmt_finder (stmt_finder ? stmt_finder->clone () : NULL),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
78 m_var (var), m_state (state),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
79 m_d (d), m_trailing_eedge (NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
80 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
81 gcc_assert (m_stmt || m_stmt_finder);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
82
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
83 /* We must have an enode in order to be able to look for paths
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
84 through the exploded_graph to this diagnostic. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
85 gcc_assert (m_enode);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
86 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
87
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
88 /* saved_diagnostic's dtor. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
89
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
90 saved_diagnostic::~saved_diagnostic ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
91 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
92 delete m_stmt_finder;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
93 delete m_d;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
94 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
95
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
96 bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
97 saved_diagnostic::operator== (const saved_diagnostic &other) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
98 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
99 return (m_sm == other.m_sm
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
100 /* We don't compare m_enode. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
101 && m_snode == other.m_snode
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
102 && m_stmt == other.m_stmt
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
103 /* We don't compare m_stmt_finder. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
104 && pending_diagnostic::same_tree_p (m_var, other.m_var)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
105 && m_state == other.m_state
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
106 && m_d->equal_p (*other.m_d)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
107 && m_trailing_eedge == other.m_trailing_eedge);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
108 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
109
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
110 /* class diagnostic_manager. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
111
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
112 /* diagnostic_manager's ctor. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
113
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
114 diagnostic_manager::diagnostic_manager (logger *logger, int verbosity)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
115 : log_user (logger), m_verbosity (verbosity)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
116 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
117 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
118
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
119 /* Queue pending_diagnostic D at ENODE for later emission. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
120
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
121 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
122 diagnostic_manager::add_diagnostic (const state_machine *sm,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
123 const exploded_node *enode,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
124 const supernode *snode, const gimple *stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
125 stmt_finder *finder,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
126 tree var, state_machine::state_t state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
127 pending_diagnostic *d)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
128 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
129 LOG_FUNC (get_logger ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
130
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
131 /* We must have an enode in order to be able to look for paths
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
132 through the exploded_graph to the diagnostic. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
133 gcc_assert (enode);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
134
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
135 saved_diagnostic *sd
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
136 = new saved_diagnostic (sm, enode, snode, stmt, finder, var, state, d);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
137 m_saved_diagnostics.safe_push (sd);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
138 if (get_logger ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
139 log ("adding saved diagnostic %i at SN %i: %qs",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
140 m_saved_diagnostics.length () - 1,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
141 snode->m_index, d->get_kind ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
142 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
143
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
144 /* Queue pending_diagnostic D at ENODE for later emission. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
145
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
146 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
147 diagnostic_manager::add_diagnostic (const exploded_node *enode,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
148 const supernode *snode, const gimple *stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
149 stmt_finder *finder,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
150 pending_diagnostic *d)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
151 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
152 gcc_assert (enode);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
153 add_diagnostic (NULL, enode, snode, stmt, finder, NULL_TREE, 0, d);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
154 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
155
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
156 /* A class for identifying sets of duplicated pending_diagnostic.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
157
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
158 We want to find the simplest dedupe_candidate amongst those that share a
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
159 dedupe_key. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
160
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
161 class dedupe_key
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
162 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
163 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
164 dedupe_key (const saved_diagnostic &sd,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
165 const exploded_path &epath)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
166 : m_sd (sd), m_stmt (sd.m_stmt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
167 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
168 /* Support deferring the choice of stmt until after an emission path has
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
169 been built, using an optional stmt_finder. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
170 if (m_stmt == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
171 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
172 gcc_assert (sd.m_stmt_finder);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
173 m_stmt = sd.m_stmt_finder->find_stmt (epath);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
174 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
175 gcc_assert (m_stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
176 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
177
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
178 hashval_t hash () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
179 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
180 inchash::hash hstate;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
181 hstate.add_ptr (m_stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
182 // TODO: m_sd
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
183 return hstate.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
184 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
185 bool operator== (const dedupe_key &other) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
186 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
187 return (m_sd == other.m_sd
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
188 && m_stmt == other.m_stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
189 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
190
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
191 location_t get_location () const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
192 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
193 return m_stmt->location;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
194 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
195
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
196 /* A qsort comparator for use by dedupe_winners::emit_best
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
197 to sort them into location_t order. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
198
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
199 static int
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
200 comparator (const void *p1, const void *p2)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
201 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
202 const dedupe_key *pk1 = *(const dedupe_key * const *)p1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
203 const dedupe_key *pk2 = *(const dedupe_key * const *)p2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
204
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
205 location_t loc1 = pk1->get_location ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
206 location_t loc2 = pk2->get_location ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
207
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
208 return linemap_compare_locations (line_table, loc2, loc1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
209 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
210
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
211 const saved_diagnostic &m_sd;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
212 const gimple *m_stmt;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
213 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
214
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
215 /* The value of a slot for a dedupe_key within dedupe_winners:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
216 the exploded_path for the best candidate for that key, and the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
217 number of duplicates seen so far. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
218
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
219 class dedupe_candidate
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
220 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
221 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
222 // has the exploded_path
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
223 dedupe_candidate (const shortest_exploded_paths &sp,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
224 const saved_diagnostic &sd)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
225 : m_epath (sp.get_shortest_path (sd.m_enode)),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
226 m_num_dupes (0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
227 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
228 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
229
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
230 unsigned length () const { return m_epath.length (); }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
231 const exploded_path &get_path () const { return m_epath; }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
232
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
233 void add_duplicate () { m_num_dupes++; }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
234 int get_num_dupes () const { return m_num_dupes; }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
235
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
236 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
237 exploded_path m_epath;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
238 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
239 int m_num_dupes;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
240 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
241
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
242 /* Traits for use by dedupe_winners. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
243
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
244 class dedupe_hash_map_traits
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
245 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
246 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
247 typedef const dedupe_key *key_type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
248 typedef dedupe_candidate *value_type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
249 typedef dedupe_candidate *compare_type;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
250
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
251 static inline hashval_t hash (const key_type &v)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
252 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
253 return v->hash ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
254 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
255 static inline bool equal_keys (const key_type &k1, const key_type &k2)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
256 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
257 return *k1 == *k2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
258 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
259 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
260 static inline void remove (T &)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
261 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
262 // TODO
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
263 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
264 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
265 static inline void mark_deleted (T &entry)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
266 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
267 entry.m_key = reinterpret_cast<key_type> (1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
268 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
269 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
270 static inline void mark_empty (T &entry)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
271 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
272 entry.m_key = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
273 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
274 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
275 static inline bool is_deleted (const T &entry)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
276 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
277 return entry.m_key == reinterpret_cast<key_type> (1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
278 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
279 template <typename T>
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
280 static inline bool is_empty (const T &entry)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
281 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
282 return entry.m_key == NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
283 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
284 static const bool empty_zero_p = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
285 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
286
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
287 /* A class for deduplicating diagnostics and finding (and emitting) the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
288 best diagnostic within each partition. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
289
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
290 class dedupe_winners
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
291 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
292 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
293 ~dedupe_winners ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
294 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
295 /* Delete all keys and candidates. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
296 for (map_t::iterator iter = m_map.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
297 iter != m_map.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
298 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
299 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
300 delete (*iter).first;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
301 delete (*iter).second;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
302 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
303 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
304
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
305 /* Determine an exploded_path for SD using SP and, if it's feasible,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
306 determine if it's the best seen so far for its dedupe_key.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
307 Retain the winner for each dedupe_key, and discard the rest. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
308
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
309 void add (logger *logger,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
310 const shortest_exploded_paths &sp,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
311 const saved_diagnostic &sd)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
312 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
313 /* Build a dedupe_candidate for SD.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
314 This uses SP to build an exploded_path. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
315 dedupe_candidate *dc = new dedupe_candidate (sp, sd);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
316
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
317 /* Verify that the epath is feasible.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
318 State-merging means that not every path in the epath corresponds
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
319 to a feasible one w.r.t. states.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
320 Here we simply check each duplicate saved_diagnostic's
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
321 shortest_path, and reject any that aren't feasible.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
322 This could introduce false negatives, as there could be longer
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
323 feasible paths within the egraph. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
324 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
325 logger->log ("considering %qs at SN: %i",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
326 sd.m_d->get_kind (), sd.m_snode->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
327 if (!dc->get_path ().feasible_p (logger))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
328 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
329 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
330 logger->log ("rejecting %qs at SN: %i"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
331 " due to infeasible path",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
332 sd.m_d->get_kind (), sd.m_snode->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
333 delete dc;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
334 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
335 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
336 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
337 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
338 logger->log ("accepting %qs at SN: %i with feasible path",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
339 sd.m_d->get_kind (), sd.m_snode->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
340
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
341 dedupe_key *key = new dedupe_key (sd, dc->get_path ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
342 if (dedupe_candidate **slot = m_map.get (key))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
343 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
344 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
345 logger->log ("already have this dedupe_key");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
346
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
347 (*slot)->add_duplicate ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
348
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
349 if (dc->length () < (*slot)->length ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
350 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
351 /* We've got a shorter path for the key; replace
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
352 the current candidate. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
353 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
354 logger->log ("length %i is better than existing length %i;"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
355 " taking over this dedupe_key",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
356 dc->length (), (*slot)->length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
357 dc->m_num_dupes = (*slot)->get_num_dupes ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
358 delete *slot;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
359 *slot = dc;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
360 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
361 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
362 /* We haven't beaten the current best candidate;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
363 drop the new candidate. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
364 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
365 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
366 logger->log ("length %i isn't better than existing length %i;"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
367 " dropping this candidate",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
368 dc->length (), (*slot)->length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
369 delete dc;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
370 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
371 delete key;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
372 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
373 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
374 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
375 /* This is the first candidate for this key. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
376 m_map.put (key, dc);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
377 if (logger)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
378 logger->log ("first candidate for this dedupe_key");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
379 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
380 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
381
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
382 /* Emit the simplest diagnostic within each set. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
383
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
384 void emit_best (diagnostic_manager *dm,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
385 const exploded_graph &eg)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
386 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
387 LOG_SCOPE (dm->get_logger ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
388
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
389 /* Get keys into a vec for sorting. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
390 auto_vec<const dedupe_key *> keys (m_map.elements ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
391 for (map_t::iterator iter = m_map.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
392 iter != m_map.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
393 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
394 keys.quick_push ((*iter).first);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
395
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
396 dm->log ("# keys after de-duplication: %i", keys.length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
397
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
398 /* Sort into a good emission order. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
399 keys.qsort (dedupe_key::comparator);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
400
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
401 /* Emit the best candidate for each key. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
402 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
403 const dedupe_key *key;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
404 FOR_EACH_VEC_ELT (keys, i, key)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
405 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
406 dedupe_candidate **slot = m_map.get (key);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
407 gcc_assert (*slot);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
408 const dedupe_candidate &dc = **slot;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
409
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
410 dm->emit_saved_diagnostic (eg, key->m_sd,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
411 dc.get_path (), key->m_stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
412 dc.get_num_dupes ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
413 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
414 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
415
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
416 private:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
417
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
418 /* This maps from each dedupe_key to a current best dedupe_candidate. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
419
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
420 typedef hash_map<const dedupe_key *, dedupe_candidate *,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
421 dedupe_hash_map_traits> map_t;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
422 map_t m_map;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
423 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
424
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
425 /* Emit all saved diagnostics. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
426
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
427 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
428 diagnostic_manager::emit_saved_diagnostics (const exploded_graph &eg)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
429 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
430 LOG_SCOPE (get_logger ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
431 auto_timevar tv (TV_ANALYZER_DIAGNOSTICS);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
432 log ("# saved diagnostics: %i", m_saved_diagnostics.length ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
433
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
434 if (m_saved_diagnostics.length () == 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
435 return;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
436
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
437 /* Compute the shortest_paths once, sharing it between all diagnostics. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
438 shortest_exploded_paths sp (eg, eg.get_origin ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
439
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
440 /* Iterate through all saved diagnostics, adding them to a dedupe_winners
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
441 instance. This partitions the saved diagnostics by dedupe_key,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
442 generating exploded_paths for them, and retaining the best one in each
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
443 partition. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
444 dedupe_winners best_candidates;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
445
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
446 int i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
447 saved_diagnostic *sd;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
448 FOR_EACH_VEC_ELT (m_saved_diagnostics, i, sd)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
449 best_candidates.add (get_logger (), sp, *sd);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
450
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
451 /* For each dedupe-key, call emit_saved_diagnostic on the "best"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
452 saved_diagnostic. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
453 best_candidates.emit_best (this, eg);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
454 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
455
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
456 /* Given a saved_diagnostic SD at STMT with feasible path EPATH through EG,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
457 create an checker_path of suitable events and use it to call
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
458 SD's underlying pending_diagnostic "emit" vfunc to emit a diagnostic. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
459
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
460 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
461 diagnostic_manager::emit_saved_diagnostic (const exploded_graph &eg,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
462 const saved_diagnostic &sd,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
463 const exploded_path &epath,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
464 const gimple *stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
465 int num_dupes)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
466 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
467 LOG_SCOPE (get_logger ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
468 log ("sd: %qs at SN: %i", sd.m_d->get_kind (), sd.m_snode->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
469 log ("num dupes: %i", num_dupes);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
470
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
471 pretty_printer *pp = global_dc->printer->clone ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
472
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
473 checker_path emission_path;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
474
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
475 /* Populate emission_path with a full description of EPATH. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
476 build_emission_path (eg, epath, &emission_path);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
477
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
478 /* Now prune it to just cover the most pertinent events. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
479 prune_path (&emission_path, sd.m_sm, sd.m_var, sd.m_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
480
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
481 /* Add a final event to the path, covering the diagnostic itself.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
482 We use the final enode from the epath, which might be different from
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
483 the sd.m_enode, as the dedupe code doesn't care about enodes, just
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
484 snodes. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
485 emission_path.add_final_event (sd.m_sm, epath.get_final_enode (), stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
486 sd.m_var, sd.m_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
487
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
488 /* The "final" event might not be final; if the saved_diagnostic has a
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
489 trailing eedge stashed, add any events for it. This is for use
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
490 in handling longjmp, to show where a longjmp is rewinding to. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
491 if (sd.m_trailing_eedge)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
492 add_events_for_eedge (*sd.m_trailing_eedge, eg.get_ext_state (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
493 &emission_path);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
494
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
495 emission_path.prepare_for_emission (sd.m_d);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
496
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
497 gcc_rich_location rich_loc (stmt->location);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
498 rich_loc.set_path (&emission_path);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
499
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
500 auto_diagnostic_group d;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
501 auto_cfun sentinel (sd.m_snode->m_fun);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
502 if (sd.m_d->emit (&rich_loc))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
503 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
504 if (num_dupes > 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
505 inform_n (stmt->location, num_dupes,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
506 "%i duplicate", "%i duplicates",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
507 num_dupes);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
508 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
509 delete pp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
510 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
511
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
512 /* Given a state change to DST_REP, determine a tree that gives the origin
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
513 of that state at STMT, using DST_STATE's region model, so that state
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
514 changes based on assignments can be tracked back to their origins.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
515
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
516 For example, if we have
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
517
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
518 (S1) _1 = malloc (64);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
519 (S2) EXPR = _1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
520
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
521 then at stmt S2 we can get the origin of EXPR's state as being _1,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
522 and thus track the allocation back to S1. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
523
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
524 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
525 get_any_origin (const gimple *stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
526 tree dst_rep,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
527 const program_state &dst_state)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
528 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
529 if (!stmt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
530 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
531
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
532 gcc_assert (dst_rep);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
533
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
534 if (const gassign *assign = dyn_cast <const gassign *> (stmt))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
535 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
536 tree lhs = gimple_assign_lhs (assign);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
537 /* Use region IDs to compare lhs with DST_REP. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
538 if (dst_state.m_region_model->get_lvalue (lhs, NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
539 == dst_state.m_region_model->get_lvalue (dst_rep, NULL))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
540 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
541 tree rhs1 = gimple_assign_rhs1 (assign);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
542 enum tree_code op = gimple_assign_rhs_code (assign);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
543 switch (op)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
544 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
545 default:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
546 //gcc_unreachable (); // TODO
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
547 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
548 case COMPONENT_REF:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
549 case SSA_NAME:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
550 return rhs1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
551 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
552 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
553 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
554 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
555 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
556
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
557 /* Emit a "path" of events to EMISSION_PATH describing the exploded path
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
558 EPATH within EG. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
559
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
560 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
561 diagnostic_manager::build_emission_path (const exploded_graph &eg,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
562 const exploded_path &epath,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
563 checker_path *emission_path) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
564 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
565 LOG_SCOPE (get_logger ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
566 const extrinsic_state &ext_state = eg.get_ext_state ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
567 for (unsigned i = 0; i < epath.m_edges.length (); i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
568 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
569 const exploded_edge *eedge = epath.m_edges[i];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
570 add_events_for_eedge (*eedge, ext_state, emission_path);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
571 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
572 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
573
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
574 /* Subclass of state_change_visitor that creates state_change_event
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
575 instances. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
576
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
577 class state_change_event_creator : public state_change_visitor
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
578 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
579 public:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
580 state_change_event_creator (const exploded_edge &eedge,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
581 checker_path *emission_path)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
582 : m_eedge (eedge),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
583 m_emission_path (emission_path)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
584 {}
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
585
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
586 bool on_global_state_change (const state_machine &sm,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
587 state_machine::state_t src_sm_val,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
588 state_machine::state_t dst_sm_val)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
589 FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
590 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
591 const exploded_node *src_node = m_eedge.m_src;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
592 const program_point &src_point = src_node->get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
593 const int src_stack_depth = src_point.get_stack_depth ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
594 const exploded_node *dst_node = m_eedge.m_dest;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
595 const gimple *stmt = src_point.get_stmt ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
596 const supernode *supernode = src_point.get_supernode ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
597 const program_state &dst_state = dst_node->get_state ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
598
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
599 int stack_depth = src_stack_depth;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
600
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
601 m_emission_path->add_event (new state_change_event (supernode,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
602 stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
603 stack_depth,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
604 sm,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
605 NULL_TREE,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
606 src_sm_val,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
607 dst_sm_val,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
608 NULL_TREE,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
609 dst_state));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
610 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
611 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
612
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
613 bool on_state_change (const state_machine &sm,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
614 state_machine::state_t src_sm_val,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
615 state_machine::state_t dst_sm_val,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
616 tree dst_rep,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
617 svalue_id dst_origin_sid) FINAL OVERRIDE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
618 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
619 const exploded_node *src_node = m_eedge.m_src;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
620 const program_point &src_point = src_node->get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
621 const int src_stack_depth = src_point.get_stack_depth ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
622 const exploded_node *dst_node = m_eedge.m_dest;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
623 const gimple *stmt = src_point.get_stmt ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
624 const supernode *supernode = src_point.get_supernode ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
625 const program_state &dst_state = dst_node->get_state ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
626
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
627 int stack_depth = src_stack_depth;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
628
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
629 if (m_eedge.m_sedge
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
630 && m_eedge.m_sedge->m_kind == SUPEREDGE_CFG_EDGE)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
631 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
632 supernode = src_point.get_supernode ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
633 stmt = supernode->get_last_stmt ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
634 stack_depth = src_stack_depth;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
635 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
636
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
637 /* Bulletproofing for state changes at calls/returns;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
638 TODO: is there a better way? */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
639 if (!stmt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
640 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
641
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
642 tree origin_rep
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
643 = dst_state.get_representative_tree (dst_origin_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
644
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
645 if (origin_rep == NULL_TREE)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
646 origin_rep = get_any_origin (stmt, dst_rep, dst_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
647 m_emission_path->add_event (new state_change_event (supernode,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
648 stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
649 stack_depth,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
650 sm,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
651 dst_rep,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
652 src_sm_val,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
653 dst_sm_val,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
654 origin_rep,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
655 dst_state));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
656 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
657 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
658
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
659 const exploded_edge &m_eedge;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
660 checker_path *m_emission_path;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
661 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
662
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
663 /* Compare SRC_STATE and DST_STATE (which use EXT_STATE), and call
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
664 VISITOR's on_state_change for every sm-state change that occurs
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
665 to a tree, and on_global_state_change for every global state change
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
666 that occurs.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
667
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
668 This determines the state changes that ought to be reported to
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
669 the user: a combination of the effects of changes to sm_state_map
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
670 (which maps svalues to sm-states), and of region_model changes
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
671 (which map trees to svalues).
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
672
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
673 Bail out early and return true if any call to on_global_state_change
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
674 or on_state_change returns true, otherwise return false.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
675
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
676 This is split out to make it easier to experiment with changes to
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
677 exploded_node granularity (so that we can observe what state changes
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
678 lead to state_change_events being emitted). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
679
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
680 bool
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
681 for_each_state_change (const program_state &src_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
682 const program_state &dst_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
683 const extrinsic_state &ext_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
684 state_change_visitor *visitor)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
685 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
686 gcc_assert (src_state.m_checker_states.length ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
687 == ext_state.get_num_checkers ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
688 gcc_assert (dst_state.m_checker_states.length ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
689 == ext_state.get_num_checkers ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
690 for (unsigned i = 0; i < ext_state.get_num_checkers (); i++)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
691 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
692 const state_machine &sm = ext_state.get_sm (i);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
693 const sm_state_map &src_smap = *src_state.m_checker_states[i];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
694 const sm_state_map &dst_smap = *dst_state.m_checker_states[i];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
695
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
696 /* Add events for any global state changes. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
697 if (src_smap.get_global_state () != dst_smap.get_global_state ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
698 if (visitor->on_global_state_change (sm,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
699 src_smap.get_global_state (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
700 dst_smap.get_global_state ()))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
701 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
702
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
703 /* Add events for per-svalue state changes. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
704 for (sm_state_map::iterator_t iter = dst_smap.begin ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
705 iter != dst_smap.end ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
706 ++iter)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
707 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
708 /* Ideally we'd directly compare the SM state between src state
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
709 and dst state, but there's no guarantee that the IDs can
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
710 be meaningfully compared. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
711 svalue_id dst_sid = (*iter).first;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
712 state_machine::state_t dst_sm_val = (*iter).second.m_state;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
713
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
714 auto_vec<path_var> dst_pvs;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
715 dst_state.m_region_model->get_path_vars_for_svalue (dst_sid,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
716 &dst_pvs);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
717
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
718 unsigned j;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
719 path_var *dst_pv;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
720 FOR_EACH_VEC_ELT (dst_pvs, j, dst_pv)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
721 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
722 tree dst_rep = dst_pv->m_tree;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
723 gcc_assert (dst_rep);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
724 if (dst_pv->m_stack_depth
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
725 >= src_state.m_region_model->get_stack_depth ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
726 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
727 svalue_id src_sid
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
728 = src_state.m_region_model->get_rvalue (*dst_pv, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
729 if (src_sid.null_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
730 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
731 state_machine::state_t src_sm_val = src_smap.get_state (src_sid);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
732 if (dst_sm_val != src_sm_val)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
733 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
734 svalue_id dst_origin_sid = (*iter).second.m_origin;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
735 if (visitor->on_state_change (sm, src_sm_val, dst_sm_val,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
736 dst_rep, dst_origin_sid))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
737 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
738 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
739 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
740 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
741 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
742 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
743 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
744
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
745 /* Subroutine of diagnostic_manager::build_emission_path.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
746 Add any events for EEDGE to EMISSION_PATH. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
747
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
748 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
749 diagnostic_manager::add_events_for_eedge (const exploded_edge &eedge,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
750 const extrinsic_state &ext_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
751 checker_path *emission_path) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
752 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
753 const exploded_node *src_node = eedge.m_src;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
754 const program_point &src_point = src_node->get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
755 const exploded_node *dst_node = eedge.m_dest;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
756 const program_point &dst_point = dst_node->get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
757 const int dst_stack_depth = dst_point.get_stack_depth ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
758 if (get_logger ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
759 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
760 get_logger ()->start_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
761 pretty_printer *pp = get_logger ()->get_printer ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
762 pp_printf (pp, "EN %i -> EN %i: ",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
763 eedge.m_src->m_index,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
764 eedge.m_dest->m_index);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
765 src_point.print (pp, format (false));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
766 pp_string (pp, "-> ");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
767 dst_point.print (pp, format (false));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
768 get_logger ()->end_log_line ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
769 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
770 const program_state &src_state = src_node->get_state ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
771 const program_state &dst_state = dst_node->get_state ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
772
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
773 /* Add state change events for the states that have changed.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
774 We add these before events for superedges, so that if we have a
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
775 state_change_event due to following an edge, we'll get this sequence
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
776 of events:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
777
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
778 | if (!ptr)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
779 | ~
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
780 | |
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
781 | (1) assuming 'ptr' is non-NULL (state_change_event)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
782 | (2) following 'false' branch... (start_cfg_edge_event)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
783 ...
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
784 | do_something (ptr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
785 | ~~~~~~~~~~~~~^~~~~
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
786 | |
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
787 | (3) ...to here (end_cfg_edge_event). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
788 state_change_event_creator visitor (eedge, emission_path);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
789 for_each_state_change (src_state, dst_state, ext_state,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
790 &visitor);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
791
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
792 /* Allow non-standard edges to add events, e.g. when rewinding from
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
793 longjmp to a setjmp. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
794 if (eedge.m_custom_info)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
795 eedge.m_custom_info->add_events_to_path (emission_path, eedge);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
796
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
797 /* Add events for superedges, function entries, and for statements. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
798 switch (dst_point.get_kind ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
799 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
800 default:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
801 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
802 case PK_BEFORE_SUPERNODE:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
803 if (src_point.get_kind () == PK_AFTER_SUPERNODE)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
804 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
805 if (eedge.m_sedge)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
806 add_events_for_superedge (eedge, emission_path);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
807 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
808 /* Add function entry events. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
809 if (dst_point.get_supernode ()->entry_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
810 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
811 emission_path->add_event
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
812 (new function_entry_event
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
813 (dst_point.get_supernode ()->get_start_location (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
814 dst_point.get_fndecl (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
815 dst_stack_depth));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
816 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
817 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
818 case PK_BEFORE_STMT:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
819 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
820 const gimple *stmt = dst_point.get_stmt ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
821 const gcall *call = dyn_cast <const gcall *> (stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
822 if (call && is_setjmp_call_p (call))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
823 emission_path->add_event
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
824 (new setjmp_event (stmt->location,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
825 dst_node,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
826 dst_point.get_fndecl (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
827 dst_stack_depth,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
828 call));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
829 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
830 emission_path->add_event
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
831 (new statement_event (stmt,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
832 dst_point.get_fndecl (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
833 dst_stack_depth, dst_state));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
834 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
835 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
836 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
837 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
838
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
839 /* Subroutine of diagnostic_manager::add_events_for_eedge
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
840 where EEDGE has an underlying superedge i.e. a CFG edge,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
841 or an interprocedural call/return.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
842 Add any events for the superedge to EMISSION_PATH. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
843
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
844 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
845 diagnostic_manager::add_events_for_superedge (const exploded_edge &eedge,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
846 checker_path *emission_path)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
847 const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
848 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
849 gcc_assert (eedge.m_sedge);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
850
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
851 const exploded_node *src_node = eedge.m_src;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
852 const program_point &src_point = src_node->get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
853 const exploded_node *dst_node = eedge.m_dest;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
854 const program_point &dst_point = dst_node->get_point ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
855 const int src_stack_depth = src_point.get_stack_depth ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
856 const int dst_stack_depth = dst_point.get_stack_depth ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
857 const gimple *last_stmt = src_point.get_supernode ()->get_last_stmt ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
858
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
859 switch (eedge.m_sedge->m_kind)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
860 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
861 case SUPEREDGE_CFG_EDGE:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
862 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
863 emission_path->add_event
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
864 (new start_cfg_edge_event (eedge,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
865 (last_stmt
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
866 ? last_stmt->location
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
867 : UNKNOWN_LOCATION),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
868 src_point.get_fndecl (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
869 src_stack_depth));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
870 emission_path->add_event
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
871 (new end_cfg_edge_event (eedge,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
872 dst_point.get_supernode ()->get_start_location (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
873 dst_point.get_fndecl (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
874 dst_stack_depth));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
875 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
876 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
877
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
878 case SUPEREDGE_CALL:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
879 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
880 emission_path->add_event
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
881 (new call_event (eedge,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
882 (last_stmt
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
883 ? last_stmt->location
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
884 : UNKNOWN_LOCATION),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
885 src_point.get_fndecl (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
886 src_stack_depth));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
887 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
888 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
889
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
890 case SUPEREDGE_INTRAPROCEDURAL_CALL:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
891 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
892 /* TODO: add a subclass for this, or generate events for the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
893 summary. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
894 emission_path->add_event
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
895 (new debug_event ((last_stmt
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
896 ? last_stmt->location
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
897 : UNKNOWN_LOCATION),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
898 src_point.get_fndecl (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
899 src_stack_depth,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
900 "call summary"));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
901 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
902 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
903
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
904 case SUPEREDGE_RETURN:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
905 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
906 const return_superedge *return_edge
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
907 = as_a <const return_superedge *> (eedge.m_sedge);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
908
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
909 const gcall *call_stmt = return_edge->get_call_stmt ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
910 emission_path->add_event
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
911 (new return_event (eedge,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
912 (call_stmt
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
913 ? call_stmt->location
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
914 : UNKNOWN_LOCATION),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
915 dst_point.get_fndecl (),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
916 dst_stack_depth));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
917 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
918 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
919 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
920 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
921
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
922 /* Prune PATH, based on the verbosity level, to the most pertinent
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
923 events for a diagnostic that involves VAR ending in state STATE
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
924 (for state machine SM).
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
925
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
926 PATH is updated in place, and the redundant checker_events are deleted.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
927
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
928 As well as deleting events, call record_critical_state on events in
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
929 which state critical to the pending_diagnostic is being handled; see
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
930 the comment for diagnostic_manager::prune_for_sm_diagnostic. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
931
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
932 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
933 diagnostic_manager::prune_path (checker_path *path,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
934 const state_machine *sm,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
935 tree var,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
936 state_machine::state_t state) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
937 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
938 LOG_FUNC (get_logger ());
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
939 path->maybe_log (get_logger (), "path");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
940 prune_for_sm_diagnostic (path, sm, var, state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
941 prune_interproc_events (path);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
942 finish_pruning (path);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
943 path->maybe_log (get_logger (), "pruned");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
944 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
945
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
946 /* First pass of diagnostic_manager::prune_path: apply verbosity level,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
947 pruning unrelated state change events.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
948
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
949 Iterate backwards through PATH, skipping state change events that aren't
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
950 VAR but update the pertinent VAR when state-copying occurs.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
951
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
952 As well as deleting events, call record_critical_state on events in
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
953 which state critical to the pending_diagnostic is being handled, so
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
954 that the event's get_desc vfunc can potentially supply a more precise
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
955 description of the event to the user.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
956 e.g. improving
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
957 "calling 'foo' from 'bar'"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
958 to
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
959 "passing possibly-NULL pointer 'ptr' to 'foo' from 'bar' as param 1"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
960 when the diagnostic relates to later dereferencing 'ptr'. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
961
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
962 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
963 diagnostic_manager::prune_for_sm_diagnostic (checker_path *path,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
964 const state_machine *sm,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
965 tree var,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
966 state_machine::state_t state) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
967 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
968 /* If we have a constant (such as NULL), assume its state is also
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
969 constant, so as not to attempt to get its lvalue whilst tracking the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
970 origin of the state. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
971 if (var && CONSTANT_CLASS_P (var))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
972 var = NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
973
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
974 int idx = path->num_events () - 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
975 while (idx >= 0 && idx < (signed)path->num_events ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
976 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
977 checker_event *base_event = path->get_checker_event (idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
978 if (get_logger ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
979 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
980 if (sm)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
981 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
982 if (var)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
983 log ("considering event %i, with var: %qE, state: %qs",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
984 idx, var, sm->get_state_name (state));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
985 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
986 log ("considering event %i, with global state: %qs",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
987 idx, sm->get_state_name (state));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
988 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
989 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
990 log ("considering event %i", idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
991 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
992 switch (base_event->m_kind)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
993 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
994 default:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
995 gcc_unreachable ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
996
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
997 case EK_DEBUG:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
998 if (m_verbosity < 3)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
999 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1000 log ("filtering event %i: debug event", idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1001 path->delete_event (idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1002 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1003 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1004
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1005 case EK_CUSTOM:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1006 /* Don't filter custom events. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1007 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1008
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1009 case EK_STMT:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1010 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1011 /* If this stmt is the origin of "var", update var. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1012 if (var)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1013 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1014 statement_event *stmt_event = (statement_event *)base_event;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1015 tree new_var = get_any_origin (stmt_event->m_stmt, var,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1016 stmt_event->m_dst_state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1017 if (new_var)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1018 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1019 log ("event %i: switching var of interest from %qE to %qE",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1020 idx, var, new_var);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1021 var = new_var;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1022 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1023 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1024 if (m_verbosity < 3)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1025 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1026 log ("filtering event %i: statement event", idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1027 path->delete_event (idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1028 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1029 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1030 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1031
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1032 case EK_FUNCTION_ENTRY:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1033 if (m_verbosity < 1)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1034 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1035 log ("filtering event %i: function entry", idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1036 path->delete_event (idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1037 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1038 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1039
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1040 case EK_STATE_CHANGE:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1041 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1042 state_change_event *state_change = (state_change_event *)base_event;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1043 if (state_change->get_lvalue (state_change->m_var)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1044 == state_change->get_lvalue (var))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1045 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1046 if (state_change->m_origin)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1047 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1048 log ("event %i: switching var of interest from %qE to %qE",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1049 idx, var, state_change->m_origin);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1050 var = state_change->m_origin;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1051 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1052 log ("event %i: switching state of interest from %qs to %qs",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1053 idx, sm->get_state_name (state_change->m_to),
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1054 sm->get_state_name (state_change->m_from));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1055 state = state_change->m_from;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1056 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1057 else if (m_verbosity < 3)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1058 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1059 if (var)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1060 log ("filtering event %i:"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1061 " state change to %qE unrelated to %qE",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1062 idx, state_change->m_var, var);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1063 else
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1064 log ("filtering event %i: state change to %qE",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1065 idx, state_change->m_var);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1066 path->delete_event (idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1067 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1068 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1069 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1070
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1071 case EK_START_CFG_EDGE:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1072 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1073 cfg_edge_event *event = (cfg_edge_event *)base_event;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1074 const cfg_superedge& cfg_superedge
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1075 = event->get_cfg_superedge ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1076 const supernode *dest = event->m_sedge->m_dest;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1077 /* Do we have an SSA_NAME defined via a phi node in
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1078 the dest CFG node? */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1079 if (var && TREE_CODE (var) == SSA_NAME)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1080 if (SSA_NAME_DEF_STMT (var)->bb == dest->m_bb)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1081 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1082 if (gphi *phi
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1083 = dyn_cast <gphi *> (SSA_NAME_DEF_STMT (var)))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1084 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1085 /* Update var based on its phi node. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1086 tree old_var = var;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1087 var = cfg_superedge.get_phi_arg (phi);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1088 log ("updating from %qE to %qE based on phi node",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1089 old_var, var);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1090 if (get_logger ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1091 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1092 pretty_printer pp;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1093 pp_gimple_stmt_1 (&pp, phi, 0, (dump_flags_t)0);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1094 log (" phi: %s", pp_formatted_text (&pp));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1095 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1096 /* If we've chosen a bad exploded_path, then the
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1097 phi arg might be a constant. Fail gracefully for
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1098 this case. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1099 if (CONSTANT_CLASS_P (var))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1100 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1101 log ("new var is a constant (bad path?);"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1102 " setting var to NULL");
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1103 var = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1104 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1105 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1106 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1107
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1108 /* TODO: is this edge significant to var?
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1109 See if var can be in other states in the dest, but not
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1110 in other states in the src?
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1111 Must have multiple sibling edges. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1112
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1113 if (event->should_filter_p (m_verbosity))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1114 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1115 log ("filtering event %i: CFG edge", idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1116 path->delete_event (idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1117 /* Also delete the corresponding EK_END_CFG_EDGE. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1118 gcc_assert (path->get_checker_event (idx)->m_kind
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1119 == EK_END_CFG_EDGE);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1120 path->delete_event (idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1121 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1122 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1123 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1124
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1125 case EK_END_CFG_EDGE:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1126 /* These come in pairs with EK_START_CFG_EDGE events and are
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1127 filtered when their start event is filtered. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1128 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1129
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1130 case EK_CALL_EDGE:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1131 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1132 call_event *event = (call_event *)base_event;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1133 const callgraph_superedge& cg_superedge
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1134 = event->get_callgraph_superedge ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1135 callsite_expr expr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1136 tree caller_var
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1137 = cg_superedge.map_expr_from_callee_to_caller (var, &expr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1138 if (caller_var)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1139 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1140 log ("event %i:"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1141 " switching var of interest"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1142 " from %qE in callee to %qE in caller",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1143 idx, var, caller_var);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1144 var = caller_var;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1145 if (expr.param_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1146 event->record_critical_state (var, state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1147 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1148 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1149 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1150
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1151 case EK_RETURN_EDGE:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1152 // TODO: potentially update var/state based on return value,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1153 // args etc
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1154 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1155 if (var)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1156 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1157 return_event *event = (return_event *)base_event;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1158 const callgraph_superedge& cg_superedge
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1159 = event->get_callgraph_superedge ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1160 callsite_expr expr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1161 tree callee_var
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1162 = cg_superedge.map_expr_from_caller_to_callee (var, &expr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1163 if (callee_var)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1164 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1165 log ("event %i:"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1166 " switching var of interest"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1167 " from %qE in caller to %qE in callee",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1168 idx, var, callee_var);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1169 var = callee_var;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1170 if (expr.return_value_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1171 event->record_critical_state (var, state);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1172 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1173 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1174 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1175 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1176
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1177 case EK_SETJMP:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1178 /* TODO: only show setjmp_events that matter i.e. those for which
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1179 there is a later rewind event using them. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1180 case EK_REWIND_FROM_LONGJMP:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1181 case EK_REWIND_TO_SETJMP:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1182 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1183
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1184 case EK_WARNING:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1185 /* Always show the final "warning" event in the path. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1186 break;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1187 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1188 idx--;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1189 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1190 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1191
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1192 /* Second pass of diagnostic_manager::prune_path: remove redundant
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1193 interprocedural information.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1194
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1195 For example, given:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1196 (1)- calling "f2" from "f1"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1197 (2)--- entry to "f2"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1198 (3)--- calling "f3" from "f2"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1199 (4)----- entry to "f3"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1200 (5)--- returning to "f2" to "f3"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1201 (6)- returning to "f1" to "f2"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1202 with no other intervening events, then none of these events are
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1203 likely to be interesting to the user.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1204
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1205 Prune [..., call, function-entry, return, ...] triples repeatedly
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1206 until nothing has changed. For the example above, this would
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1207 remove events (3, 4, 5), and then remove events (1, 2, 6). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1208
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1209 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1210 diagnostic_manager::prune_interproc_events (checker_path *path) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1211 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1212 bool changed = false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1213 do
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1214 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1215 changed = false;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1216 int idx = path->num_events () - 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1217 while (idx >= 0)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1218 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1219 /* Prune [..., call, function-entry, return, ...] triples. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1220 if (idx + 2 < (signed)path->num_events ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1221 && path->get_checker_event (idx)->is_call_p ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1222 && path->get_checker_event (idx + 1)->is_function_entry_p ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1223 && path->get_checker_event (idx + 2)->is_return_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1224 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1225 if (get_logger ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1226 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1227 label_text desc
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1228 (path->get_checker_event (idx)->get_desc (false));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1229 log ("filtering events %i-%i:"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1230 " irrelevant call/entry/return: %s",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1231 idx, idx + 2, desc.m_buffer);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1232 desc.maybe_free ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1233 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1234 path->delete_event (idx + 2);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1235 path->delete_event (idx + 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1236 path->delete_event (idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1237 changed = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1238 idx--;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1239 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1240 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1241
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1242 /* Prune [..., call, return, ...] pairs
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1243 (for -fanalyzer-verbosity=0). */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1244 if (idx + 1 < (signed)path->num_events ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1245 && path->get_checker_event (idx)->is_call_p ()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1246 && path->get_checker_event (idx + 1)->is_return_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1247 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1248 if (get_logger ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1249 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1250 label_text desc
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1251 (path->get_checker_event (idx)->get_desc (false));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1252 log ("filtering events %i-%i:"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1253 " irrelevant call/return: %s",
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1254 idx, idx + 1, desc.m_buffer);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1255 desc.maybe_free ();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1256 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1257 path->delete_event (idx + 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1258 path->delete_event (idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1259 changed = true;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1260 idx--;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1261 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1262 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1263
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1264 idx--;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1265 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1266
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1267 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1268 while (changed);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1269 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1270
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1271 /* Final pass of diagnostic_manager::prune_path.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1272
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1273 If all we're left with is in one function, then filter function entry
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1274 events. */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1275
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1276 void
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1277 diagnostic_manager::finish_pruning (checker_path *path) const
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1278 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1279 if (!path->interprocedural_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1280 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1281 int idx = path->num_events () - 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1282 while (idx >= 0 && idx < (signed)path->num_events ())
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1283 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1284 checker_event *base_event = path->get_checker_event (idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1285 if (base_event->m_kind == EK_FUNCTION_ENTRY)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1286 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1287 log ("filtering event %i:"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1288 " function entry for purely intraprocedural path", idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1289 path->delete_event (idx);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1290 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1291 idx--;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1292 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1293 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1294 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1295
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1296 } // namespace ana
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1297
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1298 #endif /* #if ENABLE_ANALYZER */