Add analyzer plugin support and CPython GIL example
[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 class state_machine;
101 class logger;
102 class visitor;
103
104 /* Forward decls of functions. */
105
106 extern void dump_tree (pretty_printer *pp, tree t);
107 extern void dump_quoted_tree (pretty_printer *pp, tree t);
108 extern void print_quoted_type (pretty_printer *pp, tree t);
109 extern int readability_comparator (const void *p1, const void *p2);
110 extern int tree_cmp (const void *p1, const void *p2);
111
112 /* A tree, extended with stack frame information for locals, so that
113 we can distinguish between different values of locals within a potentially
114 recursive callstack. */
115
116 class path_var
117 {
118 public:
119 path_var (tree t, int stack_depth)
120 : m_tree (t), m_stack_depth (stack_depth)
121 {
122 // TODO: ignore stack depth for globals and constants
123 }
124
125 bool operator== (const path_var &other) const
126 {
127 return (m_tree == other.m_tree
128 && m_stack_depth == other.m_stack_depth);
129 }
130
131 operator bool () const
132 {
133 return m_tree != NULL_TREE;
134 }
135
136 void dump (pretty_printer *pp) const;
137
138 tree m_tree;
139 int m_stack_depth; // or -1 for globals?
140 };
141
142 typedef offset_int bit_offset_t;
143 typedef offset_int bit_size_t;
144 typedef offset_int byte_size_t;
145
146 /* The location of a region expressesd as an offset relative to a
147 base region. */
148
149 class region_offset
150 {
151 public:
152 static region_offset make_concrete (const region *base_region,
153 bit_offset_t offset)
154 {
155 return region_offset (base_region, offset, false);
156 }
157 static region_offset make_symbolic (const region *base_region)
158 {
159 return region_offset (base_region, 0, true);
160 }
161
162 const region *get_base_region () const { return m_base_region; }
163
164 bool symbolic_p () const { return m_is_symbolic; }
165
166 bit_offset_t get_bit_offset () const
167 {
168 gcc_assert (!symbolic_p ());
169 return m_offset;
170 }
171
172 bool operator== (const region_offset &other)
173 {
174 return (m_base_region == other.m_base_region
175 && m_offset == other.m_offset
176 && m_is_symbolic == other.m_is_symbolic);
177 }
178
179 private:
180 region_offset (const region *base_region, bit_offset_t offset,
181 bool is_symbolic)
182 : m_base_region (base_region), m_offset (offset), m_is_symbolic (is_symbolic)
183 {}
184
185 const region *m_base_region;
186 bit_offset_t m_offset;
187 bool m_is_symbolic;
188 };
189
190 extern location_t get_stmt_location (const gimple *stmt, function *fun);
191
192 /* Passed by pointer to PLUGIN_ANALYZER_INIT callbacks. */
193
194 class plugin_analyzer_init_iface
195 {
196 public:
197 virtual void register_state_machine (state_machine *) = 0;
198 virtual logger *get_logger () const = 0;
199 };
200
201 } // namespace ana
202
203 extern bool is_special_named_call_p (const gcall *call, const char *funcname,
204 unsigned int num_args);
205 extern bool is_named_call_p (tree fndecl, const char *funcname);
206 extern bool is_named_call_p (tree fndecl, const char *funcname,
207 const gcall *call, unsigned int num_args);
208 extern bool is_std_named_call_p (tree fndecl, const char *funcname,
209 const gcall *call, unsigned int num_args);
210 extern bool is_setjmp_call_p (const gcall *call);
211 extern bool is_longjmp_call_p (const gcall *call);
212
213 extern const char *get_user_facing_name (const gcall *call);
214
215 extern void register_analyzer_pass ();
216
217 extern label_text make_label_text (bool can_colorize, const char *fmt, ...);
218
219 extern bool fndecl_has_gimple_body_p (tree fndecl);
220
221 /* An RAII-style class for pushing/popping cfun within a scope.
222 Doing so ensures we get "In function " announcements
223 from the diagnostics subsystem. */
224
225 class auto_cfun
226 {
227 public:
228 auto_cfun (function *fun) { push_cfun (fun); }
229 ~auto_cfun () { pop_cfun (); }
230 };
231
232 /* A template for creating hash traits for a POD type. */
233
234 template <typename Type>
235 struct pod_hash_traits : typed_noop_remove<Type>
236 {
237 typedef Type value_type;
238 typedef Type compare_type;
239 static inline hashval_t hash (value_type);
240 static inline bool equal (const value_type &existing,
241 const value_type &candidate);
242 static inline void mark_deleted (Type &);
243 static inline void mark_empty (Type &);
244 static inline bool is_deleted (Type);
245 static inline bool is_empty (Type);
246 };
247
248 /* A hash traits class that uses member functions to implement
249 the various required ops. */
250
251 template <typename Type>
252 struct member_function_hash_traits : public typed_noop_remove<Type>
253 {
254 typedef Type value_type;
255 typedef Type compare_type;
256 static inline hashval_t hash (value_type v) { return v.hash (); }
257 static inline bool equal (const value_type &existing,
258 const value_type &candidate)
259 {
260 return existing == candidate;
261 }
262 static inline void mark_deleted (Type &t) { t.mark_deleted (); }
263 static inline void mark_empty (Type &t) { t.mark_empty (); }
264 static inline bool is_deleted (Type t) { return t.is_deleted (); }
265 static inline bool is_empty (Type t) { return t.is_empty (); }
266 };
267
268 /* A map from T::key_t to T* for use in consolidating instances of T.
269 Owns all instances of T.
270 T::key_t should have operator== and be hashable. */
271
272 template <typename T>
273 class consolidation_map
274 {
275 public:
276 typedef typename T::key_t key_t;
277 typedef T instance_t;
278 typedef hash_map<key_t, instance_t *> inner_map_t;
279 typedef typename inner_map_t::iterator iterator;
280
281 /* Delete all instances of T. */
282
283 ~consolidation_map ()
284 {
285 for (typename inner_map_t::iterator iter = m_inner_map.begin ();
286 iter != m_inner_map.end (); ++iter)
287 delete (*iter).second;
288 }
289
290 /* Get the instance of T for K if one exists, or NULL. */
291
292 T *get (const key_t &k) const
293 {
294 if (instance_t **slot = const_cast<inner_map_t &> (m_inner_map).get (k))
295 return *slot;
296 return NULL;
297 }
298
299 /* Take ownership of INSTANCE. */
300
301 void put (const key_t &k, T *instance)
302 {
303 m_inner_map.put (k, instance);
304 }
305
306 size_t elements () const { return m_inner_map.elements (); }
307
308 iterator begin () const { return m_inner_map.begin (); }
309 iterator end () const { return m_inner_map.end (); }
310
311 private:
312 inner_map_t m_inner_map;
313 };
314
315 /* Disable -Wformat-diag; we want to be able to use pp_printf
316 for logging/dumping without complying with the rules for diagnostics. */
317 #if __GNUC__ >= 10
318 #pragma GCC diagnostic ignored "-Wformat-diag"
319 #endif
320
321 #if !ENABLE_ANALYZER
322 extern void sorry_no_analyzer ();
323 #endif /* #if !ENABLE_ANALYZER */
324
325 #endif /* GCC_ANALYZER_ANALYZER_H */