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