analyzer: eliminate non-determinism in logs
[gcc.git] / gcc / analyzer / analyzer.h
1 /* Utility functions for the analyzer.
2 Copyright (C) 2019-2020 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 #ifndef GCC_ANALYZER_ANALYZER_H
22 #define GCC_ANALYZER_ANALYZER_H
23
24 class graphviz_out;
25
26 namespace ana {
27
28 /* Forward decls of common types, with indentation to show inheritance. */
29
30 class supergraph;
31 class supernode;
32 class superedge;
33 class cfg_superedge;
34 class switch_cfg_superedge;
35 class callgraph_superedge;
36 class call_superedge;
37 class return_superedge;
38
39 class svalue;
40 class region_svalue;
41 class constant_svalue;
42 class unknown_svalue;
43 class poisoned_svalue;
44 class setjmp_svalue;
45 class initial_svalue;
46 class unaryop_svalue;
47 class binop_svalue;
48 class sub_svalue;
49 class unmergeable_svalue;
50 class placeholder_svalue;
51 class widening_svalue;
52 class compound_svalue;
53 class conjured_svalue;
54 typedef hash_set<const svalue *> svalue_set;
55 class region;
56 class frame_region;
57 class function_region;
58 class label_region;
59 class decl_region;
60 class symbolic_region;
61 class element_region;
62 class offset_region;
63 class cast_region;
64 class field_region;
65 class string_region;
66 class region_model_manager;
67 struct model_merger;
68 class store_manager;
69 class store;
70 class region_model;
71 class region_model_context;
72 class impl_region_model_context;
73 class call_details;
74 struct rejected_constraint;
75 class constraint_manager;
76 class equiv_class;
77
78 class pending_diagnostic;
79 class state_change_event;
80 class checker_path;
81 class extrinsic_state;
82 class sm_state_map;
83 class stmt_finder;
84 class program_point;
85 class function_point;
86 class program_state;
87 class exploded_graph;
88 class exploded_node;
89 class exploded_edge;
90 class feasibility_problem;
91 class exploded_cluster;
92 class exploded_path;
93 class analysis_plan;
94 class state_purge_map;
95 class state_purge_per_ssa_name;
96 class state_change;
97 class rewind_info_t;
98
99 class engine;
100
101 /* Forward decls of functions. */
102
103 extern void dump_tree (pretty_printer *pp, tree t);
104 extern void dump_quoted_tree (pretty_printer *pp, tree t);
105 extern void print_quoted_type (pretty_printer *pp, tree t);
106 extern int readability_comparator (const void *p1, const void *p2);
107 extern int tree_cmp (const void *p1, const void *p2);
108
109 /* A tree, extended with stack frame information for locals, so that
110 we can distinguish between different values of locals within a potentially
111 recursive callstack. */
112
113 class path_var
114 {
115 public:
116 path_var (tree t, int stack_depth)
117 : m_tree (t), m_stack_depth (stack_depth)
118 {
119 // TODO: ignore stack depth for globals and constants
120 }
121
122 bool operator== (const path_var &other) const
123 {
124 return (m_tree == other.m_tree
125 && m_stack_depth == other.m_stack_depth);
126 }
127
128 operator bool () const
129 {
130 return m_tree != NULL_TREE;
131 }
132
133 void dump (pretty_printer *pp) const;
134
135 tree m_tree;
136 int m_stack_depth; // or -1 for globals?
137 };
138
139 typedef offset_int bit_offset_t;
140 typedef offset_int bit_size_t;
141 typedef offset_int byte_size_t;
142
143 /* The location of a region expressesd as an offset relative to a
144 base region. */
145
146 class region_offset
147 {
148 public:
149 static region_offset make_concrete (const region *base_region,
150 bit_offset_t offset)
151 {
152 return region_offset (base_region, offset, false);
153 }
154 static region_offset make_symbolic (const region *base_region)
155 {
156 return region_offset (base_region, 0, true);
157 }
158
159 const region *get_base_region () const { return m_base_region; }
160
161 bool symbolic_p () const { return m_is_symbolic; }
162
163 bit_offset_t get_bit_offset () const
164 {
165 gcc_assert (!symbolic_p ());
166 return m_offset;
167 }
168
169 bool operator== (const region_offset &other)
170 {
171 return (m_base_region == other.m_base_region
172 && m_offset == other.m_offset
173 && m_is_symbolic == other.m_is_symbolic);
174 }
175
176 private:
177 region_offset (const region *base_region, bit_offset_t offset,
178 bool is_symbolic)
179 : m_base_region (base_region), m_offset (offset), m_is_symbolic (is_symbolic)
180 {}
181
182 const region *m_base_region;
183 bit_offset_t m_offset;
184 bool m_is_symbolic;
185 };
186
187 extern location_t get_stmt_location (const gimple *stmt, function *fun);
188
189 } // namespace ana
190
191 extern bool is_special_named_call_p (const gcall *call, const char *funcname,
192 unsigned int num_args);
193 extern bool is_named_call_p (tree fndecl, const char *funcname);
194 extern bool is_named_call_p (tree fndecl, const char *funcname,
195 const gcall *call, unsigned int num_args);
196 extern bool is_std_named_call_p (tree fndecl, const char *funcname,
197 const gcall *call, unsigned int num_args);
198 extern bool is_setjmp_call_p (const gcall *call);
199 extern bool is_longjmp_call_p (const gcall *call);
200
201 extern const char *get_user_facing_name (const gcall *call);
202
203 extern void register_analyzer_pass ();
204
205 extern label_text make_label_text (bool can_colorize, const char *fmt, ...);
206
207 extern bool fndecl_has_gimple_body_p (tree fndecl);
208
209 /* An RAII-style class for pushing/popping cfun within a scope.
210 Doing so ensures we get "In function " announcements
211 from the diagnostics subsystem. */
212
213 class auto_cfun
214 {
215 public:
216 auto_cfun (function *fun) { push_cfun (fun); }
217 ~auto_cfun () { pop_cfun (); }
218 };
219
220 /* A template for creating hash traits for a POD type. */
221
222 template <typename Type>
223 struct pod_hash_traits : typed_noop_remove<Type>
224 {
225 typedef Type value_type;
226 typedef Type compare_type;
227 static inline hashval_t hash (value_type);
228 static inline bool equal (const value_type &existing,
229 const value_type &candidate);
230 static inline void mark_deleted (Type &);
231 static inline void mark_empty (Type &);
232 static inline bool is_deleted (Type);
233 static inline bool is_empty (Type);
234 };
235
236 /* A hash traits class that uses member functions to implement
237 the various required ops. */
238
239 template <typename Type>
240 struct member_function_hash_traits : public typed_noop_remove<Type>
241 {
242 typedef Type value_type;
243 typedef Type compare_type;
244 static inline hashval_t hash (value_type v) { return v.hash (); }
245 static inline bool equal (const value_type &existing,
246 const value_type &candidate)
247 {
248 return existing == candidate;
249 }
250 static inline void mark_deleted (Type &t) { t.mark_deleted (); }
251 static inline void mark_empty (Type &t) { t.mark_empty (); }
252 static inline bool is_deleted (Type t) { return t.is_deleted (); }
253 static inline bool is_empty (Type t) { return t.is_empty (); }
254 };
255
256 /* A map from T::key_t to T* for use in consolidating instances of T.
257 Owns all instances of T.
258 T::key_t should have operator== and be hashable. */
259
260 template <typename T>
261 class consolidation_map
262 {
263 public:
264 typedef typename T::key_t key_t;
265 typedef T instance_t;
266 typedef hash_map<key_t, instance_t *> inner_map_t;
267 typedef typename inner_map_t::iterator iterator;
268
269 /* Delete all instances of T. */
270
271 ~consolidation_map ()
272 {
273 for (typename inner_map_t::iterator iter = m_inner_map.begin ();
274 iter != m_inner_map.end (); ++iter)
275 delete (*iter).second;
276 }
277
278 /* Get the instance of T for K if one exists, or NULL. */
279
280 T *get (const key_t &k) const
281 {
282 if (instance_t **slot = const_cast<inner_map_t &> (m_inner_map).get (k))
283 return *slot;
284 return NULL;
285 }
286
287 /* Take ownership of INSTANCE. */
288
289 void put (const key_t &k, T *instance)
290 {
291 m_inner_map.put (k, instance);
292 }
293
294 size_t elements () const { return m_inner_map.elements (); }
295
296 iterator begin () const { return m_inner_map.begin (); }
297 iterator end () const { return m_inner_map.end (); }
298
299 private:
300 inner_map_t m_inner_map;
301 };
302
303 /* Disable -Wformat-diag; we want to be able to use pp_printf
304 for logging/dumping without complying with the rules for diagnostics. */
305 #if __GNUC__ >= 10
306 #pragma GCC diagnostic ignored "-Wformat-diag"
307 #endif
308
309 #endif /* GCC_ANALYZER_ANALYZER_H */