]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/analyzer/analyzer.h
Update copyright years.
[thirdparty/gcc.git] / gcc / analyzer / analyzer.h
CommitLineData
757bf1df 1/* Utility functions for the analyzer.
a945c346 2 Copyright (C) 2019-2024 Free Software Foundation, Inc.
757bf1df
DM
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along 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
78d132d7 24#include "rich-location.h"
bfca9505 25#include "function.h"
2eff4fe3
DM
26#include "json.h"
27#include "tristate.h"
bfca9505 28
757bf1df 29class graphviz_out;
75038aa6
DM
30
31namespace ana {
32
41f99ba6
DM
33/* Forward decls of common types, with indentation to show inheritance. */
34
757bf1df
DM
35class supergraph;
36class supernode;
37class superedge;
38 class cfg_superedge;
39 class switch_cfg_superedge;
40 class callgraph_superedge;
41 class call_superedge;
42 class return_superedge;
808f4dfe 43
757bf1df
DM
44class svalue;
45 class region_svalue;
46 class constant_svalue;
757bf1df 47 class unknown_svalue;
808f4dfe 48 class poisoned_svalue;
757bf1df 49 class setjmp_svalue;
808f4dfe
DM
50 class initial_svalue;
51 class unaryop_svalue;
52 class binop_svalue;
53 class sub_svalue;
e61ffa20
DM
54 class repeated_svalue;
55 class bits_within_svalue;
808f4dfe
DM
56 class unmergeable_svalue;
57 class placeholder_svalue;
58 class widening_svalue;
59 class compound_svalue;
60 class conjured_svalue;
ded2c2c0 61 class asm_output_svalue;
aee1adf2 62 class const_fn_result_svalue;
808f4dfe 63typedef hash_set<const svalue *> svalue_set;
757bf1df 64class region;
808f4dfe
DM
65 class frame_region;
66 class function_region;
67 class label_region;
68 class decl_region;
757bf1df 69 class symbolic_region;
808f4dfe
DM
70 class element_region;
71 class offset_region;
e61ffa20 72 class sized_region;
808f4dfe
DM
73 class cast_region;
74 class field_region;
75 class string_region;
93e759fc 76 class bit_range_region;
2402dc6b 77 class var_arg_region;
808f4dfe 78class region_model_manager;
3734527d 79class conjured_purge;
808f4dfe
DM
80struct model_merger;
81class store_manager;
82class store;
757bf1df
DM
83class region_model;
84class region_model_context;
85 class impl_region_model_context;
808f4dfe 86class call_details;
8ca7fa84 87class rejected_constraint;
757bf1df
DM
88class constraint_manager;
89class equiv_class;
ded2c2c0 90class reachable_regions;
8ca7fa84
DM
91class bounded_ranges;
92class bounded_ranges_manager;
808f4dfe 93
759a1a52 94struct pending_location;
757bf1df 95class pending_diagnostic;
c65d3c7f 96class pending_note;
12b67d1e 97class saved_diagnostic;
e24fe128 98struct event_loc_info;
0d6f7b1d
DM
99class checker_event;
100 class state_change_event;
101 class warning_event;
757bf1df
DM
102class checker_path;
103class extrinsic_state;
104class sm_state_map;
105class stmt_finder;
106class program_point;
808f4dfe 107class function_point;
757bf1df
DM
108class program_state;
109class exploded_graph;
110class exploded_node;
111class exploded_edge;
42c63313 112class feasibility_problem;
757bf1df
DM
113class exploded_cluster;
114class exploded_path;
115class analysis_plan;
116class state_purge_map;
117class state_purge_per_ssa_name;
faacafd2 118class state_purge_per_decl;
757bf1df
DM
119class state_change;
120class rewind_info_t;
121
808f4dfe 122class engine;
e9751143
DM
123class state_machine;
124class logger;
125class visitor;
07e30160 126class known_function_manager;
bfca9505
DM
127class call_summary;
128class call_summary_replay;
129struct per_function_data;
130struct interesting_t;
808f4dfe 131
7bffea89
DM
132class feasible_node;
133
55f6a7d9 134class known_function;
135 class builtin_known_function;
136 class internal_known_function;
137
41f99ba6
DM
138/* Forward decls of functions. */
139
808f4dfe 140extern void dump_tree (pretty_printer *pp, tree t);
41f99ba6 141extern void dump_quoted_tree (pretty_printer *pp, tree t);
808f4dfe
DM
142extern void print_quoted_type (pretty_printer *pp, tree t);
143extern int readability_comparator (const void *p1, const void *p2);
144extern int tree_cmp (const void *p1, const void *p2);
e4bb1bd6 145extern tree fixup_tree_for_diagnostic (tree);
33255ad3 146extern tree get_diagnostic_tree_for_gassign (const gassign *);
808f4dfe
DM
147
148/* A tree, extended with stack frame information for locals, so that
149 we can distinguish between different values of locals within a potentially
150 recursive callstack. */
151
152class path_var
153{
154public:
155 path_var (tree t, int stack_depth)
156 : m_tree (t), m_stack_depth (stack_depth)
157 {
158 // TODO: ignore stack depth for globals and constants
159 }
160
161 bool operator== (const path_var &other) const
162 {
163 return (m_tree == other.m_tree
164 && m_stack_depth == other.m_stack_depth);
165 }
166
167 operator bool () const
168 {
169 return m_tree != NULL_TREE;
170 }
171
172 void dump (pretty_printer *pp) const;
173
174 tree m_tree;
175 int m_stack_depth; // or -1 for globals?
176};
177
178typedef offset_int bit_offset_t;
179typedef offset_int bit_size_t;
7c6b354b 180typedef offset_int byte_offset_t;
808f4dfe
DM
181typedef offset_int byte_size_t;
182
c957d380
DM
183extern bool int_size_in_bits (const_tree type, bit_size_t *out);
184
e61ffa20
DM
185extern tree get_field_at_bit_offset (tree record_type, bit_offset_t bit_offset);
186
808f4dfe
DM
187/* The location of a region expressesd as an offset relative to a
188 base region. */
189
190class region_offset
191{
192public:
0e466e97
DM
193 region_offset ()
194 : m_base_region (NULL), m_offset (0), m_sym_offset (NULL)
195 {
196 }
197
808f4dfe
DM
198 static region_offset make_concrete (const region *base_region,
199 bit_offset_t offset)
200 {
7a6564c9 201 return region_offset (base_region, offset, NULL);
808f4dfe 202 }
7a6564c9
TL
203 static region_offset make_symbolic (const region *base_region,
204 const svalue *sym_offset)
808f4dfe 205 {
7a6564c9 206 return region_offset (base_region, 0, sym_offset);
808f4dfe 207 }
0e466e97
DM
208 static region_offset make_byte_offset (const region *base_region,
209 const svalue *num_bytes_sval);
808f4dfe
DM
210
211 const region *get_base_region () const { return m_base_region; }
212
0e466e97 213 bool concrete_p () const { return m_sym_offset == NULL; }
7a6564c9 214 bool symbolic_p () const { return m_sym_offset != NULL; }
808f4dfe
DM
215
216 bit_offset_t get_bit_offset () const
217 {
218 gcc_assert (!symbolic_p ());
219 return m_offset;
220 }
221
0e466e97
DM
222 bool get_concrete_byte_offset (byte_offset_t *out) const
223 {
224 gcc_assert (!symbolic_p ());
225 if (m_offset % BITS_PER_UNIT == 0)
226 {
227 *out = m_offset / BITS_PER_UNIT;
228 return true;
229 }
230 return false;
231 }
232
7a6564c9
TL
233 const svalue *get_symbolic_byte_offset () const
234 {
235 gcc_assert (symbolic_p ());
236 return m_sym_offset;
237 }
238
0e466e97
DM
239 tree calc_symbolic_bit_offset (const region_model &model) const;
240 const svalue *calc_symbolic_byte_offset (region_model_manager *mgr) const;
241
8a18261a 242 bool operator== (const region_offset &other) const
808f4dfe
DM
243 {
244 return (m_base_region == other.m_base_region
245 && m_offset == other.m_offset
7a6564c9 246 && m_sym_offset == other.m_sym_offset);
808f4dfe
DM
247 }
248
0e466e97
DM
249 void dump_to_pp (pretty_printer *pp, bool) const;
250 void dump (bool) const;
251
808f4dfe
DM
252private:
253 region_offset (const region *base_region, bit_offset_t offset,
7a6564c9
TL
254 const svalue *sym_offset)
255 : m_base_region (base_region), m_offset (offset), m_sym_offset (sym_offset)
808f4dfe
DM
256 {}
257
258 const region *m_base_region;
259 bit_offset_t m_offset;
7a6564c9 260 const svalue *m_sym_offset;
808f4dfe
DM
261};
262
0e466e97
DM
263extern bool operator< (const region_offset &, const region_offset &);
264extern bool operator<= (const region_offset &, const region_offset &);
265extern bool operator> (const region_offset &, const region_offset &);
266extern bool operator>= (const region_offset &, const region_offset &);
267
808f4dfe 268extern location_t get_stmt_location (const gimple *stmt, function *fun);
41f99ba6 269
e66b9f67
DM
270extern bool compat_types_p (tree src_type, tree dst_type);
271
07e30160 272/* Abstract base class for simulating the behavior of known functions,
63a42ffc
DM
273 supplied by the core of the analyzer, or by plugins.
274 The former are typically implemented in the various kf*.cc */
07e30160
DM
275
276class known_function
277{
278public:
279 virtual ~known_function () {}
21501ec7
DM
280 virtual bool matches_call_types_p (const call_details &cd) const = 0;
281 virtual void impl_call_pre (const call_details &) const
282 {
283 return;
284 }
285 virtual void impl_call_post (const call_details &) const
286 {
287 return;
288 }
55f6a7d9 289
290 virtual const builtin_known_function *
291 dyn_cast_builtin_kf () const { return NULL; }
292};
293
294/* Subclass of known_function for builtin functions. */
295
296class builtin_known_function : public known_function
297{
298public:
299 virtual enum built_in_function builtin_code () const = 0;
300 tree builtin_decl () const {
301 gcc_assert (builtin_code () < END_BUILTINS);
302 return builtin_info[builtin_code ()].decl;
303 }
304
305 const builtin_known_function *
306 dyn_cast_builtin_kf () const final override { return this; }
07e30160
DM
307};
308
6bd31b33
DM
309/* Subclass of known_function for IFN_* functions. */
310
311class internal_known_function : public known_function
312{
313public:
314 bool matches_call_types_p (const call_details &) const final override
315 {
316 /* Types are assumed to be correct. */
317 return true;
318 }
319};
320
73da34a5
DM
321/* Abstract subclass of known_function that merely sets the return
322 value of the function (based on function attributes), and assumes
323 it has no side-effects. */
324
325class pure_known_function_with_default_return : public known_function
326{
327public:
328 void impl_call_pre (const call_details &cd) const override;
329};
330
f65f63c4
DM
331extern void register_known_functions (known_function_manager &kfm,
332 region_model_manager &rmm);
861c917a 333extern void register_known_analyzer_functions (known_function_manager &kfm);
50d5b240 334extern void register_known_fd_functions (known_function_manager &kfm);
78a17f44 335extern void register_known_file_functions (known_function_manager &kfm);
861c917a 336extern void register_known_functions_lang_cp (known_function_manager &kfm);
6bd31b33 337extern void register_varargs_builtins (known_function_manager &kfm);
21501ec7 338
66dde7bc
DM
339/* Passed by pointer to PLUGIN_ANALYZER_INIT callbacks. */
340
341class plugin_analyzer_init_iface
342{
343public:
e177be86 344 virtual void register_state_machine (std::unique_ptr<state_machine>) = 0;
07e30160 345 virtual void register_known_function (const char *name,
76dd2c4f 346 std::unique_ptr<known_function>) = 0;
66dde7bc
DM
347 virtual logger *get_logger () const = 0;
348};
349
9faf8348
DM
350/* An enum for describing the direction of an access to memory. */
351
352enum access_direction
353{
354 DIR_READ,
355 DIR_WRITE
356};
357
eafa9d96
DM
358/* Abstract base class for associating custom data with an
359 exploded_edge, for handling non-standard edges such as
360 rewinding from a longjmp, signal handlers, etc.
361 Also used when "bifurcating" state: splitting the execution
362 path in non-standard ways (e.g. for simulating the various
363 outcomes of "realloc"). */
364
365class custom_edge_info
366{
367public:
368 virtual ~custom_edge_info () {}
369
370 /* Hook for making .dot label more readable. */
371 virtual void print (pretty_printer *pp) const = 0;
372
bfca9505
DM
373 /* Hook for updating STATE when handling bifurcation. */
374 virtual bool update_state (program_state *state,
375 const exploded_edge *eedge,
376 region_model_context *ctxt) const;
377
eafa9d96
DM
378 /* Hook for updating MODEL within exploded_path::feasible_p
379 and when handling bifurcation. */
380 virtual bool update_model (region_model *model,
381 const exploded_edge *eedge,
382 region_model_context *ctxt) const = 0;
383
384 virtual void add_events_to_path (checker_path *emission_path,
385 const exploded_edge &eedge) const = 0;
386};
387
388/* Abstract base class for splitting state.
389
390 Most of the state-management code in the analyzer involves
391 modifying state objects in-place, which assumes a single outcome.
392
393 This class provides an escape hatch to allow for multiple outcomes
394 for such updates e.g. for modelling multiple outcomes from function
395 calls, such as the various outcomes of "realloc". */
396
397class path_context
398{
399public:
400 virtual ~path_context () {}
401
accece8c
DM
402 /* Hook for clients to split state with a non-standard path. */
403 virtual void bifurcate (std::unique_ptr<custom_edge_info> info) = 0;
eafa9d96
DM
404
405 /* Hook for clients to terminate the standard path. */
406 virtual void terminate_path () = 0;
407
408 /* Hook for clients to determine if the standard path has been
409 terminated. */
410 virtual bool terminate_path_p () const = 0;
411};
412
d8aba860
DM
413extern tree get_stashed_constant_by_name (const char *name);
414extern void log_stashed_constants (logger *logger);
415
6e496281
DM
416extern FILE *get_or_create_any_logfile ();
417
7abc7aae
DM
418extern json::value *
419tree_to_json (tree node);
420
421extern json::value *
422diagnostic_event_id_to_json (const diagnostic_event_id_t &);
423
424extern json::value *
425bit_offset_to_json (const bit_offset_t &offset);
426
427extern json::value *
428byte_offset_to_json (const byte_offset_t &offset);
429
75038aa6
DM
430} // namespace ana
431
757bf1df
DM
432extern bool is_special_named_call_p (const gcall *call, const char *funcname,
433 unsigned int num_args);
31534ac2
SP
434extern bool is_named_call_p (const_tree fndecl, const char *funcname);
435extern bool is_named_call_p (const_tree fndecl, const char *funcname,
757bf1df 436 const gcall *call, unsigned int num_args);
31534ac2
SP
437extern bool is_std_named_call_p (const_tree fndecl, const char *funcname);
438extern bool is_std_named_call_p (const_tree fndecl, const char *funcname,
9f00b22f 439 const gcall *call, unsigned int num_args);
342e14ff 440extern bool is_setjmp_call_p (const gcall *call);
757bf1df 441extern bool is_longjmp_call_p (const gcall *call);
e7b26744 442extern bool is_placement_new_p (const gcall *call);
757bf1df 443
342e14ff
DM
444extern const char *get_user_facing_name (const gcall *call);
445
757bf1df
DM
446extern void register_analyzer_pass ();
447
448extern label_text make_label_text (bool can_colorize, const char *fmt, ...);
f5758fe5
DM
449extern label_text make_label_text_n (bool can_colorize,
450 unsigned HOST_WIDE_INT n,
2402dc6b
DM
451 const char *singular_fmt,
452 const char *plural_fmt, ...);
757bf1df 453
ef7827b0
DM
454extern bool fndecl_has_gimple_body_p (tree fndecl);
455
757bf1df
DM
456/* An RAII-style class for pushing/popping cfun within a scope.
457 Doing so ensures we get "In function " announcements
458 from the diagnostics subsystem. */
459
460class auto_cfun
461{
462public:
463 auto_cfun (function *fun) { push_cfun (fun); }
464 ~auto_cfun () { pop_cfun (); }
465};
466
757bf1df
DM
467/* A template for creating hash traits for a POD type. */
468
469template <typename Type>
470struct pod_hash_traits : typed_noop_remove<Type>
471{
472 typedef Type value_type;
473 typedef Type compare_type;
474 static inline hashval_t hash (value_type);
475 static inline bool equal (const value_type &existing,
476 const value_type &candidate);
477 static inline void mark_deleted (Type &);
478 static inline void mark_empty (Type &);
479 static inline bool is_deleted (Type);
480 static inline bool is_empty (Type);
481};
482
808f4dfe
DM
483/* A hash traits class that uses member functions to implement
484 the various required ops. */
485
486template <typename Type>
487struct member_function_hash_traits : public typed_noop_remove<Type>
488{
489 typedef Type value_type;
490 typedef Type compare_type;
491 static inline hashval_t hash (value_type v) { return v.hash (); }
492 static inline bool equal (const value_type &existing,
493 const value_type &candidate)
494 {
495 return existing == candidate;
496 }
497 static inline void mark_deleted (Type &t) { t.mark_deleted (); }
498 static inline void mark_empty (Type &t) { t.mark_empty (); }
499 static inline bool is_deleted (Type t) { return t.is_deleted (); }
500 static inline bool is_empty (Type t) { return t.is_empty (); }
501};
502
503/* A map from T::key_t to T* for use in consolidating instances of T.
504 Owns all instances of T.
505 T::key_t should have operator== and be hashable. */
506
507template <typename T>
508class consolidation_map
509{
510public:
511 typedef typename T::key_t key_t;
512 typedef T instance_t;
513 typedef hash_map<key_t, instance_t *> inner_map_t;
514 typedef typename inner_map_t::iterator iterator;
515
516 /* Delete all instances of T. */
517
518 ~consolidation_map ()
519 {
520 for (typename inner_map_t::iterator iter = m_inner_map.begin ();
521 iter != m_inner_map.end (); ++iter)
522 delete (*iter).second;
523 }
524
525 /* Get the instance of T for K if one exists, or NULL. */
526
527 T *get (const key_t &k) const
528 {
529 if (instance_t **slot = const_cast<inner_map_t &> (m_inner_map).get (k))
530 return *slot;
531 return NULL;
532 }
533
534 /* Take ownership of INSTANCE. */
535
536 void put (const key_t &k, T *instance)
537 {
538 m_inner_map.put (k, instance);
539 }
540
541 size_t elements () const { return m_inner_map.elements (); }
542
543 iterator begin () const { return m_inner_map.begin (); }
544 iterator end () const { return m_inner_map.end (); }
545
546private:
547 inner_map_t m_inner_map;
548};
549
550/* Disable -Wformat-diag; we want to be able to use pp_printf
551 for logging/dumping without complying with the rules for diagnostics. */
5253b3e6 552#if __GNUC__ >= 10
808f4dfe 553#pragma GCC diagnostic ignored "-Wformat-diag"
5253b3e6 554#endif
808f4dfe 555
66dde7bc
DM
556#if !ENABLE_ANALYZER
557extern void sorry_no_analyzer ();
558#endif /* #if !ENABLE_ANALYZER */
559
757bf1df 560#endif /* GCC_ANALYZER_ANALYZER_H */