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