1e01aa904Sopenharmony_ci// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 2e01aa904Sopenharmony_ci// -*- mode: C++ -*- 3e01aa904Sopenharmony_ci// 4e01aa904Sopenharmony_ci// Copyright (C) 2013-2022 Red Hat, Inc. 5e01aa904Sopenharmony_ci 6e01aa904Sopenharmony_ci/// @file 7e01aa904Sopenharmony_ci 8e01aa904Sopenharmony_ci#include <functional> 9e01aa904Sopenharmony_ci#include "abg-internal.h" 10e01aa904Sopenharmony_ci// <headers defining libabigail's API go under here> 11e01aa904Sopenharmony_ciABG_BEGIN_EXPORT_DECLARATIONS 12e01aa904Sopenharmony_ci 13e01aa904Sopenharmony_ci#include "abg-hash.h" 14e01aa904Sopenharmony_ci#include "abg-ir.h" 15e01aa904Sopenharmony_ci 16e01aa904Sopenharmony_ciABG_END_EXPORT_DECLARATIONS 17e01aa904Sopenharmony_ci// </headers defining libabigail's API> 18e01aa904Sopenharmony_ci 19e01aa904Sopenharmony_cinamespace abigail 20e01aa904Sopenharmony_ci{ 21e01aa904Sopenharmony_ci 22e01aa904Sopenharmony_cinamespace hashing 23e01aa904Sopenharmony_ci{ 24e01aa904Sopenharmony_ci 25e01aa904Sopenharmony_ci// Mix 3 32 bits values reversibly. Borrowed from hashtab.c in gcc tree. 26e01aa904Sopenharmony_ci#define abigail_hash_mix(a, b, c) \ 27e01aa904Sopenharmony_ci{ \ 28e01aa904Sopenharmony_ci a -= b; a -= c; a ^= (c>>13); \ 29e01aa904Sopenharmony_ci b -= c; b -= a; b ^= (a<< 8); \ 30e01aa904Sopenharmony_ci c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \ 31e01aa904Sopenharmony_ci a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \ 32e01aa904Sopenharmony_ci b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \ 33e01aa904Sopenharmony_ci c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \ 34e01aa904Sopenharmony_ci a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \ 35e01aa904Sopenharmony_ci b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \ 36e01aa904Sopenharmony_ci c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \ 37e01aa904Sopenharmony_ci} 38e01aa904Sopenharmony_ci 39e01aa904Sopenharmony_cisize_t 40e01aa904Sopenharmony_cicombine_hashes(size_t val1, size_t val2) 41e01aa904Sopenharmony_ci{ 42e01aa904Sopenharmony_ci /* the golden ratio; an arbitrary value. */ 43e01aa904Sopenharmony_ci size_t a = 0x9e3779b9; 44e01aa904Sopenharmony_ci abigail_hash_mix(a, val1, val2); 45e01aa904Sopenharmony_ci return val2; 46e01aa904Sopenharmony_ci} 47e01aa904Sopenharmony_ci 48e01aa904Sopenharmony_ci/// Compute a stable string hash. 49e01aa904Sopenharmony_ci/// 50e01aa904Sopenharmony_ci/// std::hash has no portability or stability guarantees so is 51e01aa904Sopenharmony_ci/// unsuitable where reproducibility is a requirement such as in XML 52e01aa904Sopenharmony_ci/// output. 53e01aa904Sopenharmony_ci/// 54e01aa904Sopenharmony_ci/// This is the 32-bit FNV-1a algorithm. The algorithm, reference code 55e01aa904Sopenharmony_ci/// and constants are all unencumbered. It is fast and has reasonable 56e01aa904Sopenharmony_ci/// distribution properties. 57e01aa904Sopenharmony_ci/// 58e01aa904Sopenharmony_ci/// https://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function 59e01aa904Sopenharmony_ci/// 60e01aa904Sopenharmony_ci/// @param str the string to hash. 61e01aa904Sopenharmony_ci/// 62e01aa904Sopenharmony_ci/// @return an unsigned 32 bit hash value. 63e01aa904Sopenharmony_ciuint32_t 64e01aa904Sopenharmony_cifnv_hash(const std::string& str) 65e01aa904Sopenharmony_ci{ 66e01aa904Sopenharmony_ci const uint32_t prime = 0x01000193; 67e01aa904Sopenharmony_ci const uint32_t offset_basis = 0x811c9dc5; 68e01aa904Sopenharmony_ci uint32_t hash = offset_basis; 69e01aa904Sopenharmony_ci for (std::string::const_iterator i = str.begin(); i != str.end(); ++i) 70e01aa904Sopenharmony_ci { 71e01aa904Sopenharmony_ci uint8_t byte = *i; 72e01aa904Sopenharmony_ci hash = hash ^ byte; 73e01aa904Sopenharmony_ci hash = hash * prime; 74e01aa904Sopenharmony_ci } 75e01aa904Sopenharmony_ci return hash; 76e01aa904Sopenharmony_ci} 77e01aa904Sopenharmony_ci 78e01aa904Sopenharmony_ci}//end namespace hashing 79e01aa904Sopenharmony_ci 80e01aa904Sopenharmony_ciusing std::list; 81e01aa904Sopenharmony_ciusing std::vector; 82e01aa904Sopenharmony_ci 83e01aa904Sopenharmony_ciusing namespace abigail::ir; 84e01aa904Sopenharmony_ci 85e01aa904Sopenharmony_ci// See forward declarations in abg-ir.h. 86e01aa904Sopenharmony_ci 87e01aa904Sopenharmony_ci// Definitions. 88e01aa904Sopenharmony_ci 89e01aa904Sopenharmony_ci/// Hash function for an instance of @ref type_base. 90e01aa904Sopenharmony_ci/// 91e01aa904Sopenharmony_ci/// @param t the type to hash. 92e01aa904Sopenharmony_ci/// 93e01aa904Sopenharmony_ci/// @return the type value. 94e01aa904Sopenharmony_cisize_t 95e01aa904Sopenharmony_citype_base::hash::operator()(const type_base& t) const 96e01aa904Sopenharmony_ci{ 97e01aa904Sopenharmony_ci std::hash<size_t> size_t_hash; 98e01aa904Sopenharmony_ci std::hash<string> str_hash; 99e01aa904Sopenharmony_ci 100e01aa904Sopenharmony_ci size_t v = str_hash(typeid(t).name()); 101e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, size_t_hash(t.get_size_in_bits())); 102e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, size_t_hash(t.get_alignment_in_bits())); 103e01aa904Sopenharmony_ci 104e01aa904Sopenharmony_ci return v; 105e01aa904Sopenharmony_ci} 106e01aa904Sopenharmony_ci 107e01aa904Sopenharmony_ci/// Hash function for an instance of @ref type_base. 108e01aa904Sopenharmony_ci/// 109e01aa904Sopenharmony_ci/// @param t the type to hash. 110e01aa904Sopenharmony_ci/// 111e01aa904Sopenharmony_ci/// @return the type value. 112e01aa904Sopenharmony_cisize_t 113e01aa904Sopenharmony_citype_base::hash::operator()(const type_base* t) const 114e01aa904Sopenharmony_ci{return operator()(*t);} 115e01aa904Sopenharmony_ci 116e01aa904Sopenharmony_ci/// Hash function for an instance of @ref type_base. 117e01aa904Sopenharmony_ci/// 118e01aa904Sopenharmony_ci/// @param t the type to hash. 119e01aa904Sopenharmony_ci/// 120e01aa904Sopenharmony_ci/// @return the type value. 121e01aa904Sopenharmony_cisize_t 122e01aa904Sopenharmony_citype_base::hash::operator()(const type_base_sptr t) const 123e01aa904Sopenharmony_ci{return operator()(*t);} 124e01aa904Sopenharmony_ci 125e01aa904Sopenharmony_cistruct decl_base::hash 126e01aa904Sopenharmony_ci{ 127e01aa904Sopenharmony_ci size_t 128e01aa904Sopenharmony_ci operator()(const decl_base& d) const 129e01aa904Sopenharmony_ci { 130e01aa904Sopenharmony_ci std::hash<string> str_hash; 131e01aa904Sopenharmony_ci 132e01aa904Sopenharmony_ci size_t v = str_hash(typeid(d).name()); 133e01aa904Sopenharmony_ci if (!d.get_linkage_name().empty()) 134e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, str_hash(d.get_linkage_name())); 135e01aa904Sopenharmony_ci if (!d.get_name().empty()) 136e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, str_hash(d.get_qualified_name())); 137e01aa904Sopenharmony_ci if (is_member_decl(d)) 138e01aa904Sopenharmony_ci { 139e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, get_member_access_specifier(d)); 140e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, get_member_is_static(d)); 141e01aa904Sopenharmony_ci } 142e01aa904Sopenharmony_ci return v; 143e01aa904Sopenharmony_ci } 144e01aa904Sopenharmony_ci}; // end struct decl_base::hash 145e01aa904Sopenharmony_ci 146e01aa904Sopenharmony_cistruct type_decl::hash 147e01aa904Sopenharmony_ci{ 148e01aa904Sopenharmony_ci size_t 149e01aa904Sopenharmony_ci operator()(const type_decl& t) const 150e01aa904Sopenharmony_ci { 151e01aa904Sopenharmony_ci decl_base::hash decl_hash; 152e01aa904Sopenharmony_ci type_base::hash type_hash; 153e01aa904Sopenharmony_ci std::hash<string> str_hash; 154e01aa904Sopenharmony_ci 155e01aa904Sopenharmony_ci size_t v = str_hash(typeid(t).name()); 156e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, decl_hash(t)); 157e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, type_hash(t)); 158e01aa904Sopenharmony_ci 159e01aa904Sopenharmony_ci return v; 160e01aa904Sopenharmony_ci } 161e01aa904Sopenharmony_ci}; 162e01aa904Sopenharmony_ci 163e01aa904Sopenharmony_ci/// Hashing operator for the @ref scope_decl type. 164e01aa904Sopenharmony_ci/// 165e01aa904Sopenharmony_ci/// @param d the scope_decl to hash. 166e01aa904Sopenharmony_ci/// 167e01aa904Sopenharmony_ci/// @return the hash value. 168e01aa904Sopenharmony_cisize_t 169e01aa904Sopenharmony_ciscope_decl::hash::operator()(const scope_decl& d) const 170e01aa904Sopenharmony_ci{ 171e01aa904Sopenharmony_ci std::hash<string> hash_string; 172e01aa904Sopenharmony_ci size_t v = hash_string(typeid(d).name()); 173e01aa904Sopenharmony_ci for (scope_decl::declarations::const_iterator i = 174e01aa904Sopenharmony_ci d.get_member_decls().begin(); 175e01aa904Sopenharmony_ci i != d.get_member_decls().end(); 176e01aa904Sopenharmony_ci ++i) 177e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, (*i)->get_hash()); 178e01aa904Sopenharmony_ci 179e01aa904Sopenharmony_ci return v; 180e01aa904Sopenharmony_ci} 181e01aa904Sopenharmony_ci 182e01aa904Sopenharmony_ci/// Hashing operator for the @ref scope_decl type. 183e01aa904Sopenharmony_ci/// 184e01aa904Sopenharmony_ci/// @param d the scope_decl to hash. 185e01aa904Sopenharmony_ci/// 186e01aa904Sopenharmony_ci/// @return the hash value. 187e01aa904Sopenharmony_cisize_t 188e01aa904Sopenharmony_ciscope_decl::hash::operator()(const scope_decl* d) const 189e01aa904Sopenharmony_ci{return d? operator()(*d) : 0;} 190e01aa904Sopenharmony_ci 191e01aa904Sopenharmony_cistruct scope_type_decl::hash 192e01aa904Sopenharmony_ci{ 193e01aa904Sopenharmony_ci size_t 194e01aa904Sopenharmony_ci operator()(const scope_type_decl& t) const 195e01aa904Sopenharmony_ci { 196e01aa904Sopenharmony_ci decl_base::hash decl_hash; 197e01aa904Sopenharmony_ci type_base::hash type_hash; 198e01aa904Sopenharmony_ci std::hash<string> str_hash; 199e01aa904Sopenharmony_ci 200e01aa904Sopenharmony_ci size_t v = str_hash(typeid(t).name()); 201e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, decl_hash(t)); 202e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, type_hash(t)); 203e01aa904Sopenharmony_ci 204e01aa904Sopenharmony_ci return v; 205e01aa904Sopenharmony_ci } 206e01aa904Sopenharmony_ci}; 207e01aa904Sopenharmony_ci 208e01aa904Sopenharmony_cistruct qualified_type_def::hash 209e01aa904Sopenharmony_ci{ 210e01aa904Sopenharmony_ci size_t 211e01aa904Sopenharmony_ci operator()(const qualified_type_def& t) const 212e01aa904Sopenharmony_ci { 213e01aa904Sopenharmony_ci type_base::hash type_hash; 214e01aa904Sopenharmony_ci decl_base::hash decl_hash; 215e01aa904Sopenharmony_ci std::hash<string> str_hash; 216e01aa904Sopenharmony_ci 217e01aa904Sopenharmony_ci size_t v = str_hash(typeid(t).name()); 218e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, type_hash(t)); 219e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, decl_hash(t)); 220e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, t.get_cv_quals()); 221e01aa904Sopenharmony_ci return v; 222e01aa904Sopenharmony_ci } 223e01aa904Sopenharmony_ci}; 224e01aa904Sopenharmony_ci 225e01aa904Sopenharmony_cistruct pointer_type_def::hash 226e01aa904Sopenharmony_ci{ 227e01aa904Sopenharmony_ci size_t 228e01aa904Sopenharmony_ci operator()(const pointer_type_def& t) const 229e01aa904Sopenharmony_ci { 230e01aa904Sopenharmony_ci std::hash<string> str_hash; 231e01aa904Sopenharmony_ci type_base::hash type_base_hash; 232e01aa904Sopenharmony_ci decl_base::hash decl_hash; 233e01aa904Sopenharmony_ci type_base::shared_ptr_hash hash_type_ptr; 234e01aa904Sopenharmony_ci 235e01aa904Sopenharmony_ci size_t v = str_hash(typeid(t).name()); 236e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, decl_hash(t)); 237e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, type_base_hash(t)); 238e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_type_ptr(t.get_pointed_to_type())); 239e01aa904Sopenharmony_ci return v ; 240e01aa904Sopenharmony_ci } 241e01aa904Sopenharmony_ci}; 242e01aa904Sopenharmony_ci 243e01aa904Sopenharmony_cistruct reference_type_def::hash 244e01aa904Sopenharmony_ci{ 245e01aa904Sopenharmony_ci size_t 246e01aa904Sopenharmony_ci operator()(const reference_type_def& t) 247e01aa904Sopenharmony_ci { 248e01aa904Sopenharmony_ci std::hash<string> hash_str; 249e01aa904Sopenharmony_ci type_base::hash hash_type_base; 250e01aa904Sopenharmony_ci decl_base::hash hash_decl; 251e01aa904Sopenharmony_ci type_base::shared_ptr_hash hash_type_ptr; 252e01aa904Sopenharmony_ci 253e01aa904Sopenharmony_ci size_t v = hash_str(typeid(t).name()); 254e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_str(t.is_lvalue() 255e01aa904Sopenharmony_ci ? "lvalue" 256e01aa904Sopenharmony_ci : "rvalue")); 257e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_type_base(t)); 258e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_decl(t)); 259e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_type_ptr(t.get_pointed_to_type())); 260e01aa904Sopenharmony_ci return v; 261e01aa904Sopenharmony_ci } 262e01aa904Sopenharmony_ci}; 263e01aa904Sopenharmony_ci 264e01aa904Sopenharmony_cistruct array_type_def::subrange_type::hash 265e01aa904Sopenharmony_ci{ 266e01aa904Sopenharmony_ci size_t 267e01aa904Sopenharmony_ci operator()(const array_type_def::subrange_type& s) const 268e01aa904Sopenharmony_ci { 269e01aa904Sopenharmony_ci std::hash<int> hash_size_t; 270e01aa904Sopenharmony_ci size_t v = hash_size_t(hash_size_t(s.get_lower_bound())); 271e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_size_t(s.get_upper_bound())); 272e01aa904Sopenharmony_ci return v; 273e01aa904Sopenharmony_ci } 274e01aa904Sopenharmony_ci}; 275e01aa904Sopenharmony_ci 276e01aa904Sopenharmony_cistruct array_type_def::hash 277e01aa904Sopenharmony_ci{ 278e01aa904Sopenharmony_ci size_t 279e01aa904Sopenharmony_ci operator()(const array_type_def& t) 280e01aa904Sopenharmony_ci { 281e01aa904Sopenharmony_ci std::hash<string> hash_str; 282e01aa904Sopenharmony_ci type_base::hash hash_type_base; 283e01aa904Sopenharmony_ci decl_base::hash hash_decl; 284e01aa904Sopenharmony_ci type_base::shared_ptr_hash hash_type_ptr; 285e01aa904Sopenharmony_ci array_type_def::subrange_type::hash hash_subrange; 286e01aa904Sopenharmony_ci 287e01aa904Sopenharmony_ci size_t v = hash_str(typeid(t).name()); 288e01aa904Sopenharmony_ci 289e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_type_base(t)); 290e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_decl(t)); 291e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_type_ptr(t.get_element_type())); 292e01aa904Sopenharmony_ci 293e01aa904Sopenharmony_ci for (vector<array_type_def::subrange_sptr >::const_iterator i = 294e01aa904Sopenharmony_ci t.get_subranges().begin(); 295e01aa904Sopenharmony_ci i != t.get_subranges().end(); 296e01aa904Sopenharmony_ci ++i) 297e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_subrange(**i)); 298e01aa904Sopenharmony_ci 299e01aa904Sopenharmony_ci return v; 300e01aa904Sopenharmony_ci } 301e01aa904Sopenharmony_ci}; 302e01aa904Sopenharmony_ci 303e01aa904Sopenharmony_cistruct enum_type_decl::hash 304e01aa904Sopenharmony_ci{ 305e01aa904Sopenharmony_ci size_t 306e01aa904Sopenharmony_ci operator()(const enum_type_decl& t) const 307e01aa904Sopenharmony_ci { 308e01aa904Sopenharmony_ci std::hash<string> str_hash; 309e01aa904Sopenharmony_ci decl_base::hash decl_hash; 310e01aa904Sopenharmony_ci type_base::shared_ptr_hash type_ptr_hash; 311e01aa904Sopenharmony_ci std::hash<size_t> size_t_hash; 312e01aa904Sopenharmony_ci 313e01aa904Sopenharmony_ci size_t v = str_hash(typeid(t).name()); 314e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, decl_hash(t)); 315e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, type_ptr_hash(t.get_underlying_type())); 316e01aa904Sopenharmony_ci for (enum_type_decl::enumerators::const_iterator i = 317e01aa904Sopenharmony_ci t.get_enumerators().begin(); 318e01aa904Sopenharmony_ci i != t.get_enumerators().end(); 319e01aa904Sopenharmony_ci ++i) 320e01aa904Sopenharmony_ci { 321e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, str_hash(i->get_name())); 322e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, size_t_hash(i->get_value())); 323e01aa904Sopenharmony_ci } 324e01aa904Sopenharmony_ci return v; 325e01aa904Sopenharmony_ci } 326e01aa904Sopenharmony_ci}; 327e01aa904Sopenharmony_ci 328e01aa904Sopenharmony_cistruct typedef_decl::hash 329e01aa904Sopenharmony_ci{ 330e01aa904Sopenharmony_ci size_t 331e01aa904Sopenharmony_ci operator()(const typedef_decl& t) const 332e01aa904Sopenharmony_ci { 333e01aa904Sopenharmony_ci std::hash<string> str_hash; 334e01aa904Sopenharmony_ci type_base::hash hash_type; 335e01aa904Sopenharmony_ci decl_base::hash decl_hash; 336e01aa904Sopenharmony_ci type_base::shared_ptr_hash type_ptr_hash; 337e01aa904Sopenharmony_ci 338e01aa904Sopenharmony_ci size_t v = str_hash(typeid(t).name()); 339e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_type(t)); 340e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, decl_hash(t)); 341e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, type_ptr_hash(t.get_underlying_type())); 342e01aa904Sopenharmony_ci return v; 343e01aa904Sopenharmony_ci } 344e01aa904Sopenharmony_ci }; 345e01aa904Sopenharmony_ci 346e01aa904Sopenharmony_ci/// Compute a hash for an instance @ref var_decl. 347e01aa904Sopenharmony_ci/// 348e01aa904Sopenharmony_ci/// Note that this function caches the hashing value the 349e01aa904Sopenharmony_ci/// decl_base::hash_ data member of the input instance and re-uses it 350e01aa904Sopenharmony_ci/// when it is already calculated. 351e01aa904Sopenharmony_ci/// 352e01aa904Sopenharmony_ci/// @param t the instance of @ref var_decl to compute the hash for. 353e01aa904Sopenharmony_ci/// 354e01aa904Sopenharmony_ci/// @return the calculated hash value, or the one that was previously 355e01aa904Sopenharmony_ci/// calculated. 356e01aa904Sopenharmony_cisize_t 357e01aa904Sopenharmony_civar_decl::hash::operator()(const var_decl& t) const 358e01aa904Sopenharmony_ci{ 359e01aa904Sopenharmony_ci std::hash<string> hash_string; 360e01aa904Sopenharmony_ci decl_base::hash hash_decl; 361e01aa904Sopenharmony_ci type_base::shared_ptr_hash hash_type_ptr; 362e01aa904Sopenharmony_ci std::hash<size_t> hash_size_t; 363e01aa904Sopenharmony_ci 364e01aa904Sopenharmony_ci size_t v = hash_string(typeid(t).name()); 365e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_decl(t)); 366e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_type_ptr(t.get_type())); 367e01aa904Sopenharmony_ci 368e01aa904Sopenharmony_ci if (is_data_member(t) && get_data_member_is_laid_out(t)) 369e01aa904Sopenharmony_ci { 370e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_decl(*t.get_scope())); 371e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_size_t(get_data_member_offset(t))); 372e01aa904Sopenharmony_ci } 373e01aa904Sopenharmony_ci 374e01aa904Sopenharmony_ci return v; 375e01aa904Sopenharmony_ci} 376e01aa904Sopenharmony_ci 377e01aa904Sopenharmony_ci/// Compute a hash for a pointer to @ref var_decl. 378e01aa904Sopenharmony_ci/// 379e01aa904Sopenharmony_ci/// @param t the pointer to @ref var_decl to compute the hash for. 380e01aa904Sopenharmony_ci/// 381e01aa904Sopenharmony_ci/// @return the calculated hash value 382e01aa904Sopenharmony_cisize_t 383e01aa904Sopenharmony_civar_decl::hash::operator()(const var_decl* t) const 384e01aa904Sopenharmony_ci{return operator()(*t);} 385e01aa904Sopenharmony_ci 386e01aa904Sopenharmony_ci/// Compute a hash value for an instance of @ref function_decl. 387e01aa904Sopenharmony_ci/// 388e01aa904Sopenharmony_ci/// Note that this function caches the resulting hash in the 389e01aa904Sopenharmony_ci/// decl_base::hash_ data member of the instance of @ref 390e01aa904Sopenharmony_ci/// function_decl, and just returns if it is already calculated. 391e01aa904Sopenharmony_ci/// 392e01aa904Sopenharmony_ci/// @param t the function to calculate the hash for. 393e01aa904Sopenharmony_ci/// 394e01aa904Sopenharmony_ci/// @return the hash value. 395e01aa904Sopenharmony_cisize_t 396e01aa904Sopenharmony_cifunction_decl::hash::operator()(const function_decl& t) const 397e01aa904Sopenharmony_ci{ 398e01aa904Sopenharmony_ci std::hash<int> hash_int; 399e01aa904Sopenharmony_ci std::hash<size_t> hash_size_t; 400e01aa904Sopenharmony_ci std::hash<bool> hash_bool; 401e01aa904Sopenharmony_ci std::hash<string> hash_string; 402e01aa904Sopenharmony_ci decl_base::hash hash_decl_base; 403e01aa904Sopenharmony_ci type_base::shared_ptr_hash hash_type_ptr; 404e01aa904Sopenharmony_ci 405e01aa904Sopenharmony_ci size_t v = hash_string(typeid(t).name()); 406e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_decl_base(t)); 407e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_type_ptr(t.get_type())); 408e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_bool(t.is_declared_inline())); 409e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_int(t.get_binding())); 410e01aa904Sopenharmony_ci if (is_member_function(t)) 411e01aa904Sopenharmony_ci { 412e01aa904Sopenharmony_ci bool is_ctor = get_member_function_is_ctor(t), 413e01aa904Sopenharmony_ci is_dtor = get_member_function_is_dtor(t), 414e01aa904Sopenharmony_ci is_static = get_member_is_static(t), 415e01aa904Sopenharmony_ci is_const = get_member_function_is_const(t); 416e01aa904Sopenharmony_ci size_t voffset = get_member_function_vtable_offset(t); 417e01aa904Sopenharmony_ci 418e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_bool(is_ctor)); 419e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_bool(is_dtor)); 420e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_bool(is_static)); 421e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_bool(is_const)); 422e01aa904Sopenharmony_ci if (!is_static && !is_ctor) 423e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_size_t(voffset)); 424e01aa904Sopenharmony_ci } 425e01aa904Sopenharmony_ci 426e01aa904Sopenharmony_ci return v; 427e01aa904Sopenharmony_ci} 428e01aa904Sopenharmony_ci 429e01aa904Sopenharmony_ci/// Compute a hash for a pointer to @ref function_decl. 430e01aa904Sopenharmony_ci/// 431e01aa904Sopenharmony_ci/// @param t the pointer to @ref function_decl to compute the hash for. 432e01aa904Sopenharmony_ci/// 433e01aa904Sopenharmony_ci/// @return the calculated hash value 434e01aa904Sopenharmony_cisize_t 435e01aa904Sopenharmony_cifunction_decl::hash::operator()(const function_decl* t) const 436e01aa904Sopenharmony_ci{return operator()(*t);} 437e01aa904Sopenharmony_ci 438e01aa904Sopenharmony_cisize_t 439e01aa904Sopenharmony_cifunction_decl::parameter::hash::operator() 440e01aa904Sopenharmony_ci (const function_decl::parameter& p) const 441e01aa904Sopenharmony_ci{ 442e01aa904Sopenharmony_ci type_base::shared_ptr_hash hash_type_ptr; 443e01aa904Sopenharmony_ci std::hash<bool> hash_bool; 444e01aa904Sopenharmony_ci std::hash<unsigned> hash_unsigned; 445e01aa904Sopenharmony_ci size_t v = hash_type_ptr(p.get_type()); 446e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_unsigned(p.get_index())); 447e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_bool(p.get_variadic_marker())); 448e01aa904Sopenharmony_ci return v; 449e01aa904Sopenharmony_ci} 450e01aa904Sopenharmony_ci 451e01aa904Sopenharmony_cisize_t 452e01aa904Sopenharmony_cifunction_decl::parameter::hash::operator() 453e01aa904Sopenharmony_ci (const function_decl::parameter* p) const 454e01aa904Sopenharmony_ci{return operator()(*p);} 455e01aa904Sopenharmony_ci 456e01aa904Sopenharmony_cisize_t 457e01aa904Sopenharmony_cifunction_decl::parameter::hash::operator() 458e01aa904Sopenharmony_ci (const function_decl::parameter_sptr p) const 459e01aa904Sopenharmony_ci{return operator()(p.get());} 460e01aa904Sopenharmony_ci 461e01aa904Sopenharmony_ci/// Hashing functor for the @ref method_type type. 462e01aa904Sopenharmony_cistruct method_type::hash 463e01aa904Sopenharmony_ci{ 464e01aa904Sopenharmony_ci size_t 465e01aa904Sopenharmony_ci operator()(const method_type& t) const 466e01aa904Sopenharmony_ci { 467e01aa904Sopenharmony_ci std::hash<string> hash_string; 468e01aa904Sopenharmony_ci type_base::shared_ptr_hash hash_type_ptr; 469e01aa904Sopenharmony_ci function_decl::parameter::hash hash_parameter; 470e01aa904Sopenharmony_ci 471e01aa904Sopenharmony_ci size_t v = hash_string(typeid(t).name()); 472e01aa904Sopenharmony_ci string class_name = t.get_class_type()->get_qualified_name(); 473e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_string(class_name)); 474e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_type_ptr(t.get_return_type())); 475e01aa904Sopenharmony_ci vector<shared_ptr<function_decl::parameter> >::const_iterator i = 476e01aa904Sopenharmony_ci t.get_first_non_implicit_parm(); 477e01aa904Sopenharmony_ci 478e01aa904Sopenharmony_ci for (; i != t.get_parameters().end(); ++i) 479e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_parameter(**i)); 480e01aa904Sopenharmony_ci 481e01aa904Sopenharmony_ci return v; 482e01aa904Sopenharmony_ci } 483e01aa904Sopenharmony_ci 484e01aa904Sopenharmony_ci size_t 485e01aa904Sopenharmony_ci operator()(const method_type* t) 486e01aa904Sopenharmony_ci {return operator()(*t);} 487e01aa904Sopenharmony_ci 488e01aa904Sopenharmony_ci size_t 489e01aa904Sopenharmony_ci operator()(const method_type_sptr t) 490e01aa904Sopenharmony_ci {return operator()(t.get());} 491e01aa904Sopenharmony_ci}; // end struct method_type::hash 492e01aa904Sopenharmony_ci 493e01aa904Sopenharmony_ci// <struct function_type::hash stuff> 494e01aa904Sopenharmony_ci 495e01aa904Sopenharmony_ci/// Hashing function for @ref function_type. 496e01aa904Sopenharmony_ci/// 497e01aa904Sopenharmony_ci/// @param t the function type to hash. 498e01aa904Sopenharmony_ci/// 499e01aa904Sopenharmony_ci/// @return the resulting hash value. 500e01aa904Sopenharmony_cisize_t 501e01aa904Sopenharmony_cifunction_type::hash::operator()(const function_type& t) const 502e01aa904Sopenharmony_ci{ 503e01aa904Sopenharmony_ci std::hash<string> hash_string; 504e01aa904Sopenharmony_ci type_base::shared_ptr_hash hash_type_ptr; 505e01aa904Sopenharmony_ci function_decl::parameter::hash hash_parameter; 506e01aa904Sopenharmony_ci 507e01aa904Sopenharmony_ci size_t v = hash_string(typeid(t).name()); 508e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_type_ptr(t.get_return_type())); 509e01aa904Sopenharmony_ci for (vector<shared_ptr<function_decl::parameter> >::const_iterator i = 510e01aa904Sopenharmony_ci t.get_first_non_implicit_parm(); 511e01aa904Sopenharmony_ci i != t.get_parameters().end(); 512e01aa904Sopenharmony_ci ++i) 513e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_parameter(**i)); 514e01aa904Sopenharmony_ci return v; 515e01aa904Sopenharmony_ci} 516e01aa904Sopenharmony_ci 517e01aa904Sopenharmony_ci/// Hashing function for a pointer to @ref function_type. 518e01aa904Sopenharmony_ci/// 519e01aa904Sopenharmony_ci/// @param t the pointer to @ref function_type to hash. 520e01aa904Sopenharmony_ci/// 521e01aa904Sopenharmony_ci/// @return the resulting hash value. 522e01aa904Sopenharmony_cisize_t 523e01aa904Sopenharmony_cifunction_type::hash::operator()(const function_type* t) const 524e01aa904Sopenharmony_ci{ 525e01aa904Sopenharmony_ci if (const method_type* m = dynamic_cast<const method_type*>(t)) 526e01aa904Sopenharmony_ci { 527e01aa904Sopenharmony_ci method_type::hash h; 528e01aa904Sopenharmony_ci return h(m); 529e01aa904Sopenharmony_ci } 530e01aa904Sopenharmony_ci return operator()(*t); 531e01aa904Sopenharmony_ci} 532e01aa904Sopenharmony_ci 533e01aa904Sopenharmony_ci/// Hashing function for a shared pointer to @ref function_type. 534e01aa904Sopenharmony_ci/// 535e01aa904Sopenharmony_ci/// @param t the pointer to @ref function_type to hash. 536e01aa904Sopenharmony_ci/// 537e01aa904Sopenharmony_ci/// @return the resulting hash value. 538e01aa904Sopenharmony_cisize_t 539e01aa904Sopenharmony_cifunction_type::hash::operator()(const function_type_sptr t) const 540e01aa904Sopenharmony_ci{return operator()(t.get());} 541e01aa904Sopenharmony_ci 542e01aa904Sopenharmony_ci// </struct function_type::hash stuff> 543e01aa904Sopenharmony_ci 544e01aa904Sopenharmony_cisize_t 545e01aa904Sopenharmony_cimember_base::hash::operator()(const member_base& m) const 546e01aa904Sopenharmony_ci{ 547e01aa904Sopenharmony_ci std::hash<int> hash_int; 548e01aa904Sopenharmony_ci return hash_int(m.get_access_specifier()); 549e01aa904Sopenharmony_ci} 550e01aa904Sopenharmony_ci 551e01aa904Sopenharmony_cisize_t 552e01aa904Sopenharmony_ciclass_decl::base_spec::hash::operator()(const base_spec& t) const 553e01aa904Sopenharmony_ci{ 554e01aa904Sopenharmony_ci member_base::hash hash_member; 555e01aa904Sopenharmony_ci type_base::shared_ptr_hash hash_type_ptr; 556e01aa904Sopenharmony_ci std::hash<size_t> hash_size; 557e01aa904Sopenharmony_ci std::hash<bool> hash_bool; 558e01aa904Sopenharmony_ci std::hash<string> hash_string; 559e01aa904Sopenharmony_ci 560e01aa904Sopenharmony_ci size_t v = hash_string(typeid(t).name()); 561e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_member(t)); 562e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_size(t.get_offset_in_bits())); 563e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_bool(t.get_is_virtual())); 564e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_type_ptr(t.get_base_class())); 565e01aa904Sopenharmony_ci return v; 566e01aa904Sopenharmony_ci} 567e01aa904Sopenharmony_ci 568e01aa904Sopenharmony_cisize_t 569e01aa904Sopenharmony_cimember_function_template::hash::operator() 570e01aa904Sopenharmony_ci (const member_function_template& t) const 571e01aa904Sopenharmony_ci{ 572e01aa904Sopenharmony_ci std::hash<bool> hash_bool; 573e01aa904Sopenharmony_ci function_tdecl::hash hash_function_tdecl; 574e01aa904Sopenharmony_ci member_base::hash hash_member; 575e01aa904Sopenharmony_ci std::hash<string> hash_string; 576e01aa904Sopenharmony_ci 577e01aa904Sopenharmony_ci size_t v = hash_member(t); 578e01aa904Sopenharmony_ci string n = t.get_qualified_name(); 579e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_string(n)); 580e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_function_tdecl(t)); 581e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_bool(t.is_constructor())); 582e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_bool(t.is_const())); 583e01aa904Sopenharmony_ci return v; 584e01aa904Sopenharmony_ci} 585e01aa904Sopenharmony_ci 586e01aa904Sopenharmony_cisize_t 587e01aa904Sopenharmony_cimember_class_template::hash::operator() 588e01aa904Sopenharmony_ci (const member_class_template& t) const 589e01aa904Sopenharmony_ci{ 590e01aa904Sopenharmony_ci member_base::hash hash_member; 591e01aa904Sopenharmony_ci class_tdecl::hash hash_class_tdecl; 592e01aa904Sopenharmony_ci std::hash<string> hash_string; 593e01aa904Sopenharmony_ci 594e01aa904Sopenharmony_ci size_t v = hash_member(t); 595e01aa904Sopenharmony_ci string n = t.get_qualified_name(); 596e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_string(n)); 597e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_class_tdecl(t)); 598e01aa904Sopenharmony_ci return v; 599e01aa904Sopenharmony_ci} 600e01aa904Sopenharmony_ci 601e01aa904Sopenharmony_ci/// Compute a hash for a @ref class_or_union 602e01aa904Sopenharmony_ci/// 603e01aa904Sopenharmony_ci/// @param t the class_or_union for which to compute the hash value. 604e01aa904Sopenharmony_ci/// 605e01aa904Sopenharmony_ci/// @return the computed hash value. 606e01aa904Sopenharmony_cisize_t 607e01aa904Sopenharmony_ciclass_or_union::hash::operator()(const class_or_union& t) const 608e01aa904Sopenharmony_ci{ 609e01aa904Sopenharmony_ci if (t.hashing_started() 610e01aa904Sopenharmony_ci || (t.get_is_declaration_only() && !t.get_definition_of_declaration())) 611e01aa904Sopenharmony_ci // All non-resolved decl-only types have a hash of zero. Their hash 612e01aa904Sopenharmony_ci // will differ from the resolved hash, but then at least, having 613e01aa904Sopenharmony_ci // it be zero will give a hint that we couldn't actually compute 614e01aa904Sopenharmony_ci // the hash. 615e01aa904Sopenharmony_ci return 0; 616e01aa904Sopenharmony_ci 617e01aa904Sopenharmony_ci // If the type is decl-only and now has a definition, then hash its 618e01aa904Sopenharmony_ci // definition instead. 619e01aa904Sopenharmony_ci 620e01aa904Sopenharmony_ci if (t.get_is_declaration_only()) 621e01aa904Sopenharmony_ci { 622e01aa904Sopenharmony_ci ABG_ASSERT(t.get_definition_of_declaration()); 623e01aa904Sopenharmony_ci size_t v = operator() 624e01aa904Sopenharmony_ci (*is_class_or_union_type(t.get_definition_of_declaration())); 625e01aa904Sopenharmony_ci return v; 626e01aa904Sopenharmony_ci } 627e01aa904Sopenharmony_ci 628e01aa904Sopenharmony_ci ABG_ASSERT(!t.get_is_declaration_only()); 629e01aa904Sopenharmony_ci 630e01aa904Sopenharmony_ci std::hash<string> hash_string; 631e01aa904Sopenharmony_ci scope_type_decl::hash hash_scope_type; 632e01aa904Sopenharmony_ci var_decl::hash hash_data_member; 633e01aa904Sopenharmony_ci member_function_template::hash hash_member_fn_tmpl; 634e01aa904Sopenharmony_ci member_class_template::hash hash_member_class_tmpl; 635e01aa904Sopenharmony_ci 636e01aa904Sopenharmony_ci size_t v = hash_string(typeid(t).name()); 637e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_scope_type(t)); 638e01aa904Sopenharmony_ci 639e01aa904Sopenharmony_ci t.hashing_started(true); 640e01aa904Sopenharmony_ci 641e01aa904Sopenharmony_ci // Hash data members. 642e01aa904Sopenharmony_ci for (class_decl::data_members::const_iterator d = 643e01aa904Sopenharmony_ci t.get_non_static_data_members().begin(); 644e01aa904Sopenharmony_ci d != t.get_non_static_data_members().end(); 645e01aa904Sopenharmony_ci ++d) 646e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_data_member(**d)); 647e01aa904Sopenharmony_ci 648e01aa904Sopenharmony_ci // Do not hash member functions. All of them are not necessarily 649e01aa904Sopenharmony_ci // emitted per class, in a given TU so do not consider them when 650e01aa904Sopenharmony_ci // hashing a class. 651e01aa904Sopenharmony_ci 652e01aa904Sopenharmony_ci // Hash member function templates 653e01aa904Sopenharmony_ci for (member_function_templates::const_iterator f = 654e01aa904Sopenharmony_ci t.get_member_function_templates().begin(); 655e01aa904Sopenharmony_ci f != t.get_member_function_templates().end(); 656e01aa904Sopenharmony_ci ++f) 657e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_member_fn_tmpl(**f)); 658e01aa904Sopenharmony_ci 659e01aa904Sopenharmony_ci // Hash member class templates 660e01aa904Sopenharmony_ci for (member_class_templates::const_iterator c = 661e01aa904Sopenharmony_ci t.get_member_class_templates().begin(); 662e01aa904Sopenharmony_ci c != t.get_member_class_templates().end(); 663e01aa904Sopenharmony_ci ++c) 664e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_member_class_tmpl(**c)); 665e01aa904Sopenharmony_ci 666e01aa904Sopenharmony_ci t.hashing_started(false); 667e01aa904Sopenharmony_ci 668e01aa904Sopenharmony_ci return v; 669e01aa904Sopenharmony_ci}; 670e01aa904Sopenharmony_ci 671e01aa904Sopenharmony_ci/// Compute a hash for a @ref class_or_union 672e01aa904Sopenharmony_ci/// 673e01aa904Sopenharmony_ci/// @param t the class_or_union for which to compute the hash value. 674e01aa904Sopenharmony_ci/// 675e01aa904Sopenharmony_ci/// @return the computed hash value. 676e01aa904Sopenharmony_cisize_t 677e01aa904Sopenharmony_ciclass_or_union::hash::operator()(const class_or_union *t) const 678e01aa904Sopenharmony_ci{return t ? operator()(*t) : 0;} 679e01aa904Sopenharmony_ci 680e01aa904Sopenharmony_ci/// Compute a hash for a @ref class_decl 681e01aa904Sopenharmony_ci/// 682e01aa904Sopenharmony_ci/// @param t the class_decl for which to compute the hash value. 683e01aa904Sopenharmony_ci/// 684e01aa904Sopenharmony_ci/// @return the computed hash value. 685e01aa904Sopenharmony_cisize_t 686e01aa904Sopenharmony_ciclass_decl::hash::operator()(const class_decl& t) const 687e01aa904Sopenharmony_ci{ 688e01aa904Sopenharmony_ci if (t.hashing_started() 689e01aa904Sopenharmony_ci || (t.get_is_declaration_only() && !t.get_definition_of_declaration())) 690e01aa904Sopenharmony_ci // All non-resolved decl-only types have a hash of zero. Their hash 691e01aa904Sopenharmony_ci // will differ from the resolved hash, but then at least, having 692e01aa904Sopenharmony_ci // it be zero will give a hint that we couldn't actually compute 693e01aa904Sopenharmony_ci // the hash. 694e01aa904Sopenharmony_ci return 0; 695e01aa904Sopenharmony_ci 696e01aa904Sopenharmony_ci 697e01aa904Sopenharmony_ci // If the type is decl-only and now has a definition, then hash its 698e01aa904Sopenharmony_ci // definition instead. 699e01aa904Sopenharmony_ci 700e01aa904Sopenharmony_ci if (t.get_is_declaration_only()) 701e01aa904Sopenharmony_ci { 702e01aa904Sopenharmony_ci ABG_ASSERT(t.get_definition_of_declaration()); 703e01aa904Sopenharmony_ci size_t v = operator()(*is_class_type(t.get_definition_of_declaration())); 704e01aa904Sopenharmony_ci return v; 705e01aa904Sopenharmony_ci } 706e01aa904Sopenharmony_ci 707e01aa904Sopenharmony_ci ABG_ASSERT(!t.get_is_declaration_only()); 708e01aa904Sopenharmony_ci 709e01aa904Sopenharmony_ci std::hash<string> hash_string; 710e01aa904Sopenharmony_ci class_decl::base_spec::hash hash_base; 711e01aa904Sopenharmony_ci class_or_union::hash hash_class_or_union; 712e01aa904Sopenharmony_ci 713e01aa904Sopenharmony_ci size_t v = hash_string(typeid(t).name()); 714e01aa904Sopenharmony_ci 715e01aa904Sopenharmony_ci t.hashing_started(true); 716e01aa904Sopenharmony_ci 717e01aa904Sopenharmony_ci // Hash bases. 718e01aa904Sopenharmony_ci for (class_decl::base_specs::const_iterator b = 719e01aa904Sopenharmony_ci t.get_base_specifiers().begin(); 720e01aa904Sopenharmony_ci b != t.get_base_specifiers().end(); 721e01aa904Sopenharmony_ci ++b) 722e01aa904Sopenharmony_ci { 723e01aa904Sopenharmony_ci class_decl_sptr cl = (*b)->get_base_class(); 724e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_base(**b)); 725e01aa904Sopenharmony_ci } 726e01aa904Sopenharmony_ci 727e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_class_or_union(t)); 728e01aa904Sopenharmony_ci 729e01aa904Sopenharmony_ci t.hashing_started(false); 730e01aa904Sopenharmony_ci 731e01aa904Sopenharmony_ci return v; 732e01aa904Sopenharmony_ci} 733e01aa904Sopenharmony_ci 734e01aa904Sopenharmony_ci/// Compute a hash for a @ref class_decl 735e01aa904Sopenharmony_ci/// 736e01aa904Sopenharmony_ci/// @param t the class_decl for which to compute the hash value. 737e01aa904Sopenharmony_ci/// 738e01aa904Sopenharmony_ci/// @return the computed hash value. 739e01aa904Sopenharmony_cisize_t 740e01aa904Sopenharmony_ciclass_decl::hash::operator()(const class_decl* t) const 741e01aa904Sopenharmony_ci{return t ? operator()(*t) : 0;} 742e01aa904Sopenharmony_ci 743e01aa904Sopenharmony_cistruct template_parameter::hash 744e01aa904Sopenharmony_ci{ 745e01aa904Sopenharmony_ci size_t 746e01aa904Sopenharmony_ci operator()(const template_parameter& t) const 747e01aa904Sopenharmony_ci { 748e01aa904Sopenharmony_ci // Let's avoid infinite recursion triggered from the fact that 749e01aa904Sopenharmony_ci // hashing a template parameter triggers hashing the enclosed 750e01aa904Sopenharmony_ci // template decl, which in turn triggers the hashing of its 751e01aa904Sopenharmony_ci // template parameters; so the initial template parameter that 752e01aa904Sopenharmony_ci // triggered the hashing could be hashed again ... 753e01aa904Sopenharmony_ci if (t.get_hashing_has_started()) 754e01aa904Sopenharmony_ci return 0; 755e01aa904Sopenharmony_ci 756e01aa904Sopenharmony_ci t.set_hashing_has_started(true); 757e01aa904Sopenharmony_ci 758e01aa904Sopenharmony_ci std::hash<unsigned> hash_unsigned; 759e01aa904Sopenharmony_ci std::hash<std::string> hash_string; 760e01aa904Sopenharmony_ci template_decl::hash hash_template_decl; 761e01aa904Sopenharmony_ci 762e01aa904Sopenharmony_ci size_t v = hash_string(typeid(t).name()); 763e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_unsigned(t.get_index())); 764e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_template_decl 765e01aa904Sopenharmony_ci (*t.get_enclosing_template_decl())); 766e01aa904Sopenharmony_ci 767e01aa904Sopenharmony_ci t.set_hashing_has_started(false); 768e01aa904Sopenharmony_ci 769e01aa904Sopenharmony_ci return v; 770e01aa904Sopenharmony_ci } 771e01aa904Sopenharmony_ci}; 772e01aa904Sopenharmony_ci 773e01aa904Sopenharmony_cistruct template_parameter::dynamic_hash 774e01aa904Sopenharmony_ci{ 775e01aa904Sopenharmony_ci size_t 776e01aa904Sopenharmony_ci operator()(const template_parameter* t) const; 777e01aa904Sopenharmony_ci}; 778e01aa904Sopenharmony_ci 779e01aa904Sopenharmony_cistruct template_parameter::shared_ptr_hash 780e01aa904Sopenharmony_ci{ 781e01aa904Sopenharmony_ci size_t 782e01aa904Sopenharmony_ci operator()(const shared_ptr<template_parameter> t) const 783e01aa904Sopenharmony_ci {return template_parameter::dynamic_hash()(t.get());} 784e01aa904Sopenharmony_ci}; 785e01aa904Sopenharmony_ci 786e01aa904Sopenharmony_cisize_t 787e01aa904Sopenharmony_citemplate_decl::hash::operator()(const template_decl& t) const 788e01aa904Sopenharmony_ci{ 789e01aa904Sopenharmony_ci std::hash<string> hash_string; 790e01aa904Sopenharmony_ci template_parameter::shared_ptr_hash hash_template_parameter; 791e01aa904Sopenharmony_ci 792e01aa904Sopenharmony_ci size_t v = hash_string(typeid(t).name()); 793e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_string(t.get_qualified_name())); 794e01aa904Sopenharmony_ci 795e01aa904Sopenharmony_ci for (list<template_parameter_sptr>::const_iterator p = 796e01aa904Sopenharmony_ci t.get_template_parameters().begin(); 797e01aa904Sopenharmony_ci p != t.get_template_parameters().end(); 798e01aa904Sopenharmony_ci ++p) 799e01aa904Sopenharmony_ci if (!(*p)->get_hashing_has_started()) 800e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_template_parameter(*p)); 801e01aa904Sopenharmony_ci 802e01aa904Sopenharmony_ci return v; 803e01aa904Sopenharmony_ci} 804e01aa904Sopenharmony_ci 805e01aa904Sopenharmony_cistruct type_tparameter::hash 806e01aa904Sopenharmony_ci{ 807e01aa904Sopenharmony_ci size_t 808e01aa904Sopenharmony_ci operator()(const type_tparameter& t) const 809e01aa904Sopenharmony_ci { 810e01aa904Sopenharmony_ci std::hash<string> hash_string; 811e01aa904Sopenharmony_ci template_parameter::hash hash_template_parameter; 812e01aa904Sopenharmony_ci type_decl::hash hash_type; 813e01aa904Sopenharmony_ci 814e01aa904Sopenharmony_ci size_t v = hash_string(typeid(t).name()); 815e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_template_parameter(t)); 816e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_type(t)); 817e01aa904Sopenharmony_ci 818e01aa904Sopenharmony_ci return v; 819e01aa904Sopenharmony_ci } 820e01aa904Sopenharmony_ci}; 821e01aa904Sopenharmony_ci 822e01aa904Sopenharmony_ci/// Compute a hash value for a @ref non_type_tparameter 823e01aa904Sopenharmony_ci/// 824e01aa904Sopenharmony_ci/// @param t the non_type_tparameter for which to compute the value. 825e01aa904Sopenharmony_ci/// 826e01aa904Sopenharmony_ci/// @return the computed hash value. 827e01aa904Sopenharmony_cisize_t 828e01aa904Sopenharmony_cinon_type_tparameter::hash::operator()(const non_type_tparameter& t) const 829e01aa904Sopenharmony_ci{ 830e01aa904Sopenharmony_ci template_parameter::hash hash_template_parameter; 831e01aa904Sopenharmony_ci std::hash<string> hash_string; 832e01aa904Sopenharmony_ci type_base::shared_ptr_hash hash_type; 833e01aa904Sopenharmony_ci 834e01aa904Sopenharmony_ci size_t v = hash_string(typeid(t).name()); 835e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_template_parameter(t)); 836e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_string(t.get_name())); 837e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_type(t.get_type())); 838e01aa904Sopenharmony_ci 839e01aa904Sopenharmony_ci return v; 840e01aa904Sopenharmony_ci} 841e01aa904Sopenharmony_ci 842e01aa904Sopenharmony_ci/// Compute a hash value for a @ref non_type_tparameter 843e01aa904Sopenharmony_ci/// 844e01aa904Sopenharmony_ci/// @param t the non_type_tparameter to compute the hash value for. 845e01aa904Sopenharmony_ci/// 846e01aa904Sopenharmony_ci/// @return the computed hash value. 847e01aa904Sopenharmony_cisize_t 848e01aa904Sopenharmony_cinon_type_tparameter::hash::operator()(const non_type_tparameter* t) const 849e01aa904Sopenharmony_ci{return t ? operator()(*t) : 0;} 850e01aa904Sopenharmony_ci 851e01aa904Sopenharmony_cistruct template_tparameter::hash 852e01aa904Sopenharmony_ci{ 853e01aa904Sopenharmony_ci size_t 854e01aa904Sopenharmony_ci operator()(const template_tparameter& t) const 855e01aa904Sopenharmony_ci { 856e01aa904Sopenharmony_ci std::hash<string> hash_string; 857e01aa904Sopenharmony_ci type_tparameter::hash hash_template_type_parm; 858e01aa904Sopenharmony_ci template_decl::hash hash_template_decl; 859e01aa904Sopenharmony_ci 860e01aa904Sopenharmony_ci size_t v = hash_string(typeid(t).name()); 861e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_template_type_parm(t)); 862e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_template_decl(t)); 863e01aa904Sopenharmony_ci 864e01aa904Sopenharmony_ci return v; 865e01aa904Sopenharmony_ci } 866e01aa904Sopenharmony_ci}; 867e01aa904Sopenharmony_ci 868e01aa904Sopenharmony_cisize_t 869e01aa904Sopenharmony_citemplate_parameter::dynamic_hash:: 870e01aa904Sopenharmony_cioperator()(const template_parameter* t) const 871e01aa904Sopenharmony_ci{ 872e01aa904Sopenharmony_ci if (const template_tparameter* p = 873e01aa904Sopenharmony_ci dynamic_cast<const template_tparameter*>(t)) 874e01aa904Sopenharmony_ci return template_tparameter::hash()(*p); 875e01aa904Sopenharmony_ci else if (const type_tparameter* p = 876e01aa904Sopenharmony_ci dynamic_cast<const type_tparameter*>(t)) 877e01aa904Sopenharmony_ci return type_tparameter::hash()(*p); 878e01aa904Sopenharmony_ci if (const non_type_tparameter* p = 879e01aa904Sopenharmony_ci dynamic_cast<const non_type_tparameter*>(t)) 880e01aa904Sopenharmony_ci return non_type_tparameter::hash()(*p); 881e01aa904Sopenharmony_ci 882e01aa904Sopenharmony_ci // Poor man's fallback. 883e01aa904Sopenharmony_ci return template_parameter::hash()(*t); 884e01aa904Sopenharmony_ci} 885e01aa904Sopenharmony_ci 886e01aa904Sopenharmony_ci/// Compute a hash value for a @ref type_composition type. 887e01aa904Sopenharmony_ci/// 888e01aa904Sopenharmony_ci/// @param t the type_composition to compute the hash value for. 889e01aa904Sopenharmony_ci/// 890e01aa904Sopenharmony_ci/// @return the computed hash value. 891e01aa904Sopenharmony_cisize_t 892e01aa904Sopenharmony_citype_composition::hash::operator()(const type_composition& t) const 893e01aa904Sopenharmony_ci{ 894e01aa904Sopenharmony_ci std::hash<string> hash_string; 895e01aa904Sopenharmony_ci type_base::dynamic_hash hash_type; 896e01aa904Sopenharmony_ci 897e01aa904Sopenharmony_ci size_t v = hash_string(typeid(t).name()); 898e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_type(t.get_composed_type().get())); 899e01aa904Sopenharmony_ci return v; 900e01aa904Sopenharmony_ci} 901e01aa904Sopenharmony_ci 902e01aa904Sopenharmony_ci/// Compute a hash value for a @ref type_composition type. 903e01aa904Sopenharmony_ci/// 904e01aa904Sopenharmony_ci/// @param t the type_composition to compute the hash value for. 905e01aa904Sopenharmony_ci/// 906e01aa904Sopenharmony_ci/// @return the computed hash value. 907e01aa904Sopenharmony_cisize_t 908e01aa904Sopenharmony_citype_composition::hash::operator()(const type_composition* t) const 909e01aa904Sopenharmony_ci{return t ? operator()(*t): 0;} 910e01aa904Sopenharmony_ci 911e01aa904Sopenharmony_cisize_t 912e01aa904Sopenharmony_cifunction_tdecl::hash:: 913e01aa904Sopenharmony_cioperator()(const function_tdecl& t) const 914e01aa904Sopenharmony_ci{ 915e01aa904Sopenharmony_ci std::hash<string> hash_string; 916e01aa904Sopenharmony_ci decl_base::hash hash_decl_base; 917e01aa904Sopenharmony_ci template_decl::hash hash_template_decl; 918e01aa904Sopenharmony_ci function_decl::hash hash_function_decl; 919e01aa904Sopenharmony_ci 920e01aa904Sopenharmony_ci size_t v = hash_string(typeid(t).name()); 921e01aa904Sopenharmony_ci 922e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_decl_base(t)); 923e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_template_decl(t)); 924e01aa904Sopenharmony_ci if (t.get_pattern()) 925e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_function_decl(*t.get_pattern())); 926e01aa904Sopenharmony_ci 927e01aa904Sopenharmony_ci return v; 928e01aa904Sopenharmony_ci} 929e01aa904Sopenharmony_ci 930e01aa904Sopenharmony_cisize_t 931e01aa904Sopenharmony_cifunction_tdecl::shared_ptr_hash:: 932e01aa904Sopenharmony_cioperator()(const shared_ptr<function_tdecl> f) const 933e01aa904Sopenharmony_ci{ 934e01aa904Sopenharmony_ci function_tdecl::hash hash_fn_tmpl_decl; 935e01aa904Sopenharmony_ci if (f) 936e01aa904Sopenharmony_ci return hash_fn_tmpl_decl(*f); 937e01aa904Sopenharmony_ci return 0; 938e01aa904Sopenharmony_ci} 939e01aa904Sopenharmony_ci 940e01aa904Sopenharmony_cisize_t 941e01aa904Sopenharmony_ciclass_tdecl::hash:: 942e01aa904Sopenharmony_cioperator()(const class_tdecl& t) const 943e01aa904Sopenharmony_ci{ 944e01aa904Sopenharmony_ci std::hash<string> hash_string; 945e01aa904Sopenharmony_ci decl_base::hash hash_decl_base; 946e01aa904Sopenharmony_ci template_decl::hash hash_template_decl; 947e01aa904Sopenharmony_ci class_decl::hash hash_class_decl; 948e01aa904Sopenharmony_ci 949e01aa904Sopenharmony_ci size_t v = hash_string(typeid(t).name()); 950e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_decl_base(t)); 951e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_template_decl(t)); 952e01aa904Sopenharmony_ci if (t.get_pattern()) 953e01aa904Sopenharmony_ci v = hashing::combine_hashes(v, hash_class_decl(*t.get_pattern())); 954e01aa904Sopenharmony_ci 955e01aa904Sopenharmony_ci return v; 956e01aa904Sopenharmony_ci} 957e01aa904Sopenharmony_ci 958e01aa904Sopenharmony_cisize_t 959e01aa904Sopenharmony_ciclass_tdecl::shared_ptr_hash:: 960e01aa904Sopenharmony_cioperator()(const shared_ptr<class_tdecl> t) const 961e01aa904Sopenharmony_ci{ 962e01aa904Sopenharmony_ci class_tdecl::hash hash_class_tmpl_decl; 963e01aa904Sopenharmony_ci 964e01aa904Sopenharmony_ci if (t) 965e01aa904Sopenharmony_ci return hash_class_tmpl_decl(*t); 966e01aa904Sopenharmony_ci return 0; 967e01aa904Sopenharmony_ci} 968e01aa904Sopenharmony_ci 969e01aa904Sopenharmony_ci/// A hashing function for type declarations. 970e01aa904Sopenharmony_ci/// 971e01aa904Sopenharmony_ci/// This function gets the dynamic type of the actual type 972e01aa904Sopenharmony_ci/// declaration and calls the right hashing function for that type. 973e01aa904Sopenharmony_ci/// 974e01aa904Sopenharmony_ci/// Note that each time a new type declaration kind is added to the 975e01aa904Sopenharmony_ci/// system, this function needs to be updated. For a given 976e01aa904Sopenharmony_ci/// inheritance hierarchy, make sure to handle the most derived type 977e01aa904Sopenharmony_ci/// first. 978e01aa904Sopenharmony_ci/// 979e01aa904Sopenharmony_ci/// FIXME: This hashing function is not maintained and is surely 980e01aa904Sopenharmony_ci/// broken in subtle ways. In pratice, the various *::hash functors 981e01aa904Sopenharmony_ci/// should be audited before they are used here. They should all 982e01aa904Sopenharmony_ci/// match what is done in the 'equals' functions in abg-ir.cc. 983e01aa904Sopenharmony_ci/// 984e01aa904Sopenharmony_ci/// @param t a pointer to the type declaration to be hashed 985e01aa904Sopenharmony_ci/// 986e01aa904Sopenharmony_ci/// @return the resulting hash 987e01aa904Sopenharmony_cisize_t 988e01aa904Sopenharmony_citype_base::dynamic_hash::operator()(const type_base* t) const 989e01aa904Sopenharmony_ci{ 990e01aa904Sopenharmony_ci if (t == 0) 991e01aa904Sopenharmony_ci return 0; 992e01aa904Sopenharmony_ci 993e01aa904Sopenharmony_ci if (const member_function_template* d = 994e01aa904Sopenharmony_ci dynamic_cast<const member_function_template*>(t)) 995e01aa904Sopenharmony_ci return member_function_template::hash()(*d); 996e01aa904Sopenharmony_ci if (const member_class_template* d = 997e01aa904Sopenharmony_ci dynamic_cast<const member_class_template*>(t)) 998e01aa904Sopenharmony_ci return member_class_template::hash()(*d); 999e01aa904Sopenharmony_ci if (const template_tparameter* d = 1000e01aa904Sopenharmony_ci dynamic_cast<const template_tparameter*>(t)) 1001e01aa904Sopenharmony_ci return template_tparameter::hash()(*d); 1002e01aa904Sopenharmony_ci if (const type_tparameter* d = 1003e01aa904Sopenharmony_ci dynamic_cast<const type_tparameter*>(t)) 1004e01aa904Sopenharmony_ci return type_tparameter::hash()(*d); 1005e01aa904Sopenharmony_ci if (const type_decl* d = dynamic_cast<const type_decl*> (t)) 1006e01aa904Sopenharmony_ci return type_decl::hash()(*d); 1007e01aa904Sopenharmony_ci if (const qualified_type_def* d = dynamic_cast<const qualified_type_def*>(t)) 1008e01aa904Sopenharmony_ci return qualified_type_def::hash()(*d); 1009e01aa904Sopenharmony_ci if (const pointer_type_def* d = dynamic_cast<const pointer_type_def*>(t)) 1010e01aa904Sopenharmony_ci return pointer_type_def::hash()(*d); 1011e01aa904Sopenharmony_ci if (const reference_type_def* d = dynamic_cast<const reference_type_def*>(t)) 1012e01aa904Sopenharmony_ci return reference_type_def::hash()(*d); 1013e01aa904Sopenharmony_ci if (const array_type_def* d = dynamic_cast<const array_type_def*>(t)) 1014e01aa904Sopenharmony_ci return array_type_def::hash()(*d); 1015e01aa904Sopenharmony_ci if (const enum_type_decl* d = dynamic_cast<const enum_type_decl*>(t)) 1016e01aa904Sopenharmony_ci return enum_type_decl::hash()(*d); 1017e01aa904Sopenharmony_ci if (const typedef_decl* d = dynamic_cast<const typedef_decl*>(t)) 1018e01aa904Sopenharmony_ci return typedef_decl::hash()(*d); 1019e01aa904Sopenharmony_ci if (const class_decl* d = dynamic_cast<const class_decl*>(t)) 1020e01aa904Sopenharmony_ci return class_decl::hash()(*d); 1021e01aa904Sopenharmony_ci if (const union_decl* d = dynamic_cast<const union_decl*>(t)) 1022e01aa904Sopenharmony_ci return union_decl::hash()(*d); 1023e01aa904Sopenharmony_ci if (const scope_type_decl* d = dynamic_cast<const scope_type_decl*>(t)) 1024e01aa904Sopenharmony_ci return scope_type_decl::hash()(*d); 1025e01aa904Sopenharmony_ci if (const method_type* d = dynamic_cast<const method_type*>(t)) 1026e01aa904Sopenharmony_ci return method_type::hash()(*d); 1027e01aa904Sopenharmony_ci if (const function_type* d = dynamic_cast<const function_type*>(t)) 1028e01aa904Sopenharmony_ci return function_type::hash()(*d); 1029e01aa904Sopenharmony_ci 1030e01aa904Sopenharmony_ci // Poor man's fallback case. 1031e01aa904Sopenharmony_ci return type_base::hash()(*t); 1032e01aa904Sopenharmony_ci} 1033e01aa904Sopenharmony_ci 1034e01aa904Sopenharmony_cisize_t 1035e01aa904Sopenharmony_citype_base::shared_ptr_hash::operator()(const shared_ptr<type_base> t) const 1036e01aa904Sopenharmony_ci{return type_base::dynamic_hash()(t.get());} 1037e01aa904Sopenharmony_ci 1038e01aa904Sopenharmony_ci}//end namespace abigail 1039