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
32 /* Forward decls of common types, with indentation to show inheritance. */
38 class switch_cfg_superedge;
39 class callgraph_superedge;
41 class return_superedge;
45 class constant_svalue;
47 class poisoned_svalue;
53 class repeated_svalue;
54 class bits_within_svalue;
55 class unmergeable_svalue;
56 class placeholder_svalue;
57 class widening_svalue;
58 class compound_svalue;
59 class conjured_svalue;
60 class asm_output_svalue;
61 class const_fn_result_svalue;
62 typedef hash_set<const svalue *> svalue_set;
65 class function_region;
68 class symbolic_region;
75 class bit_range_region;
77 class region_model_manager;
83 class region_model_context;
84 class impl_region_model_context;
86 class rejected_constraint;
87 class constraint_manager;
89 class reachable_regions;
91 class bounded_ranges_manager;
93 class pending_diagnostic;
95 struct event_loc_info;
96 class state_change_event;
98 class extrinsic_state;
102 class function_point;
104 class exploded_graph;
107 class feasibility_problem;
108 class exploded_cluster;
111 class state_purge_map;
112 class state_purge_per_ssa_name;
113 class state_purge_per_decl;
121 class known_function_manager;
123 class call_summary_replay;
124 struct per_function_data;
125 struct interesting_t;
127 /* Forward decls of functions. */
129 extern void dump_tree (pretty_printer *pp, tree t);
130 extern void dump_quoted_tree (pretty_printer *pp, tree t);
131 extern void print_quoted_type (pretty_printer *pp, tree t);
132 extern int readability_comparator (const void *p1, const void *p2);
133 extern int tree_cmp (const void *p1, const void *p2);
134 extern tree fixup_tree_for_diagnostic (tree);
135 extern tree get_diagnostic_tree_for_gassign (const gassign *);
137 /* A tree, extended with stack frame information for locals, so that
138 we can distinguish between different values of locals within a potentially
139 recursive callstack. */
144 path_var (tree t, int stack_depth)
145 : m_tree (t), m_stack_depth (stack_depth)
147 // TODO: ignore stack depth for globals and constants
150 bool operator== (const path_var &other) const
152 return (m_tree == other.m_tree
153 && m_stack_depth == other.m_stack_depth);
156 operator bool () const
158 return m_tree != NULL_TREE;
161 void dump (pretty_printer *pp) const;
164 int m_stack_depth; // or -1 for globals?
167 typedef offset_int bit_offset_t;
168 typedef offset_int bit_size_t;
169 typedef offset_int byte_offset_t;
170 typedef offset_int byte_size_t;
172 extern bool int_size_in_bits (const_tree type, bit_size_t *out);
174 extern tree get_field_at_bit_offset (tree record_type, bit_offset_t bit_offset);
176 /* The location of a region expressesd as an offset relative to a
182 static region_offset make_concrete (const region *base_region,
185 return region_offset (base_region, offset, NULL);
187 static region_offset make_symbolic (const region *base_region,
188 const svalue *sym_offset)
190 return region_offset (base_region, 0, sym_offset);
193 const region *get_base_region () const { return m_base_region; }
195 bool symbolic_p () const { return m_sym_offset != NULL; }
197 bit_offset_t get_bit_offset () const
199 gcc_assert (!symbolic_p ());
203 const svalue *get_symbolic_byte_offset () const
205 gcc_assert (symbolic_p ());
209 bool operator== (const region_offset &other) const
211 return (m_base_region == other.m_base_region
212 && m_offset == other.m_offset
213 && m_sym_offset == other.m_sym_offset);
217 region_offset (const region *base_region, bit_offset_t offset,
218 const svalue *sym_offset)
219 : m_base_region (base_region), m_offset (offset), m_sym_offset (sym_offset)
222 const region *m_base_region;
223 bit_offset_t m_offset;
224 const svalue *m_sym_offset;
227 extern location_t get_stmt_location (const gimple *stmt, function *fun);
229 extern bool compat_types_p (tree src_type, tree dst_type);
231 /* Abstract base class for simulating the behavior of known functions,
232 supplied by the core of the analyzer, or by plugins. */
237 virtual ~known_function () {}
238 virtual bool matches_call_types_p (const call_details &cd) const = 0;
239 virtual void impl_call_pre (const call_details &) const
243 virtual void impl_call_post (const call_details &) const
249 /* Subclass of known_function for IFN_* functions. */
251 class internal_known_function : public known_function
254 bool matches_call_types_p (const call_details &) const final override
256 /* Types are assumed to be correct. */
261 extern void register_known_functions (known_function_manager &mgr);
262 extern void register_known_fd_functions (known_function_manager &kfm);
263 extern void register_known_file_functions (known_function_manager &kfm);
264 extern void register_varargs_builtins (known_function_manager &kfm);
266 /* Passed by pointer to PLUGIN_ANALYZER_INIT callbacks. */
268 class plugin_analyzer_init_iface
271 virtual void register_state_machine (std::unique_ptr<state_machine>) = 0;
272 virtual void register_known_function (const char *name,
273 std::unique_ptr<known_function>) = 0;
274 virtual logger *get_logger () const = 0;
277 /* An enum for describing the direction of an access to memory. */
279 enum access_direction
285 /* Abstract base class for associating custom data with an
286 exploded_edge, for handling non-standard edges such as
287 rewinding from a longjmp, signal handlers, etc.
288 Also used when "bifurcating" state: splitting the execution
289 path in non-standard ways (e.g. for simulating the various
290 outcomes of "realloc"). */
292 class custom_edge_info
295 virtual ~custom_edge_info () {}
297 /* Hook for making .dot label more readable. */
298 virtual void print (pretty_printer *pp) const = 0;
300 /* Hook for updating STATE when handling bifurcation. */
301 virtual bool update_state (program_state *state,
302 const exploded_edge *eedge,
303 region_model_context *ctxt) const;
305 /* Hook for updating MODEL within exploded_path::feasible_p
306 and when handling bifurcation. */
307 virtual bool update_model (region_model *model,
308 const exploded_edge *eedge,
309 region_model_context *ctxt) const = 0;
311 virtual void add_events_to_path (checker_path *emission_path,
312 const exploded_edge &eedge) const = 0;
315 /* Abstract base class for splitting state.
317 Most of the state-management code in the analyzer involves
318 modifying state objects in-place, which assumes a single outcome.
320 This class provides an escape hatch to allow for multiple outcomes
321 for such updates e.g. for modelling multiple outcomes from function
322 calls, such as the various outcomes of "realloc". */
327 virtual ~path_context () {}
329 /* Hook for clients to split state with a non-standard path. */
330 virtual void bifurcate (std::unique_ptr<custom_edge_info> info) = 0;
332 /* Hook for clients to terminate the standard path. */
333 virtual void terminate_path () = 0;
335 /* Hook for clients to determine if the standard path has been
337 virtual bool terminate_path_p () const = 0;
340 extern tree get_stashed_constant_by_name (const char *name);
341 extern void log_stashed_constants (logger *logger);
343 extern FILE *get_or_create_any_logfile ();
347 extern bool is_special_named_call_p (const gcall *call, const char *funcname,
348 unsigned int num_args);
349 extern bool is_named_call_p (const_tree fndecl, const char *funcname);
350 extern bool is_named_call_p (const_tree fndecl, const char *funcname,
351 const gcall *call, unsigned int num_args);
352 extern bool is_std_named_call_p (const_tree fndecl, const char *funcname);
353 extern bool is_std_named_call_p (const_tree fndecl, const char *funcname,
354 const gcall *call, unsigned int num_args);
355 extern bool is_setjmp_call_p (const gcall *call);
356 extern bool is_longjmp_call_p (const gcall *call);
358 extern const char *get_user_facing_name (const gcall *call);
360 extern void register_analyzer_pass ();
362 extern label_text make_label_text (bool can_colorize, const char *fmt, ...);
363 extern label_text make_label_text_n (bool can_colorize,
364 unsigned HOST_WIDE_INT n,
365 const char *singular_fmt,
366 const char *plural_fmt, ...);
368 extern bool fndecl_has_gimple_body_p (tree fndecl);
370 /* An RAII-style class for pushing/popping cfun within a scope.
371 Doing so ensures we get "In function " announcements
372 from the diagnostics subsystem. */
377 auto_cfun (function *fun) { push_cfun (fun); }
378 ~auto_cfun () { pop_cfun (); }
381 /* A template for creating hash traits for a POD type. */
383 template <typename Type>
384 struct pod_hash_traits : typed_noop_remove<Type>
386 typedef Type value_type;
387 typedef Type compare_type;
388 static inline hashval_t hash (value_type);
389 static inline bool equal (const value_type &existing,
390 const value_type &candidate);
391 static inline void mark_deleted (Type &);
392 static inline void mark_empty (Type &);
393 static inline bool is_deleted (Type);
394 static inline bool is_empty (Type);
397 /* A hash traits class that uses member functions to implement
398 the various required ops. */
400 template <typename Type>
401 struct member_function_hash_traits : public typed_noop_remove<Type>
403 typedef Type value_type;
404 typedef Type compare_type;
405 static inline hashval_t hash (value_type v) { return v.hash (); }
406 static inline bool equal (const value_type &existing,
407 const value_type &candidate)
409 return existing == candidate;
411 static inline void mark_deleted (Type &t) { t.mark_deleted (); }
412 static inline void mark_empty (Type &t) { t.mark_empty (); }
413 static inline bool is_deleted (Type t) { return t.is_deleted (); }
414 static inline bool is_empty (Type t) { return t.is_empty (); }
417 /* A map from T::key_t to T* for use in consolidating instances of T.
418 Owns all instances of T.
419 T::key_t should have operator== and be hashable. */
421 template <typename T>
422 class consolidation_map
425 typedef typename T::key_t key_t;
426 typedef T instance_t;
427 typedef hash_map<key_t, instance_t *> inner_map_t;
428 typedef typename inner_map_t::iterator iterator;
430 /* Delete all instances of T. */
432 ~consolidation_map ()
434 for (typename inner_map_t::iterator iter = m_inner_map.begin ();
435 iter != m_inner_map.end (); ++iter)
436 delete (*iter).second;
439 /* Get the instance of T for K if one exists, or NULL. */
441 T *get (const key_t &k) const
443 if (instance_t **slot = const_cast<inner_map_t &> (m_inner_map).get (k))
448 /* Take ownership of INSTANCE. */
450 void put (const key_t &k, T *instance)
452 m_inner_map.put (k, instance);
455 size_t elements () const { return m_inner_map.elements (); }
457 iterator begin () const { return m_inner_map.begin (); }
458 iterator end () const { return m_inner_map.end (); }
461 inner_map_t m_inner_map;
464 /* Disable -Wformat-diag; we want to be able to use pp_printf
465 for logging/dumping without complying with the rules for diagnostics. */
467 #pragma GCC diagnostic ignored "-Wformat-diag"
471 extern void sorry_no_analyzer ();
472 #endif /* #if !ENABLE_ANALYZER */
474 #endif /* GCC_ANALYZER_ANALYZER_H */