libabigail
abg-hash.cc
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2// -*- mode: C++ -*-
3//
4// Copyright (C) 2013-2025 Red Hat, Inc.
5
6/// @file
7
8#include <functional>
9#include <cstring>
10#include <xxhash.h>
11#include "abg-internal.h"
12#include "abg-ir-priv.h"
13
14// <headers defining libabigail's API go under here>
15ABG_BEGIN_EXPORT_DECLARATIONS
16
17#include "abg-hash.h"
18#include "abg-ir.h"
19
20ABG_END_EXPORT_DECLARATIONS
21// </headers defining libabigail's API>
22
23namespace abigail
24{
25
26namespace hashing
27{
28
29/// Read a character representing an hexadecimal digit (from '0' to
30/// 'f' or to 'F'), and return an integer representing the value of
31/// that digit. For instance, for the character '0', the function
32/// returns the integer 0. For the character 'A' (or 'a'), the
33/// function returns the integer 10; for the character 'b' (or 'B')
34/// the function returns the integer 11.
35///
36/// @param c the input character to transform into an integer.
37///
38/// @param integer output value. This is set by the function to the
39/// integer representing the character @p c.
40///
41/// @return true iff @p c is a character representing an hexadecimal
42/// number which value could be set to @p integer.
43static bool
44char_to_int(char c, unsigned char& integer)
45{
46 if (c >= '0' && c <= '9')
47 integer = c - '0';
48 else if (c >= 'a' && c <= 'z')
49 integer = 10 + c - 'a';
50 else if (c >= 'A' && c <= 'Z')
51 integer = 10 + c - 'A';
52 else
53 return false;
54
55 return true;
56}
57
58/// Given an integer value representing an hexadecimal digit (from 0
59/// to F), emit the character value which prints that digit. For the
60/// integer 11, the function returns the character 'b'. For the
61/// integer 10, it returns the character 'a'.
62///
63/// @param integer the input hexadecimal integer digit to take into
64/// account.
65///
66/// @param c the output character representing the digit @p integer.
67///
68/// @return true iff @p integer is a valid hexadecimal digit that
69/// could could be represented by a character @p c.
70static bool
71int_to_char(unsigned char integer, unsigned char& c)
72{
73 if (integer <= 9)
74 c = integer + '0';
75 else if (integer >= 0xA && integer <= 0xF)
76 c = 'a' + (integer - 0xA);
77 else
78 return false;
79
80 return true;
81}
82
83/// Read a string of characters representing a string of hexadecimal
84/// digits which itself represents a hash value that was computed
85/// using the XH64 algorithm from the xxhash project.
86///
87/// That string of digit (characters) is laid out in the "canonical
88/// form" requested by the xxhash project. That form is basically the
89/// hash number, represented in big endian.
90///
91/// @param input the input string of characters to consider.
92///
93/// @param hash the resulting hash value de-serialized from @p input.
94/// This is set by the function iff it returns true.
95///
96/// @return true iff the function could de-serialize the characters
97/// string @p input into the hash value @p hash.
98bool
99deserialize_hash(const string& input, uint64_t& hash)
100{
101 unsigned char byte = 0;
102 string xxh64_canonical_form;
103 for (size_t i = 0; i + 1 < input.size(); i += 2)
104 {
105 unsigned char first_nibble = 0, second_nibble = 0;
106 ABG_ASSERT(char_to_int(input[i], first_nibble));
107 ABG_ASSERT(char_to_int(input[i+1], second_nibble));
108 byte = (first_nibble << 4) | second_nibble;
109 xxh64_canonical_form.push_back(byte);
110 }
111
112 XXH64_canonical_t canonical_hash = {};
113 size_t size = sizeof(canonical_hash.digest);
114 memcpy(canonical_hash.digest,
115 xxh64_canonical_form.c_str(),
116 size);
117 hash = XXH64_hashFromCanonical(&canonical_hash);
118
119 return true;
120}
121
122/// Serialiaze a hash value computed using the XH64 algorithm (from the
123/// xxhash project) into a string of characters representing the
124/// digits of the hash in the canonical form requested by the xxhash
125/// project. That canonical form is basically a big endian
126/// representation of the hexadecimal hash number.
127///
128/// @param hash the hash number to serialize.
129///
130/// @param output the resulting string of characters representing the
131/// hash value @p hash in its serialized form. This is set iff the
132/// function return true.
133///
134/// @return true iff the function could serialize the hash value @p
135/// hash into a serialized form that is set into the output parameter
136/// @p output.
137bool
138serialize_hash(uint64_t hash, string& output)
139{
140 XXH64_canonical_t canonical_output = {};
141 XXH64_canonicalFromHash(&canonical_output, hash);
142 for (unsigned i = 0; i < sizeof(canonical_output.digest); ++i)
143 {
144 unsigned char first_nibble = 0, second_nibble = 0;
145 unsigned char byte = canonical_output.digest[i];
146 first_nibble = (0xf0 & byte) >> 4;
147 second_nibble = 0xf & byte;
148 unsigned char c = 0;
149 int_to_char(first_nibble, c);
150 output.push_back(c);
151 int_to_char(second_nibble, c);
152 output.push_back(c);
153 }
154
155 return true;
156}
157
158// </serialized_hash_type definitions>
159
160/// Combine two hash values to produce a third hash value.
161///
162/// If one of the hash values is empty then the other one is returned,
163/// intact. If the two hash values are empty then an empty hash value
164/// is returned as a result.
165///
166/// @param val1 the first hash value.
167///
168/// @param val2 the second hash value.
169///
170/// @return a combination of the hash values @p val1 and @p val2.
171hash_t
173{
174 hash_t result;
175 if (val1.has_value() && val2.has_value())
176 result = hash(*val2, *val1);
177 else if (val1.has_value())
178 result = *val1;
179 else if (val2.has_value())
180 result = *val2;
181
182 return result;
183}
184
185/// Hash an integer value and combine it with a hash previously
186/// computed.
187///
188/// @param v the value to hash.
189///
190/// @param seed a previous hash value that is to be combined with the
191/// result of hashing @p v. This is can be zero if no previous hash
192/// value is available.
193///
194/// @return the resulting hash value.
195hash_t
196hash(uint64_t v, uint64_t seed)
197{
198 // THe XXH hashing functions take an array of bytes representing the
199 // value to hash. So let's represent 'v' as a big endian input and
200 // pass it to XXH3_64bits_withSeed.
201 unsigned char data[sizeof(uint64_t)] = {};
202 uint64_t t = v;
203 size_t data_size = sizeof(data);
204 for (unsigned i = 0; i < data_size; ++i)
205 {
206 data[data_size - i - 1] = t & 0xff;
207 t = t >> 8;
208 }
209 hash_t h = XXH3_64bits_withSeed(data, data_size, seed);
210 return h;
211}
212
213/// Hash a string.
214///
215/// @param str the string to hash.
216///
217/// @return the resulting hash value.
218hash_t
219hash(const std::string& str)
220{
221 hash_t h = XXH3_64bits(str.c_str(), str.size());
222 return h;
223}
224
225/// Compute a stable string hash.
226///
227/// std::hash has no portability or stability guarantees so is
228/// unsuitable where reproducibility is a requirement such as in XML
229/// output.
230///
231/// This is the 32-bit FNV-1a algorithm. The algorithm, reference code
232/// and constants are all unencumbered. It is fast and has reasonable
233/// distribution properties.
234///
235/// https://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function
236///
237/// @param str the string to hash.
238///
239/// @return an unsigned 32 bit hash value.
241fnv_hash(const std::string& str)
242{
243 const uint32_t prime = 0x01000193;
244 const uint32_t offset_basis = 0x811c9dc5;
245 uint32_t hash = offset_basis;
246 for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
247 {
248 uint8_t byte = *i;
249 hash = hash ^ byte;
250 hash = hash * prime;
251 }
252 return hash;
253}
254
255/// Get the hashing state of an IR node.
256///
257/// @param tod the type or decl IR node to get the hashing state for.
258///
259/// @return the hashing state of @p tod.
262{
263 const type_or_decl_base* todp = &tod;
264 if (decl_base *d = is_decl(todp))
265 {
267 return d->type_or_decl_base::priv_->get_hashing_state();
268 }
269 else
270 return tod.priv_->get_hashing_state();
271}
272
273/// Set the hashing state of an IR node.
274///
275/// @param tod the type or decl IR node to set the hashing state for.
276///
277///
278/// @param s the new hashing state to set.
279void
282{
283 const type_or_decl_base* todp = &tod;
284 if (decl_base* d = is_decl(todp))
285 {
287 d->type_or_decl_base::priv_->set_hashing_state(s);
288 }
289 else
290 tod.priv_->set_hashing_state(s);
291}
292
293/// Test if an artifact is recursive.
294///
295/// For now, a recursive artifact is a type that contains a sub-type
296/// that refers to itself.
297///
298/// @param t the artifact to consider.
299///
300/// @return truf iff @p t is recursive.
301bool
303{
304 bool result = false;
305 const type_or_decl_base* tp = &t;
306 if (decl_base* d = is_decl(tp))
307 {
309 result = d->type_or_decl_base::priv_->is_recursive_artefact();
310 }
311 else
312 result = t.type_or_decl_base::priv_->is_recursive_artefact();
313
314 return result;
315}
316
317/// Set the property that flags an artifact as recursive.
318///
319/// For now, a recursive artifact is a type that contains a sub-type
320/// that refers to itself.
321///
322/// @param t the artifact to consider.
323///
324/// @param f the new value of the flag. If true, then the artefact @p
325/// t is considered recursive.
326void
328{
329 const type_or_decl_base* tp = &t;
330 if (decl_base* d = is_decl(tp))
331 {
333 d->type_or_decl_base::priv_->is_recursive_artefact(f);
334 }
335 else
336 t.priv_->is_recursive_artefact(f);
337}
338}//end namespace hashing
339
340using std::list;
341using std::vector;
342
343using namespace abigail::ir;
344
345// See forward declarations in abg-ir.h.
346
347// Definitions.
348
349#define MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(type) \
350 do \
351 { \
352 if (hashing::get_hashing_state(type) == hashing::HASHING_STARTED_STATE \
353 || hashing::get_hashing_state(type) == hashing::HASHING_SUBTYPE_STATE) \
354 { \
355 hashing::set_hashing_state(t, hashing::HASHING_CYCLED_TYPE_STATE); \
356 hashing::is_recursive_artefact(type, true); \
357 return hash_t(); \
358 } \
359 else if (hashing::get_hashing_state(type) == hashing::HASHING_CYCLED_TYPE_STATE) \
360 return hash_t(); \
361 else if (hashing::get_hashing_state(type) == hashing::HASHING_FINISHED_STATE) \
362 return peek_hash_value(type); \
363 } \
364 while(false)
365
366#define MAYBE_FLAG_TYPE_AS_RECURSIVE(type, underlying, h) \
367 do \
368 { \
369 if (!h || hashing::is_recursive_artefact(*underlying)) \
370 hashing::is_recursive_artefact(type, true); \
371 } \
372 while(false)
373
374#define MAYBE_RETURN_EARLY_IF_HASH_EXISTS(type) \
375 do \
376 { \
377 if (hashing::get_hashing_state(type) == hashing::HASHING_FINISHED_STATE) \
378 return peek_hash_value(type); \
379 } \
380 while(false)
381
382/// The hashing functor for using instances of @ref type_or_decl_base
383/// as values in a hash map or set.
384
385/// Hash function for an instance of @ref type_base.
386///
387/// @param t the type to hash.
388///
389/// @return the type value.
390hash_t
391type_base::hash::operator()(const type_base& t) const
392{
395 return v;
396}
397
398/// Hash function for an instance of @ref type_base.
399///
400/// @param t the type to hash.
401///
402/// @return the type value.
403hash_t
404type_base::hash::operator()(const type_base* t) const
405{return operator()(*t);}
406
407/// Hash function for an instance of @ref type_base.
408///
409/// @param t the type to hash.
410///
411/// @return the hash value.
412hash_t
413type_base::hash::operator()(const type_base_sptr t) const
414{return operator()(*t);}
415
416/// Hash function for an instance of @ref decl_base.
417///
418/// @param d the decl to hash.
419///
420/// @return the hash value.
421hash_t
422decl_base::hash::operator()(const decl_base& d) const
423{
424 hash_t v = 0;
425
426 if (!d.get_is_anonymous())
427 {
428 interned_string ln = d.get_name();
429 v = hashing::hash((string) ln);
430 }
431
432 if (is_member_decl(d))
433 {
436 }
437
438 return v;
439}
440
441/// Hash function for an instance of @ref decl_base.
442///
443/// @param d the decl to hash.
444///
445/// @return the hash value.
446hash_t
447decl_base::hash::operator()(const decl_base* d) const
448{
449 if (!d)
450 return 0;
451 return operator()(*d);
452}
453
454/// Hashing function for a @ref type_decl IR node.
455///
456/// @param t the @ref type_decl IR node t hash.
457///
458/// @return the resulting hash value.
459hash_t
460type_decl::hash::operator()(const type_decl& t) const
461{
462 MAYBE_RETURN_EARLY_IF_HASH_EXISTS(t);
463
464 decl_base::hash decl_hash;
465 type_base::hash type_hash;
466
468
469 hash_t v = decl_hash(t);
470 v = hashing::combine_hashes(v, type_hash(t));
471
473
474 t.set_hash_value(v);
475
476 return v;
477}
478
479/// Hashing function for a @ref type_decl IR node.
480///
481/// @param t the @ref type_decl IR node to hash.
482///
483/// @return the resulting hash value.
484hash_t
485type_decl::hash::operator()(const type_decl* t) const
486{
487 if (!t)
488 return 0;
489 return operator()(*t);
490}
491
492/// Hashing function for a @ref typedef_decl IR node.
493///
494/// @param t the @ref typedef_decl IR node to hash
495///
496/// @return the resulting hash value.
497hash_t
498typedef_decl::hash::operator()(const typedef_decl& t) const
499{
500 MAYBE_RETURN_EARLY_IF_HASH_EXISTS(t);
501
503
504 // The hash value of a typedef is the same as the hash value of its
505 // underlying type.
506 type_base_sptr u = look_through_decl_only_type(t.get_underlying_type());
509 hash_t v = u->hash_value();
511 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, u, v);
512
514
515 return v;
516}
517
518/// Hashing function for a @ref typedef_decl IR node.
519///
520/// @param t the @ref typedef_decl IR node to hash
521///
522/// @return the resulting hash value.
523hash_t
524typedef_decl::hash::operator()(const typedef_decl* t) const
525{
526 if (!t)
527 return 0;
528 return operator()(*t);
529}
530
531/// Hashing function for a @ref qualified_type_def IR node.
532///
533/// @param t the @ref qualified_type_def IR node to hash.
534///
535/// @return the resulting hash value.
536hash_t
537qualified_type_def::hash::operator()(const qualified_type_def& t) const
538{
539 MAYBE_RETURN_EARLY_IF_HASH_EXISTS(t);
540
541 type_base::hash type_hash;
542 decl_base::hash decl_hash;
543
545
546 type_base_sptr u = look_through_decl_only_type(t.get_underlying_type());
549 hash_t v = u->hash_value();
551 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, u, v);
552 v = hashing::combine_hashes(v, type_hash(t));
553 v = hashing::combine_hashes(v, decl_hash(t));
555
557
558 return v;
559}
560
561/// Hashing function for a @ref qualified_type_def IR node.
562///
563/// @param t the @ref qualified_type_def IR node to hash.
564///
565/// @return the resulting hash value.
566hash_t
567qualified_type_def::hash::operator()(const qualified_type_def* t) const
568{
569 if (!t)
570 return 0;
571 return operator()(*t);
572}
573
574/// Hashing function for a @ref pointer_type_def IR node.
575///
576/// @param t the @ref pointer_type_def IR node to hash.
577///
578/// @return the resulting hash value.
579hash_t
580pointer_type_def::hash::operator()(const pointer_type_def& t) const
581{
582 MAYBE_RETURN_EARLY_IF_HASH_EXISTS(t);
583
584 type_base::hash type_base_hash;
585 decl_base::hash decl_hash;
586
588
589 type_base_sptr u = look_through_decl_only_type(t.get_pointed_to_type());
592 hash_t v = u->hash_value();
594 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, u, v);
595 v = hashing::combine_hashes(v, type_base_hash(t));
596 v = hashing::combine_hashes(v, decl_hash(t));
597
599
600 return v;
601}
602
603/// Hashing function for a @ref pointer_type_def IR node.
604///
605/// @param t the @ref pointer_type_def IR node to hash.
606///
607/// @return the resulting hash value.
608hash_t
609pointer_type_def::hash::operator()(const pointer_type_def* t) const
610{
611 if (!t)
612 return 0;
613 return operator()(*t);
614}
615
616/// Hashing function for a @ref reference_type_def IR node.
617///
618/// @param t the @ref reference_type_def IR node to hash.
619///
620/// @return the resulting hash value.
621hash_t
622reference_type_def::hash::operator()(const reference_type_def& t) const
623{
624 MAYBE_RETURN_EARLY_IF_HASH_EXISTS(t);
625
626 type_base::hash hash_type_base;
627 decl_base::hash hash_decl;
628
630
631 type_base_sptr u = look_through_decl_only_type(t.get_pointed_to_type());
634 hash_t v = u->hash_value();
636 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, u, v);
637 v = hashing::combine_hashes(v, hash_type_base(t));
638 v = hashing::combine_hashes(v, hash_decl(t));
639 v = hashing::combine_hashes(v, hashing::hash(t.is_lvalue()));
640
642
643 return v;
644}
645
646/// Hashing function for a @ref reference_type_def IR node.
647///
648/// @param t the @ref reference_type_def IR node to hash.
649///
650/// @return the resulting hash value.
651hash_t
652reference_type_def::hash::operator()(const reference_type_def* t) const
653{
654 if (!t)
655 return 0;
656 return operator()(*t);
657}
658
659/// Hashing function for a @ref array_type_def::subrange_type IR node.
660///
661/// @param t the @ref array_type_def::subrange_type IR node to hash.
662///
663/// @return the resulting hash value.
664hash_t
665array_type_def::subrange_type::hash::operator()(const array_type_def::subrange_type& t) const
666{
668
672
674
675 return v;
676}
677
678/// Hashing function for a @ref array_type_def::subrange_type IR node.
679///
680/// @param t the @ref array_type_def::subrange_type IR node to hash.
681///
682/// @return the resulting hash value.
683hash_t
684array_type_def::subrange_type::hash::operator()(const array_type_def::subrange_type* s) const
685{
686 if (!s)
687 return 0;
688 return operator()(*s);
689}
690
691/// Hashing function for a @ref array_type_def IR node.
692///
693/// @param t the @ref array_type_def IR node to hash.
694///
695/// @return the resulting hash value.
696hash_t
697array_type_def::hash::operator()(const array_type_def& t) const
698{
699 MAYBE_RETURN_EARLY_IF_HASH_EXISTS(t);
700
701 type_base::hash hash_as_type_base;
702 decl_base::hash hash_as_decl_base;
703
705
706 hash_t v = hash_as_type_base(t), h = 0;
707 v = hashing::combine_hashes(v, hash_as_decl_base(t));
708
709 for (vector<array_type_def::subrange_sptr >::const_iterator i =
710 t.get_subranges().begin();
711 i != t.get_subranges().end();
712 ++i)
713 {
716 h = (*i)->hash_value();
718 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, *i, h);
719 v = hashing::combine_hashes(v, h);
720 }
721
722 type_base_sptr e = t.get_element_type();
725 h = e->hash_value();
727 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, e, h);
728 v = hashing::combine_hashes(v, h);
729
731
732 return v;
733}
734
735/// Hashing function for a @ref array_type_def IR node.
736///
737/// @param t the @ref array_type_def IR node to hash.
738///
739/// @return the resulting hash value.
740hash_t
741array_type_def::hash::operator()(const array_type_def* t) const
742{
743 if (!t)
744 return 0;
745 return operator()(*t);
746}
747
748/// Hashing function for a @ref ptr_to_mbr_type IR node.
749///
750/// @param t the @ref ptr_to_mbr_type IR node to hash.
751///
752/// @return the resulting hash value.
753hash_t
754ptr_to_mbr_type::hash::operator() (const ptr_to_mbr_type& t) const
755{
756 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
757
758 type_base::hash hash_as_type_base;
759 decl_base::hash hash_as_decl_base;
760
762
763 hash_t v = hash_as_type_base(t);
764 v = hashing::combine_hashes(v, hash_as_decl_base(t));
765 type_base_sptr e = t.get_member_type();
768 hash_t h = e->hash_value();
770 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, e, h);
771 v = hashing::combine_hashes(v, h);
772
773 e = t.get_containing_type();
776 h = e->hash_value();
778 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, t.get_containing_type(), h);
779 v = hashing::combine_hashes(v, h);
780
782
783 return v;
784}
785
786/// Hashing function for a @ref ptr_to_mbr_type IR node.
787///
788/// @param t the @ref ptr_to_mbr_type IR node to hash.
789///
790/// @return the resulting hash value.
791hash_t
792ptr_to_mbr_type::hash::operator() (const ptr_to_mbr_type* t) const
793{
794 if (!t)
795 return 0;
796 return operator()(*t);
797}
798
799/// Hashing function for a @ref ptr_to_mbr_type IR node.
800///
801/// @param t the @ref ptr_to_mbr_type IR node to hash.
802///
803/// @return the resulting hash value.
804hash_t
805ptr_to_mbr_type::hash::operator() (const ptr_to_mbr_type_sptr& t) const
806{return operator()(t.get());}
807
808/// Hashing function for a @ref enum_type_decl IR node.
809///
810/// @param t the @ref enum_type_decl IR node to hash.
811///
812/// @return the resulting hash value.
813hash_t
814enum_type_decl::hash::operator()(const enum_type_decl& t) const
815{
816 MAYBE_RETURN_EARLY_IF_HASH_EXISTS(t);
817
819 {
823 hash_t v = e->hash_value();
825 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, e, v);
826 return v;
827 }
828
829 decl_base::hash hash_as_decl;
830 type_base::hash hash_as_type;
831
833
834 hash_t v = hash_as_type(t);
835 v = hashing::combine_hashes(v, hash_as_decl(t));
836
837 type_base_sptr u = t.get_underlying_type();
840 hash_t h = u->hash_value();
842 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, u, h);
843 v = hashing::combine_hashes(v, h);
844
845 for (enum_type_decl::enumerators::const_iterator i =
846 t.get_enumerators().begin();
847 i != t.get_enumerators().end();
848 ++i)
849 {
850 v = hashing::combine_hashes(v, hashing::hash(i->get_name()));
851 v = hashing::combine_hashes(v, hashing::hash(i->get_value()));
852 }
853
855
856 return v;
857}
858
859/// Hashing function for a @ref enum_type_decl IR node.
860///
861/// @param t the @ref enum_type_decl IR node to hash.
862///
863/// @return the resulting hash value.
864hash_t
865enum_type_decl::hash::operator()(const enum_type_decl* t) const
866{
867 if (!t)
868 return 0;
869 return operator()(*t);
870}
871
872/// Hashing function for @ref function_type.
873///
874/// @param t the function type to hash.
875///
876/// @return the resulting hash value.
877hash_t
878function_type::hash::operator()(const function_type& t) const
879{
880 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
881
882 type_base::hash hash_as_type_base;
883
885
886 hash_t v = hash_as_type_base(t), h = 0;
887 type_base_sptr r = t.get_return_type();
890 h = r->hash_value();
892 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, r, h);
893 v = hashing::combine_hashes(v, h);
894
895 for (auto parm = t.get_first_parm();
896 parm != t.get_parameters().end();
897 ++parm)
898 {
899 type_base_sptr parm_type = (*parm)->get_type();
902 h = parm_type->hash_value();
903 hashing::set_hashing_state(*parm_type, s);
904 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, parm_type, h);
905 v = hashing::combine_hashes(v, h);
906 }
907
909
910 return v;
911}
912
913/// Hashing function for a pointer to @ref function_type.
914///
915/// @param t the pointer to @ref function_type to hash.
916///
917/// @return the resulting hash value.
918hash_t
919function_type::hash::operator()(const function_type* t) const
920{
921 if (!t)
922 return 0;
923 return operator()(*t);
924}
925
926/// Hashing function for a shared pointer to @ref function_type.
927///
928/// @param t the pointer to @ref function_type to hash.
929///
930/// @return the resulting hash value.
931hash_t
932function_type::hash::operator()(const function_type_sptr t) const
933{return operator()(t.get());}
934
935/// Hashing function for a @ref method_type IR node.
936///
937/// @param t the @ref method_type IR node to hash.
938///
939/// @return the resulting hash value.
940hash_t
941method_type::hash::operator()(const method_type& t) const
942{
943 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
944
945 type_base::hash hash_as_type_base;
946
948
949 hash_t v = hash_as_type_base(t), h = 0;
950 type_base_sptr r = t.get_return_type();
953 h = r->hash_value();
955 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, t.get_return_type(), h);
956 v = hashing::combine_hashes(v, h);
957
958 for (auto i = t.get_first_non_implicit_parm();
959 i != t.get_parameters().end();
960 ++i)
961 {
963 type_base_sptr ty = parm->get_type();
966 h = ty->hash_value();
968 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, ty, h);
969 v = hashing::combine_hashes(v, h);
970 }
971
973
974 return v;
975}
976
977/// Hashing function for a @ref method_type IR node.
978///
979/// @param t the @ref method_type IR node to hash.
980///
981/// @return the resulting hash value.
982hash_t
983method_type::hash::operator()(const method_type* t) const
984{return operator()(*t);}
985
986/// Hashing function for a @ref method_type IR node.
987///
988/// @param t the @ref method_type IR node to hash.
989///
990/// @return the resulting hash value.
991hash_t
992method_type::hash::operator()(const method_type_sptr t) const
993{return operator()(t.get());}
994
995/// Hashing function for a @ref member_base IR node.
996///
997/// @param t the @ref member_base IR node to hash.
998///
999/// @return the resulting hash value.
1000hash_t
1001member_base::hash::operator()(const member_base& m) const
1002{
1004}
1005
1006/// Hashing function for a @ref class_decl::base_spec IR node.
1007///
1008/// @param t the @ref class_decl::base_spec IR node to hash.
1009///
1010/// @return the resulting hash value.
1011hash_t
1012class_decl::base_spec::hash::operator()(const base_spec& t) const
1013{
1014 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
1015
1017
1018 member_base::hash hash_member;
1019
1020 hash_t v = hash_member(t), h = 0;;
1023 type_base_sptr b = t.get_base_class();
1026 h = b->hash_value();
1028 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, t.get_base_class(), h);
1029 v = hashing::combine_hashes(v, h);
1030
1032
1033 return v;
1034}
1035
1036/// Hashing function for a @ref class_decl::base_spec IR node.
1037///
1038/// @param t the @ref class_decl::base_spec IR node to hash.
1039///
1040/// @return the resulting hash value.
1041hash_t
1042class_decl::base_spec::hash::operator()(const base_spec* t) const
1043{
1044 if (!t)
1045 return 0;
1046 return operator()(*t);
1047}
1048
1049/// Compute a hash for a @ref class_or_union
1050///
1051/// @param t the class_or_union for which to compute the hash value.
1052///
1053/// @return the computed hash value.
1054hash_t
1055class_or_union::hash::operator()(const class_or_union& t) const
1056{
1057 // If the type is decl-only and now has a definition, then hash its
1058 // definition instead.
1059
1061 {
1062 class_or_union_sptr cou = is_class_or_union_type(t.get_definition_of_declaration());
1065 hash_t v = cou->hash_value();
1067 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, t.get_definition_of_declaration(), v);
1068 return v;
1069 }
1070
1071 type_base::hash hash_as_type_base;
1072 decl_base::hash hash_as_decl_base;
1073
1074 hash_t v = hash_as_type_base(t);
1075 v = hashing::combine_hashes(v, hash_as_decl_base(t));
1076
1077 // Hash data members.
1078 type_base_sptr ty;
1079 for (auto d = t.get_non_static_data_members().begin();
1080 d != t.get_non_static_data_members().end();
1081 ++d)
1082 {
1083 ty = (*d)->get_type();
1086 hash_t h = ty->hash_value();
1088 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, ty, h);
1089 v = hashing::combine_hashes(v, h);
1090 v = hashing::combine_hashes(v, hashing::hash((*d)->get_name()));
1091 }
1092
1093 return v;
1094};
1095
1096/// Compute a hash for a @ref class_or_union
1097///
1098/// @param t the class_or_union for which to compute the hash value.
1099///
1100/// @return the computed hash value.
1101hash_t
1102class_or_union::hash::operator()(const class_or_union *t) const
1103{return t ? operator()(*t) : 0;}
1104
1105/// Compute a hash for a @ref class_decl
1106///
1107/// @param t the class_decl for which to compute the hash value.
1108///
1109/// @return the computed hash value.
1110hash_t
1111class_decl::hash::operator()(const class_decl& t) const
1112{
1113 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
1114
1115 // If the type is decl-only and now has a definition, then hash its
1116 // definition instead.
1117
1119 {
1123 hash_t v = c->hash_value();
1125 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, c, v);
1126 return v;
1127 }
1128
1130
1131 class_or_union::hash hash_as_class_or_union;
1132
1133 hash_t v = hash_as_class_or_union(t);
1134
1135 // Hash bases.
1136 for (auto b = t.get_base_specifiers().begin();
1137 b != t.get_base_specifiers().end();
1138 ++b)
1139 {
1142 hash_t h = (*b)->hash_value();
1144 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, *b, h);
1145 v = hashing::combine_hashes(v, h);
1146 }
1147
1148#if 0
1149 // Do not hash (virtual) member functions because in C++ at least,
1150 // due to the function cloning used to implement destructors (and
1151 // maybe other functions in the future) comparing two sets of
1152 // virtual destructors is a bit more involved than what we could
1153 // naively do with by just hashing the virtual member functions.
1154 // You can look at the overload of the equals function for
1155 // class_decl, in abg-ir.cc to see the dance involved in comparing
1156 // virtual member functions. Maybe in the future we can come up
1157 // with a clever way to hash these. For now, let's rely on
1158 // structural comparison to tell the virtual member functions part
1159 // of classes appart.
1160
1161 // If we were to hash virtual member functions naively, please find
1162 // below what it would look like. Note that it doesn't work in
1163 // practise as it creates spurious self-comparison errors. You
1164 // might want to test it on this command and see for yourself:
1165 //
1166 // fedabipkgdiff --self-compare --from fc37 gcc-gnat
1167
1168 // Hash virtual member functions.
1169
1170 // TODO: hash the linkage names of the virtual member functions too.
1171 const_cast<class_decl&>(t).sort_virtual_mem_fns();
1172 for (const auto& method : t.get_virtual_mem_fns())
1173 {
1174 ssize_t voffset = get_member_function_vtable_offset(method);
1175 v = hashing::combine_hashes(v, hashing::hash(voffset));
1176 method_type_sptr method_type = method->get_type();
1178 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, method_type, h);
1179 v = hashing::combine_hashes(v, h);
1180 }
1181#endif
1182
1184
1185 return v;
1186}
1187
1188/// Compute a hash for a @ref class_decl
1189///
1190/// @param t the class_decl for which to compute the hash value.
1191///
1192/// @return the computed hash value.
1193hash_t
1194class_decl::hash::operator()(const class_decl* t) const
1195{return t ? operator()(*t) : 0;}
1196
1197/// Hashing function for a @ref union_decl IR node.
1198///
1199/// @param t the @ref union_decl IR node to hash.
1200///
1201/// @return the resulting hash value.
1202hash_t
1203union_decl::hash::operator()(const union_decl& t) const
1204{
1205 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
1206
1207 // If the type is decl-only and now has a definition, then hash its
1208 // definition instead.
1209
1211 {
1212 union_decl_sptr u = is_union_type(t.get_definition_of_declaration());
1215 hash_t v = u->hash_value();
1217 MAYBE_FLAG_TYPE_AS_RECURSIVE(t, u, v);
1218 return v;
1219 }
1220
1222
1223 class_or_union::hash hash_as_class_or_union;
1224
1225 hash_t v = hash_as_class_or_union(t);
1226
1228
1229 return v;
1230}
1231
1232/// Hashing function for a @ref union_decl IR node.
1233///
1234/// @param t the @ref union_decl IR node to hash.
1235///
1236/// @return the resulting hash value.
1237hash_t
1238union_decl::hash::operator()(const union_decl*t) const
1239{
1240 if (!t)
1241 return 0;
1242 return operator()(*t);
1243}
1244}//end namespace abigail
#define ABG_ASSERT(cond)
This is a wrapper around the 'assert' glibc call. It allows for its argument to have side effects,...
Definition: abg-fwd.h:1737
This contains the private implementation of the suppression engine of libabigail.
Types of the main internal representation of libabigail.
The abstraction of an interned string.
Abstraction for an array range type, like in Ada, or just for an array dimension like in C or C++.
Definition: abg-ir.h:2574
int64_t get_upper_bound() const
Getter of the upper bound of the subrange type.
Definition: abg-ir.cc:19340
int64_t get_lower_bound() const
Getter of the lower bound of the subrange type.
Definition: abg-ir.cc:19347
The abstraction of an array type.
Definition: abg-ir.h:2548
const type_base_sptr get_element_type() const
Getter of the type of an array element.
Definition: abg-ir.cc:19988
const std::vector< subrange_sptr > & get_subranges() const
Get the array's subranges.
Definition: abg-ir.cc:20147
Abstraction of a base specifier in a class declaration.
Definition: abg-ir.h:4362
class_decl_sptr get_base_class() const
Get the base class referred to by the current base class specifier.
Definition: abg-ir.cc:25287
bool get_is_virtual() const
Getter of the "is-virtual" proprerty of the base class specifier.
Definition: abg-ir.cc:25294
long get_offset_in_bits() const
Getter of the offset of the base.
Definition: abg-ir.cc:25301
Abstracts a class declaration.
Definition: abg-ir.h:4175
const base_specs & get_base_specifiers() const
Get the base specifiers for this class.
Definition: abg-ir.cc:25108
const member_functions & get_virtual_mem_fns() const
Get the virtual member functions of this class.
Definition: abg-ir.cc:25134
The base type of class_decl and union_decl.
Definition: abg-ir.h:3977
const data_members & get_non_static_data_members() const
Get the non-static data members of this class_or_union.
Definition: abg-ir.cc:24242
The base type of all declarations.
Definition: abg-ir.h:1585
virtual const interned_string & get_name() const
Getter for the name of the current decl.
Definition: abg-ir.cc:4811
bool get_is_anonymous() const
Test if the current declaration is anonymous.
Definition: abg-ir.cc:4668
const decl_base_sptr get_definition_of_declaration() const
If this decl_base is declaration-only, get its definition, if any.
Definition: abg-ir.cc:4973
bool get_is_declaration_only() const
Test if a decl_base is a declaration-only decl.
Definition: abg-ir.cc:4996
Abstracts a declaration for an enum type.
Definition: abg-ir.h:2785
const enumerators & get_enumerators() const
Definition: abg-ir.cc:20233
type_base_sptr get_underlying_type() const
Return the underlying type of the enum.
Definition: abg-ir.cc:20228
shared_ptr< parameter > parameter_sptr
Convenience typedef for a shared pointer on a function_decl::parameter.
Definition: abg-ir.h:3187
Abstraction of a function type.
Definition: abg-ir.h:3420
parameters::const_iterator get_first_parm() const
Get the first parameter of the function.
Definition: abg-ir.cc:22257
type_base_sptr get_return_type() const
Getter for the return type of the current instance of function_type.
Definition: abg-ir.cc:21952
parameters::const_iterator get_first_non_implicit_parm() const
Get the first parameter of the function.
Definition: abg-ir.cc:22235
const parameters & get_parameters() const
Getter for the set of parameters of the current intance of function_type.
Definition: abg-ir.cc:21969
The base class for member types, data members and member functions. Its purpose is mainly to carry th...
Definition: abg-ir.h:3839
access_specifier get_access_specifier() const
Getter for the access specifier of this member.
Definition: abg-ir.h:3859
Abstracts the type of a class member function.
Definition: abg-ir.h:3506
The abstraction of a pointer type.
Definition: abg-ir.h:2350
const type_base_sptr get_pointed_to_type() const
Getter of the pointed-to type.
Definition: abg-ir.cc:18168
The abstraction of a pointer-to-member type.
Definition: abg-ir.h:2485
const type_base_sptr & get_containing_type() const
Getter of the type containing the member pointed-to by the current ptr_to_mbr_type.
Definition: abg-ir.cc:18895
const type_base_sptr & get_member_type() const
Getter of the member type of the current ptr_to_mbr_type.
Definition: abg-ir.cc:18886
The abstraction of a qualified type.
Definition: abg-ir.h:2236
CV get_cv_quals() const
Getter of the const/volatile qualifier bit field.
Definition: abg-ir.cc:17804
type_base_sptr get_underlying_type() const
Getter of the underlying type.
Definition: abg-ir.cc:17823
Abstracts a reference type.
Definition: abg-ir.h:2416
An abstraction helper for type declarations.
Definition: abg-ir.h:2003
virtual size_t get_size_in_bits() const
Getter for the size of the type.
Definition: abg-ir.cc:16410
virtual size_t get_alignment_in_bits() const
Getter for the alignment of the type.
Definition: abg-ir.cc:16424
A basic type declaration that introduces no scope.
Definition: abg-ir.h:2118
The base class of both types and declarations.
Definition: abg-ir.h:1406
The abstraction of a typedef declaration.
Definition: abg-ir.h:2935
type_base_sptr get_underlying_type() const
Getter of the underlying type of the typedef.
Definition: abg-ir.cc:21194
Abstracts a union type declaration.
Definition: abg-ir.h:4420
hash_t combine_hashes(hash_t val1, hash_t val2)
Combine two hash values to produce a third hash value.
Definition: abg-hash.cc:172
hashing::hashing_state get_hashing_state(const type_or_decl_base &tod)
Get the hashing state of an IR node.
Definition: abg-hash.cc:261
void set_hashing_state(const type_or_decl_base &tod, hashing::hashing_state s)
Set the hashing state of an IR node.
Definition: abg-hash.cc:280
hash_t hash(uint64_t v, uint64_t seed)
Hash an integer value and combine it with a hash previously computed.
Definition: abg-hash.cc:196
hashing_state
Enumeration of the different hashing states of an IR node being hashed.
Definition: abg-hash.h:25
@ HASHING_STARTED_STATE
Hashing started but is not yet finished.
Definition: abg-hash.h:34
@ HASHING_SUBTYPE_STATE
Hashing a sub-type while hashing another type.
Definition: abg-hash.h:55
@ HASHING_NOT_DONE_STATE
No hashing has been done/started.
Definition: abg-hash.h:27
bool deserialize_hash(const string &input, uint64_t &hash)
Read a string of characters representing a string of hexadecimal digits which itself represents a has...
Definition: abg-hash.cc:99
bool serialize_hash(uint64_t hash, string &output)
Serialiaze a hash value computed using the XH64 algorithm (from the xxhash project) into a string of ...
Definition: abg-hash.cc:138
uint32_t fnv_hash(const std::string &str)
Compute a stable string hash.
Definition: abg-hash.cc:241
bool is_recursive_artefact(const type_or_decl_base &t)
Test if an artifact is recursive.
Definition: abg-hash.cc:302
The namespace of the internal representation of ABI artifacts like types and decls.
shared_ptr< method_type > method_type_sptr
Convenience typedef for shared pointer to method_type.
Definition: abg-fwd.h:221
bool get_member_is_static(const decl_base &d)
Gets a flag saying if a class member is static or not.
Definition: abg-ir.cc:5575
ssize_t get_member_function_vtable_offset(const function_decl &f)
Get the vtable offset of a member function.
Definition: abg-ir.cc:6578
bool is_class_type(const type_or_decl_base &t)
Test whether a type is a class.
Definition: abg-ir.cc:11091
class_or_union * is_class_or_union_type(const type_or_decl_base *t)
Test if a type is a class_or_union.
Definition: abg-ir.cc:11322
type_base * look_through_decl_only_type(type_base *t)
If a type is is decl-only, then get its definition. Otherwise, just return the initial type.
Definition: abg-ir.cc:11953
shared_ptr< class_decl > class_decl_sptr
Convenience typedef for a shared pointer on a class_decl.
Definition: abg-fwd.h:193
decl_base_sptr look_through_decl_only(const decl_base &d)
If a decl is decl-only get its definition. Otherwise, just return nil.
Definition: abg-ir.cc:11893
shared_ptr< function_type > function_type_sptr
Convenience typedef for a shared pointer on a function_type.
Definition: abg-fwd.h:210
const enum_type_decl * is_enum_type(const type_or_decl_base *d)
Test if a decl is an enum_type_decl.
Definition: abg-ir.cc:11041
shared_ptr< ptr_to_mbr_type > ptr_to_mbr_type_sptr
Convenience typedef for a shared pointer to a ptr_to_mbr_type.
Definition: abg-fwd.h:239
decl_base * is_decl(const type_or_decl_base *d)
Test if an ABI artifact is a declaration.
Definition: abg-ir.cc:10705
access_specifier get_member_access_specifier(const decl_base &d)
Gets the access specifier for a class member.
Definition: abg-ir.cc:5515
shared_ptr< enum_type_decl > enum_type_decl_sptr
Convenience typedef for shared pointer to a enum_type_decl.
Definition: abg-fwd.h:175
bool is_union_type(const type_or_decl_base &t)
Test if a type is a union_decl.
Definition: abg-ir.cc:11371
bool is_member_decl(const decl_base_sptr d)
Tests if a declaration is a class member.
Definition: abg-ir.cc:5417
hash_t do_hash_value(const T &tod)
Compute the hash value of an IR node and return it.
Definition: abg-ir-priv.h:340
Toplevel namespace for libabigail.
Hasher for the class_or_union type.
Definition: abg-hash.h:250
The hashing functor for member_base.
Definition: abg-hash.h:243
Hash functor for instances of type_base.
Definition: abg-hash.h:111