1 /* Utility functions for the analyzer.
2 Copyright (C) 2019-2022 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #ifndef GCC_ANALYZER_ANALYZER_H
22 #define GCC_ANALYZER_ANALYZER_H
28 /* Forward decls of common types, with indentation to show inheritance. */
34 class switch_cfg_superedge
;
35 class callgraph_superedge
;
37 class return_superedge
;
41 class constant_svalue
;
43 class poisoned_svalue
;
49 class repeated_svalue
;
50 class bits_within_svalue
;
51 class unmergeable_svalue
;
52 class placeholder_svalue
;
53 class widening_svalue
;
54 class compound_svalue
;
55 class conjured_svalue
;
56 class asm_output_svalue
;
57 class const_fn_result_svalue
;
58 typedef hash_set
<const svalue
*> svalue_set
;
61 class function_region
;
64 class symbolic_region
;
71 class bit_range_region
;
73 class region_model_manager
;
79 class region_model_context
;
80 class impl_region_model_context
;
82 class rejected_constraint
;
83 class constraint_manager
;
85 class reachable_regions
;
87 class bounded_ranges_manager
;
89 class pending_diagnostic
;
91 class state_change_event
;
93 class extrinsic_state
;
102 class feasibility_problem
;
103 class exploded_cluster
;
106 class state_purge_map
;
107 class state_purge_per_ssa_name
;
108 class state_purge_per_decl
;
117 /* Forward decls of functions. */
119 extern void dump_tree (pretty_printer
*pp
, tree t
);
120 extern void dump_quoted_tree (pretty_printer
*pp
, tree t
);
121 extern void print_quoted_type (pretty_printer
*pp
, tree t
);
122 extern int readability_comparator (const void *p1
, const void *p2
);
123 extern int tree_cmp (const void *p1
, const void *p2
);
124 extern tree
fixup_tree_for_diagnostic (tree
);
125 extern tree
get_diagnostic_tree_for_gassign (const gassign
*);
127 /* A tree, extended with stack frame information for locals, so that
128 we can distinguish between different values of locals within a potentially
129 recursive callstack. */
134 path_var (tree t
, int stack_depth
)
135 : m_tree (t
), m_stack_depth (stack_depth
)
137 // TODO: ignore stack depth for globals and constants
140 bool operator== (const path_var
&other
) const
142 return (m_tree
== other
.m_tree
143 && m_stack_depth
== other
.m_stack_depth
);
146 operator bool () const
148 return m_tree
!= NULL_TREE
;
151 void dump (pretty_printer
*pp
) const;
154 int m_stack_depth
; // or -1 for globals?
157 typedef offset_int bit_offset_t
;
158 typedef offset_int bit_size_t
;
159 typedef offset_int byte_offset_t
;
160 typedef offset_int byte_size_t
;
162 extern bool int_size_in_bits (const_tree type
, bit_size_t
*out
);
164 extern tree
get_field_at_bit_offset (tree record_type
, bit_offset_t bit_offset
);
166 /* The location of a region expressesd as an offset relative to a
172 static region_offset
make_concrete (const region
*base_region
,
175 return region_offset (base_region
, offset
, false);
177 static region_offset
make_symbolic (const region
*base_region
)
179 return region_offset (base_region
, 0, true);
182 const region
*get_base_region () const { return m_base_region
; }
184 bool symbolic_p () const { return m_is_symbolic
; }
186 bit_offset_t
get_bit_offset () const
188 gcc_assert (!symbolic_p ());
192 bool operator== (const region_offset
&other
) const
194 return (m_base_region
== other
.m_base_region
195 && m_offset
== other
.m_offset
196 && m_is_symbolic
== other
.m_is_symbolic
);
200 region_offset (const region
*base_region
, bit_offset_t offset
,
202 : m_base_region (base_region
), m_offset (offset
), m_is_symbolic (is_symbolic
)
205 const region
*m_base_region
;
206 bit_offset_t m_offset
;
210 extern location_t
get_stmt_location (const gimple
*stmt
, function
*fun
);
212 extern bool compat_types_p (tree src_type
, tree dst_type
);
214 /* Passed by pointer to PLUGIN_ANALYZER_INIT callbacks. */
216 class plugin_analyzer_init_iface
219 virtual void register_state_machine (state_machine
*) = 0;
220 virtual logger
*get_logger () const = 0;
223 /* An enum for describing the direction of an access to memory. */
225 enum access_direction
231 /* Abstract base class for associating custom data with an
232 exploded_edge, for handling non-standard edges such as
233 rewinding from a longjmp, signal handlers, etc.
234 Also used when "bifurcating" state: splitting the execution
235 path in non-standard ways (e.g. for simulating the various
236 outcomes of "realloc"). */
238 class custom_edge_info
241 virtual ~custom_edge_info () {}
243 /* Hook for making .dot label more readable. */
244 virtual void print (pretty_printer
*pp
) const = 0;
246 /* Hook for updating MODEL within exploded_path::feasible_p
247 and when handling bifurcation. */
248 virtual bool update_model (region_model
*model
,
249 const exploded_edge
*eedge
,
250 region_model_context
*ctxt
) const = 0;
252 virtual void add_events_to_path (checker_path
*emission_path
,
253 const exploded_edge
&eedge
) const = 0;
256 /* Abstract base class for splitting state.
258 Most of the state-management code in the analyzer involves
259 modifying state objects in-place, which assumes a single outcome.
261 This class provides an escape hatch to allow for multiple outcomes
262 for such updates e.g. for modelling multiple outcomes from function
263 calls, such as the various outcomes of "realloc". */
268 virtual ~path_context () {}
270 /* Hook for clients to split state with a non-standard path.
271 Take ownership of INFO. */
272 virtual void bifurcate (custom_edge_info
*info
) = 0;
274 /* Hook for clients to terminate the standard path. */
275 virtual void terminate_path () = 0;
277 /* Hook for clients to determine if the standard path has been
279 virtual bool terminate_path_p () const = 0;
284 extern bool is_special_named_call_p (const gcall
*call
, const char *funcname
,
285 unsigned int num_args
);
286 extern bool is_named_call_p (const_tree fndecl
, const char *funcname
);
287 extern bool is_named_call_p (const_tree fndecl
, const char *funcname
,
288 const gcall
*call
, unsigned int num_args
);
289 extern bool is_std_named_call_p (const_tree fndecl
, const char *funcname
);
290 extern bool is_std_named_call_p (const_tree fndecl
, const char *funcname
,
291 const gcall
*call
, unsigned int num_args
);
292 extern bool is_setjmp_call_p (const gcall
*call
);
293 extern bool is_longjmp_call_p (const gcall
*call
);
295 extern const char *get_user_facing_name (const gcall
*call
);
297 extern void register_analyzer_pass ();
299 extern label_text
make_label_text (bool can_colorize
, const char *fmt
, ...);
300 extern label_text
make_label_text_n (bool can_colorize
, int n
,
301 const char *singular_fmt
,
302 const char *plural_fmt
, ...);
304 extern bool fndecl_has_gimple_body_p (tree fndecl
);
306 /* An RAII-style class for pushing/popping cfun within a scope.
307 Doing so ensures we get "In function " announcements
308 from the diagnostics subsystem. */
313 auto_cfun (function
*fun
) { push_cfun (fun
); }
314 ~auto_cfun () { pop_cfun (); }
317 /* A template for creating hash traits for a POD type. */
319 template <typename Type
>
320 struct pod_hash_traits
: typed_noop_remove
<Type
>
322 typedef Type value_type
;
323 typedef Type compare_type
;
324 static inline hashval_t
hash (value_type
);
325 static inline bool equal (const value_type
&existing
,
326 const value_type
&candidate
);
327 static inline void mark_deleted (Type
&);
328 static inline void mark_empty (Type
&);
329 static inline bool is_deleted (Type
);
330 static inline bool is_empty (Type
);
333 /* A hash traits class that uses member functions to implement
334 the various required ops. */
336 template <typename Type
>
337 struct member_function_hash_traits
: public typed_noop_remove
<Type
>
339 typedef Type value_type
;
340 typedef Type compare_type
;
341 static inline hashval_t
hash (value_type v
) { return v
.hash (); }
342 static inline bool equal (const value_type
&existing
,
343 const value_type
&candidate
)
345 return existing
== candidate
;
347 static inline void mark_deleted (Type
&t
) { t
.mark_deleted (); }
348 static inline void mark_empty (Type
&t
) { t
.mark_empty (); }
349 static inline bool is_deleted (Type t
) { return t
.is_deleted (); }
350 static inline bool is_empty (Type t
) { return t
.is_empty (); }
353 /* A map from T::key_t to T* for use in consolidating instances of T.
354 Owns all instances of T.
355 T::key_t should have operator== and be hashable. */
357 template <typename T
>
358 class consolidation_map
361 typedef typename
T::key_t key_t
;
362 typedef T instance_t
;
363 typedef hash_map
<key_t
, instance_t
*> inner_map_t
;
364 typedef typename
inner_map_t::iterator iterator
;
366 /* Delete all instances of T. */
368 ~consolidation_map ()
370 for (typename
inner_map_t::iterator iter
= m_inner_map
.begin ();
371 iter
!= m_inner_map
.end (); ++iter
)
372 delete (*iter
).second
;
375 /* Get the instance of T for K if one exists, or NULL. */
377 T
*get (const key_t
&k
) const
379 if (instance_t
**slot
= const_cast<inner_map_t
&> (m_inner_map
).get (k
))
384 /* Take ownership of INSTANCE. */
386 void put (const key_t
&k
, T
*instance
)
388 m_inner_map
.put (k
, instance
);
391 size_t elements () const { return m_inner_map
.elements (); }
393 iterator
begin () const { return m_inner_map
.begin (); }
394 iterator
end () const { return m_inner_map
.end (); }
397 inner_map_t m_inner_map
;
400 /* Disable -Wformat-diag; we want to be able to use pp_printf
401 for logging/dumping without complying with the rules for diagnostics. */
403 #pragma GCC diagnostic ignored "-Wformat-diag"
407 extern void sorry_no_analyzer ();
408 #endif /* #if !ENABLE_ANALYZER */
410 #endif /* GCC_ANALYZER_ANALYZER_H */