libabigail
Loading...
Searching...
No Matches
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-2026 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/// Add a state to the hashing state of a given IR node.
294///
295/// @param tod the type of decl IR node to set the hashing state for.
296///
297/// @param s the new state to add to the hashing state of the node.
298void
308
309/// Remove a state to the hashing state of a given IR node.
310///
311/// @param tod the type of decl IR node to set the hashing state for.
312///
313/// @param s the new state to add to the hashing state of the node.
314void
323
324}//end namespace hashing
325
326using std::list;
327using std::vector;
328
329using namespace abigail::ir;
330
331namespace ir
332{
333
334/// Compute (or get) the hash of a sub-type of the type for which we
335/// are currently computing the hash. It does so by preventing
336/// infinite loops.
337///
338/// The function detects if the sub-type is currently already being
339/// walked for hash computation; if it's the case then it returns an
340/// empty hash to prevent infinite looping. Otherwise it computes the
341/// hash of the sub-type.
342///
343/// @param t the sub-type node to consider.
344///
345/// @return the resulting hash. It can be empty to prevent infinite
346/// looping.
347///
348hash_t
369
370/// Compute (or get) the hash of a sub-type of the type for which we
371/// are currently computing the hash. It does so by preventing
372/// infinite loops.
373///
374/// The function detects if the sub-type is currently already being
375/// walked for hash computation; if it's the case then it returns an
376/// empty hash to prevent infinite looping. Otherwise it computes the
377/// hash of the sub-type.
378///
379/// @param t the sub-type node to consider.
380///
381/// @return the resulting hash. It can be empty to prevent infinite
382/// looping.
383///
384hash_t
389
390}// end namespace ir
391
392// See forward declarations in abg-ir.h.
393
394// Definitions.
395
396#define MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(type) \
397 do \
398 { \
399 if (hashing::get_hashing_state(type) == hashing::HASHING_FINISHED_STATE) \
400 return peek_hash_value(type); \
401 else if (hashing::get_hashing_state(type) & hashing::HASHING_CYCLED_TYPE_STATE) \
402 return hash_t(); \
403 } \
404 while(false)
405
406#if 0
407/// This is for debugging purposes.
408///
409/// It emits the hash value of an artifact, if its DWARF offset is
410/// among a set of given DWARF offset numbers.
411///
412/// @param artifact the artifact to consider.
413///
414/// @param native_offsets the set of DWARF offsets the artifact should
415/// have to for its hash value to be emitted.
416///
417/// @param artifact_number this is an arbitrary number provided by the
418/// caller to identify the artifact in the output.
419///
420/// @param h the hash value of the artifact to emit.
421void
422debug_hash_value(const type_or_decl_base& artifact,
423 std::unordered_set<uint32_t> native_offsets,
424 int artifact_number,
425 hash_t h)
426{
427 if (offset_t o = artifact.get_native_offset())
428 if (native_offsets.find(*o) != native_offsets.end())
429 {
430 std::cerr << "hash of '"
431 << artifact.get_pretty_representation()
432 << "'/"
433 << artifact_number
434 << " at offset "
435 << std::hex
436 << *o
437 << std::dec
438 << " is '"
439 << std::hex
440 << *h
441 << std::dec
442 << std::endl;
443 }
444}
445#endif
446
447/// Hash a type as a basic type having a name and size attributes.
448///
449/// This hashing function takes into account the name of the type as
450/// as its size. The name taken into account is the same name that is
451/// taken into account by the type canonicalization process in
452/// type_base::get_canonical_type_for.
453///
454/// @param t the type to hash.
455///
456/// @return the hash value.
457static hash_t
458hash_as_basic_type(const abigail::ir::type_base& t)
459{
460 type_base::hash hash_as_type;
461 decl_base::hash hash_as_decl;
462 qualified_type_def::hash hash_as_qualified;
463
464 hash_t h = hash_as_type(t);
465 if (auto q = is_qualified_type(&t))
466 h = hashing::combine_hashes(h, hash_as_qualified(*q));
467 else if (auto d = is_decl(&t))
468 h = hashing::combine_hashes(h, hash_as_decl(*d));
469
470 return h;
471}
472
473/// Hash a type as a basic type having a name and size attributes.
474///
475/// This hashing function takes into account the name of the type as
476/// well as its size. The name taken into account is the same name
477/// that is taken into account by the type canonicalization process in
478/// type_base::get_canonical_type_for.
479///
480/// @param t the type to hash.
481///
482/// @return the hash value.
483static hash_t
484hash_as_basic_type(const type_base_sptr t)
485{
486 if (!t)
487 return hash_t();
488 return hash_as_basic_type(*t);
489}
490
491/// Depending on the kind of the type, hash it as a pointer, a
492/// reference or a typedef.
493///
494/// @param t the type to hash.
495///
496/// @return the hash value.
497static hash_t
498hash_as_ptr_ref_or_typedef_type(const type_base* t)
499{
500 reference_type_def::hash hash_reference;
501 pointer_type_def::hash hash_pointer;
502 typedef_decl::hash hash_typedef;
503 hash_t h;
504
505 if (auto p = is_pointer_type(t))
506 h = hash_pointer(*p);
507 else if (auto r = is_reference_type(t))
508 h = hash_reference(*r);
509 else if (auto ty = is_typedef(t))
510 h = hash_typedef(*ty);
511
512 return h;
513}
514
515/// Hash a given type as a basic type, then depending on its type,
516/// hash it further as a pointer, reference, or typedef type.
517///
518/// @param t the type to consider.
519///
520/// @return the resulting hash value.
521static hash_t
522hash_as_basic_then_ptr_ref_or_typedef_type(const type_base* t)
523{
524 hash_t h = hash_as_basic_type(*t);
525 h = hashing::combine_hashes(h, hash_as_ptr_ref_or_typedef_type(t));
526 return h;
527}
528
529/// Hash a given type as a basic type, then depending on its type,
530/// hash it further as a pointer, reference, or typedef type.
531///
532/// @param t the type to consider.
533///
534/// @return the resulting hash value.
535static hash_t
536hash_as_basic_then_ptr_ref_or_typedef_type(const type_base_sptr t)
537{return hash_as_basic_then_ptr_ref_or_typedef_type(t.get());}
538
539/// The hashing functor for using instances of @ref type_or_decl_base
540/// as values in a hash map or set.
541
542/// Hash function for an instance of @ref type_base.
543///
544/// @param t the type to hash.
545///
546/// @return the type value.
547hash_t
554
555/// Hash function for an instance of @ref type_base.
556///
557/// @param t the type to hash.
558///
559/// @return the type value.
560hash_t
562{return operator()(*t);}
563
564/// Hash function for an instance of @ref type_base.
565///
566/// @param t the type to hash.
567///
568/// @return the hash value.
569hash_t
570type_base::hash::operator()(const type_base_sptr t) const
571{return operator()(*t);}
572
573/// Hash function for an instance of @ref decl_base.
574///
575/// @param d the decl to hash.
576///
577/// @return the hash value.
578hash_t
580{
581 hash_t v = 0;
582
583 string repr;
584
585 // Make sure the representation doesn't make the difference between
586 // a struct and a class so that we have the same hash for both.
587 repr = d.get_cached_pretty_representation(/*internal=*/true);
588
589 v = hashing::hash(repr);
590
591 if (is_member_decl(d))
593
594 return v;
595}
596
597/// Hash function for an instance of @ref decl_base.
598///
599/// @param d the decl to hash.
600///
601/// @return the hash value.
602hash_t
604{
605 if (!d)
606 return 0;
607 return operator()(*d);
608}
609
610/// Hashing function for a @ref type_decl IR node.
611///
612/// @param t the @ref type_decl IR node t hash.
613///
614/// @return the resulting hash value.
615hash_t
617{
618 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
619
620 decl_base::hash decl_hash;
621 type_base::hash type_hash;
622
624
625 hash_t v = decl_hash(t);
626 v = hashing::combine_hashes(v, type_hash(t));
627
629
630 t.set_hash_value(v);
631
632 return v;
633}
634
635/// Hashing function for a @ref type_decl IR node.
636///
637/// @param t the @ref type_decl IR node to hash.
638///
639/// @return the resulting hash value.
640hash_t
642{
643 if (!t)
644 return 0;
645 return operator()(*t);
646}
647
648/// Hashing function for a @ref typedef_decl IR node.
649///
650/// @param t the @ref typedef_decl IR node to hash
651///
652/// @return the resulting hash value.
653hash_t
655{
656 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
657
659
661 (const_cast<type_base*>(peel_typedef_type(&t)));
662 hash_t h = hash_as_basic_then_ptr_ref_or_typedef_type(is_type(u));
663
665
666 return h;
667}
668
669/// Hashing function for a @ref typedef_decl IR node.
670///
671/// @param t the @ref typedef_decl IR node to hash
672///
673/// @return the resulting hash value.
674hash_t
676{
677 if (!t)
678 return 0;
679 return operator()(*t);
680}
681
682/// Hashing function for a @ref qualified_type_def IR node.
683///
684/// @param t the @ref qualified_type_def IR node to hash.
685///
686/// @return the resulting hash value.
687hash_t
689{
690 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
691
692 type_base::hash type_hash;
693 decl_base::hash decl_hash;
694
696
697 hash_t v = type_hash(t);
699 type_base_sptr u = look_through_decl_only_type(t.get_underlying_type());
700 v = hashing::combine_hashes(v, hash_as_basic_then_ptr_ref_or_typedef_type(u));
701 if (auto d = is_decl(u))
702 v = hashing::combine_hashes(v, decl_hash(*d));
703
705
706 return v;
707}
708
709/// Hashing function for a @ref qualified_type_def IR node.
710///
711/// @param t the @ref qualified_type_def IR node to hash.
712///
713/// @return the resulting hash value.
714hash_t
716{
717 if (!t)
718 return 0;
719 return operator()(*t);
720}
721
722
723/// Hashing function for a @ref pointer_type_def IR node.
724///
725/// @param t the @ref pointer_type_def IR node to hash.
726///
727/// @return the resulting hash value.
728hash_t
730{
731 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
732
733 type_base::hash type_base_hash;
734 decl_base::hash decl_hash;
735
737
738 hash_t v = type_base_hash(t);
739 v = hashing::combine_hashes(v, decl_hash(t));
740 type_base_sptr u = look_through_decl_only_type(t.get_pointed_to_type());
741 if (auto d = is_decl(u))
742 v = hashing::combine_hashes(v, decl_hash(*d));
743
744
746
747 return v;
748}
749
750/// Hashing function for a @ref pointer_type_def IR node.
751///
752/// @param t the @ref pointer_type_def IR node to hash.
753///
754/// @return the resulting hash value.
755hash_t
757{
758 if (!t)
759 return 0;
760 return operator()(*t);
761}
762
763/// Hashing function for a @ref reference_type_def IR node.
764///
765/// @param t the @ref reference_type_def IR node to hash.
766///
767/// @return the resulting hash value.
768hash_t
770{
771 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
772
774
775 hash_t v = hash_as_basic_type(t);
776 v = hashing::combine_hashes(v, hashing::hash(t.is_lvalue()));
777 type_base_sptr u = look_through_decl_only_type(t.get_pointed_to_type());
778 v = hashing::combine_hashes(v, hash_as_basic_type(u));
779
781
782 return v;
783}
784
785/// Hashing function for a @ref reference_type_def IR node.
786///
787/// @param t the @ref reference_type_def IR node to hash.
788///
789/// @return the resulting hash value.
790hash_t
792{
793 if (!t)
794 return 0;
795 return operator()(*t);
796}
797
798/// Hashing function for a @ref array_type_def::subrange_type IR node.
799///
800/// @param t the @ref array_type_def::subrange_type IR node to hash.
801///
802/// @return the resulting hash value.
803hash_t
804array_type_def::subrange_type::hash::operator()(const array_type_def::subrange_type& t) const
805{
807
811
813
814 return v;
815}
816
817/// Hashing function for a @ref array_type_def::subrange_type IR node.
818///
819/// @param t the @ref array_type_def::subrange_type IR node to hash.
820///
821/// @return the resulting hash value.
822hash_t
823array_type_def::subrange_type::hash::operator()(const array_type_def::subrange_type* s) const
824{
825 if (!s)
826 return 0;
827 return operator()(*s);
828}
829
830/// Hashing function for a @ref array_type_def IR node.
831///
832/// @param t the @ref array_type_def IR node to hash.
833///
834/// @return the resulting hash value.
835hash_t
837{
838 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
839
840 type_base::hash hash_as_type_base;
841 decl_base::hash hash_as_decl_base;
842
844
845 hash_t v = hash_as_type_base(t), h = 0;
846 v = hashing::combine_hashes(v, hash_as_decl_base(t));
847
848 for (vector<array_type_def::subrange_sptr >::const_iterator i =
849 t.get_subranges().begin();
850 i != t.get_subranges().end();
851 ++i)
852 {
853 auto type = *i;
854 h = hash_as_type_base(*type);
855 v = hashing::combine_hashes(v, h);
856 v = hashing::combine_hashes(v, hash_as_decl_base(*type));
857 }
858
859 type_base_sptr e = look_through_decl_only_type(t.get_element_type());
860
861 if (auto d = is_decl(e))
862 {
863 v = hashing::combine_hashes(v, hash_as_decl_base(*d));
864 v = hashing::combine_hashes(v, hash_as_type_base(*e));
865 }
866
868
869 return v;
870}
871
872/// Hashing function for a @ref array_type_def IR node.
873///
874/// @param t the @ref array_type_def IR node to hash.
875///
876/// @return the resulting hash value.
877hash_t
879{
880 if (!t)
881 return 0;
882 return operator()(*t);
883}
884
885/// Hashing function for a @ref ptr_to_mbr_type IR node.
886///
887/// @param t the @ref ptr_to_mbr_type IR node to hash.
888///
889/// @return the resulting hash value.
890hash_t
892{
893 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
894
895 type_base::hash hash_as_type_base;
896 decl_base::hash hash_as_decl_base;
897
899
900 hash_t v = hash_as_type_base(t);
901 v = hashing::combine_hashes(v, hash_as_decl_base(t));
902 type_base_sptr e = look_through_decl_only_type(t.get_member_type());
903
904 hash_t h = hash_as_basic_then_ptr_ref_or_typedef_type(e);
905 v = hashing::combine_hashes(v, h);
906
908
909 h = hash_as_basic_then_ptr_ref_or_typedef_type(e);
910 v = hashing::combine_hashes(v, h);
911
913
914 return v;
915}
916
917/// Hashing function for a @ref ptr_to_mbr_type IR node.
918///
919/// @param t the @ref ptr_to_mbr_type IR node to hash.
920///
921/// @return the resulting hash value.
922hash_t
924{
925 if (!t)
926 return 0;
927 return operator()(*t);
928}
929
930/// Hashing function for a @ref ptr_to_mbr_type IR node.
931///
932/// @param t the @ref ptr_to_mbr_type IR node to hash.
933///
934/// @return the resulting hash value.
935hash_t
937{return operator()(t.get());}
938
939/// Hashing function for a @ref enum_type_decl IR node.
940///
941/// @param t the @ref enum_type_decl IR node to hash.
942///
943/// @return the resulting hash value.
944hash_t
946{
947 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
948
950 {
952
953 hash_t v = hash_as_basic_then_ptr_ref_or_typedef_type(e);
954 return v;
955 }
956
957 decl_base::hash hash_as_decl;
958 type_base::hash hash_as_type;
959
961
962 hash_t v = hash_as_type(t);
963 v = hashing::combine_hashes(v, hash_as_decl(t));
964
965 type_base_sptr u = look_through_decl_only_type(t.get_underlying_type());
966
967 hash_t h = hash_as_basic_then_ptr_ref_or_typedef_type(u);
968 v = hashing::combine_hashes(v, h);
969
970 for (enum_type_decl::enumerators::const_iterator i =
971 t.get_enumerators().begin();
972 i != t.get_enumerators().end();
973 ++i)
974 {
975 v = hashing::combine_hashes(v, hashing::hash(i->get_name()));
976 v = hashing::combine_hashes(v, hashing::hash(i->get_value()));
977 }
978
980
981 return v;
982}
983
984/// Hashing function for a @ref enum_type_decl IR node.
985///
986/// @param t the @ref enum_type_decl IR node to hash.
987///
988/// @return the resulting hash value.
989hash_t
991{
992 if (!t)
993 return 0;
994 return operator()(*t);
995}
996
997/// Hashing function for @ref function_type.
998///
999/// @param t the function type to hash.
1000///
1001/// @return the resulting hash value.
1002hash_t
1004{
1005 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
1006
1007 add_to_hashing_state(t, hashing::HASHING_STARTED_STATE);
1008
1009 hash_t h = hash_as_basic_type(t);
1010 type_base_sptr r = look_through_decl_only_type(t.get_return_type());
1011
1012 h = hashing::combine_hashes(h, hash_as_basic_then_ptr_ref_or_typedef_type(r));
1013
1014 for (auto parm : t.get_parameters())
1015 {
1016 type_base_sptr type = look_through_decl_only_type(parm->get_type());
1018 (h, hash_as_basic_then_ptr_ref_or_typedef_type(type));
1019 }
1020
1022
1023 return h;
1024}
1025
1026/// Hashing function for a pointer to @ref function_type.
1027///
1028/// @param t the pointer to @ref function_type to hash.
1029///
1030/// @return the resulting hash value.
1031hash_t
1033{
1034 if (!t)
1035 return 0;
1036 return operator()(*t);
1037}
1038
1039/// Hashing function for a shared pointer to @ref function_type.
1040///
1041/// @param t the pointer to @ref function_type to hash.
1042///
1043/// @return the resulting hash value.
1044hash_t
1046{return operator()(t.get());}
1047
1048/// Hashing function for a @ref method_type IR node.
1049///
1050/// @param t the @ref method_type IR node to hash.
1051///
1052/// @return the resulting hash value.
1053hash_t
1055{
1056 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
1057
1058 add_to_hashing_state(t, hashing::HASHING_STARTED_STATE);
1059
1060 hash_t v = hash_as_basic_type(t);
1061 type_base_sptr r = look_through_decl_only_type(t.get_return_type());
1062 v = hashing::combine_hashes(v, hash_as_basic_then_ptr_ref_or_typedef_type(r));
1063
1064 bool c = t.get_is_const();
1066
1067 // We are not hashing the class type. Rather, we are hashing it
1068 // indirectly by hashing the first parameter which should be the
1069 // implicit "this" pointer for types of non-static method.
1070 //
1071 // Doing this allows not taking into account the class type for
1072 // method_type of static methods, while taking it into account for
1073 // non-static methods.
1074
1075 for (auto parm : t.get_parameters())
1076 {
1077 type_base_sptr ty = look_through_decl_only_type(parm->get_type());
1079 (v, hash_as_basic_then_ptr_ref_or_typedef_type(ty));
1080 }
1081
1083
1084 return v;
1085}
1086
1087/// Hashing function for a @ref method_type IR node.
1088///
1089/// @param t the @ref method_type IR node to hash.
1090///
1091/// @return the resulting hash value.
1092hash_t
1094{return operator()(*t);}
1095
1096/// Hashing function for a @ref method_type IR node.
1097///
1098/// @param t the @ref method_type IR node to hash.
1099///
1100/// @return the resulting hash value.
1101hash_t
1103{return operator()(t.get());}
1104
1105/// Hashing function for a @ref member_base IR node.
1106///
1107/// @param t the @ref member_base IR node to hash.
1108///
1109/// @return the resulting hash value.
1110hash_t
1115
1116/// Hashing function for a @ref class_decl::base_spec IR node.
1117///
1118/// @param t the @ref class_decl::base_spec IR node to hash.
1119///
1120/// @return the resulting hash value.
1121hash_t
1123{
1124 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
1125
1126 add_to_hashing_state(t, hashing::HASHING_STARTED_STATE);
1127
1128 member_base::hash hash_member;
1129
1130 hash_t v = hash_member(t), h = 0;;
1133 type_base_sptr b = look_through_decl_only_type(t.get_base_class());
1134
1135 h = hash_as_basic_then_ptr_ref_or_typedef_type(b);
1136 v = hashing::combine_hashes(v, h);
1137
1139
1140 return v;
1141}
1142
1143/// Hashing function for a @ref class_decl::base_spec IR node.
1144///
1145/// @param t the @ref class_decl::base_spec IR node to hash.
1146///
1147/// @return the resulting hash value.
1148hash_t
1150{
1151 if (!t)
1152 return 0;
1153 return operator()(*t);
1154}
1155
1156/// Compute a hash for a @ref class_or_union
1157///
1158/// @param t the class_or_union for which to compute the hash value.
1159///
1160/// @return the computed hash value.
1161hash_t
1163{
1164 // If the type is decl-only and now has a definition, then hash its
1165 // definition instead.
1166
1168 {
1169 class_or_union_sptr cou = is_class_or_union_type(look_through_decl_only_class(t));
1170 hash_t v = operator()(*cou);
1171 return v;
1172 }
1173
1174 type_base::hash hash_as_type_base;
1175 decl_base::hash hash_as_decl_base;
1176
1177 hash_t v = hash_as_type_base(t);
1178 v = hashing::combine_hashes(v, hash_as_decl_base(t));
1179
1180 // Hash data members.
1181 type_base_sptr ty;
1182 for (auto d = t.get_non_static_data_members().begin();
1183 d != t.get_non_static_data_members().end();
1184 ++d)
1185 {
1186 ty = look_through_decl_only_type((*d)->get_type());
1187 hash_t h = hash_as_basic_type(ty);
1188 v = hashing::combine_hashes(v, h);
1189 v = hashing::combine_hashes(v, hashing::hash((*d)->get_name()));
1190 }
1191
1192 return v;
1193};
1194
1195/// Compute a hash for a @ref class_or_union
1196///
1197/// @param t the class_or_union for which to compute the hash value.
1198///
1199/// @return the computed hash value.
1200hash_t
1202{return t ? operator()(*t) : 0;}
1203
1204/// Compute a hash for a @ref class_decl
1205///
1206/// @param t the class_decl for which to compute the hash value.
1207///
1208/// @return the computed hash value.
1209hash_t
1211{
1212 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
1213
1214 // If the type is decl-only and now has a definition, then hash its
1215 // definition instead.
1216
1218 {
1220 hash_t v = operator()(*c);
1222 return v;
1223 }
1224
1225 add_to_hashing_state(t, hashing::HASHING_STARTED_STATE);
1226
1227 class_or_union::hash hash_as_class_or_union;
1228
1229 hash_t v = hash_as_class_or_union(t);
1230
1231 hash_t h;
1232 // Hash bases.
1233 for (auto b : t.get_base_specifiers())
1234 {
1235 h = hash_as_basic_then_ptr_ref_or_typedef_type(b->get_base_class());
1236 v = hashing::combine_hashes(v, h);
1237 }
1238
1239 // Do not hash (virtual) member functions because in C++ at least,
1240 // due to the function cloning used to implement destructors (and
1241 // maybe other functions in the future) comparing two sets of
1242 // virtual destructors is a bit more involved than what we could
1243 // naively do with by just hashing the virtual member functions.
1244 // You can look at the overload of the equals function for
1245 // class_decl, in abg-ir.cc to see the dance involved in comparing
1246 // virtual member functions. Maybe in the future we can come up
1247 // with a clever way to hash these. For now, let's rely on
1248 // structural comparison to tell the virtual member functions part
1249 // of classes appart.
1250
1251 // If we were to hash virtual member functions naively, please find
1252 // below what it would look like. Note that it doesn't work in
1253 // practise as it creates spurious self-comparison errors. You
1254 // might want to test it on this command and see for yourself:
1255 //
1256 // fedabipkgdiff --self-compare --from fc37 gcc-gnat
1257
1258 // TODO BIS: OK, actually, now that the DWARF reader improved enough
1259 // to better represent the virtual member functions, we can try
1260 // again to naively hash them. Please find below how it would work.
1261 //
1262 // Hash virtual member functions.
1263
1264 // TODO: hash the linkage names of the virtual member functions too.
1265 const_cast<class_decl&>(t).sort_virtual_mem_fns();
1266 for (const auto& method : t.get_virtual_mem_fns())
1267 {
1268 // Do not hash virtual destructors as these can be in different
1269 // numbers in two classes and yet the two classes can be
1270 // equivalent.
1271 if (get_member_function_is_dtor(method))
1272 continue;
1273
1274 string linkage_name = method->get_linkage_name();
1275 ABG_ASSERT(!linkage_name.empty());
1276 h = hashing::hash(linkage_name);
1277 v = hashing::combine_hashes(v, h);
1278 ssize_t voffset = get_member_function_vtable_offset(method);
1279 h = hashing::hash(voffset);
1280 v = hashing::combine_hashes(v, h);
1281 }
1282
1284
1285 return v;
1286}
1287
1288/// Compute a hash for a @ref class_decl
1289///
1290/// @param t the class_decl for which to compute the hash value.
1291///
1292/// @return the computed hash value.
1293hash_t
1295{return t ? operator()(*t) : 0;}
1296
1297/// Hashing function for a @ref union_decl IR node.
1298///
1299/// @param t the @ref union_decl IR node to hash.
1300///
1301/// @return the resulting hash value.
1302hash_t
1303union_decl::hash::operator()(const union_decl& t) const
1304{
1305 MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES(t);
1306
1307 // If the type is decl-only and now has a definition, then hash its
1308 // definition instead.
1309
1311 {
1312 union_decl_sptr u = is_union_type(t.get_definition_of_declaration());
1313 hash_t v = operator()(*u);
1315 return v;
1316 }
1317
1318 add_to_hashing_state(t, hashing::HASHING_STARTED_STATE);
1319
1320 class_or_union::hash hash_as_class_or_union;
1321
1322 hash_t v = hash_as_class_or_union(t);
1323
1325
1326 return v;
1327}
1328
1329/// Hashing function for a @ref union_decl IR node.
1330///
1331/// @param t the @ref union_decl IR node to hash.
1332///
1333/// @return the resulting hash value.
1334hash_t
1335union_decl::hash::operator()(const union_decl*t) const
1336{
1337 if (!t)
1338 return 0;
1339 return operator()(*t);
1340}
1341}//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:1790
This contains the private implementation of the suppression engine of libabigail.
Types of the main internal representation of libabigail.
Abstraction for an array range type, like in Ada, or just for an array dimension like in C or C++.
Definition abg-ir.h:2578
int64_t get_upper_bound() const
Getter of the upper bound of the subrange type.
Definition abg-ir.cc:20180
int64_t get_lower_bound() const
Getter of the lower bound of the subrange type.
Definition abg-ir.cc:20187
The abstraction of an array type.
Definition abg-ir.h:2552
const type_base_sptr get_element_type() const
Getter of the type of an array element.
Definition abg-ir.cc:20828
const std::vector< subrange_sptr > & get_subranges() const
Get the array's subranges.
Definition abg-ir.cc:20991
Abstraction of a base specifier in a class declaration.
Definition abg-ir.h:4391
class_decl_sptr get_base_class() const
Get the base class referred to by the current base class specifier.
Definition abg-ir.cc:26517
bool get_is_virtual() const
Getter of the "is-virtual" proprerty of the base class specifier.
Definition abg-ir.cc:26524
long get_offset_in_bits() const
Getter of the offset of the base.
Definition abg-ir.cc:26531
Abstracts a class declaration.
Definition abg-ir.h:4214
const base_specs & get_base_specifiers() const
Get the base specifiers for this class.
Definition abg-ir.cc:26314
const member_functions & get_virtual_mem_fns() const
Get the virtual member functions of this class.
Definition abg-ir.cc:26357
The base type of class_decl and union_decl.
Definition abg-ir.h:4005
const data_members & get_non_static_data_members() const
Get the non-static data members of this class_or_union.
Definition abg-ir.cc:25328
The base type of all declarations.
Definition abg-ir.h:1584
virtual const interned_string & get_name() const
Getter for the name of the current decl.
Definition abg-ir.cc:5946
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:6085
bool get_is_declaration_only() const
Test if a decl_base is a declaration-only decl.
Definition abg-ir.cc:6114
const interned_string & get_linkage_name() const
Getter for the mangled name.
Definition abg-ir.cc:5881
Abstracts a declaration for an enum type.
Definition abg-ir.h:2796
const enumerators & get_enumerators() const
Definition abg-ir.cc:21078
type_base_sptr get_underlying_type() const
Return the underlying type of the enum.
Definition abg-ir.cc:21073
Abstraction of a function type.
Definition abg-ir.h:3429
type_base_sptr get_return_type() const
Getter for the return type of the current instance of function_type.
Definition abg-ir.cc:22794
const parameters & get_parameters() const
Getter for the set of parameters of the current intance of function_type.
Definition abg-ir.cc:22844
The base class for member types, data members and member functions. Its purpose is mainly to carry th...
Definition abg-ir.h:3867
access_specifier get_access_specifier() const
Getter for the access specifier of this member.
Definition abg-ir.h:3887
Abstracts the type of a class member function.
Definition abg-ir.h:3527
bool get_is_const() const
Getter of the "is-const" property of method_type.
Definition abg-ir.cc:23543
The abstraction of a pointer type.
Definition abg-ir.h:2354
const type_base_sptr get_pointed_to_type() const
Getter of the pointed-to type.
Definition abg-ir.cc:19012
The abstraction of a pointer-to-member type.
Definition abg-ir.h:2489
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:19735
const type_base_sptr & get_member_type() const
Getter of the member type of the current ptr_to_mbr_type.
Definition abg-ir.cc:19726
The abstraction of a qualified type.
Definition abg-ir.h:2240
CV get_cv_quals() const
Getter of the const/volatile qualifier bit field.
Definition abg-ir.cc:18633
type_base_sptr get_underlying_type() const
Getter of the underlying type.
Definition abg-ir.cc:18658
Abstracts a reference type.
Definition abg-ir.h:2420
An abstraction helper for type declarations.
Definition abg-ir.h:2014
virtual size_t get_size_in_bits() const
Getter for the size of the type.
Definition abg-ir.cc:17233
virtual size_t get_alignment_in_bits() const
Getter for the alignment of the type.
Definition abg-ir.cc:17253
A basic type declaration that introduces no scope.
Definition abg-ir.h:2122
The base class of both types and declarations.
Definition abg-ir.h:1378
const interned_string & get_cached_pretty_representation(bool internal=false) const
Get the pretty representation of the current decl.
Definition abg-ir.cc:5332
offset_t get_native_offset() const
Get the native offset of a given artifact.
Definition abg-ir.cc:5205
virtual hash_t hash_value() const
Return the hash value of the current IR node.
Definition abg-ir.cc:5135
The abstraction of a typedef declaration.
Definition abg-ir.h:2936
Abstracts a union type declaration.
Definition abg-ir.h:4449
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
void add_to_hashing_state(const ir::type_or_decl_base &tod, hashing::hashing_state s)
Add a state to the hashing state of a given IR node.
Definition abg-hash.cc:299
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. This is a bitfield.
Definition abg-hash.h:25
@ HASHING_STARTED_STATE
Hashing started but is not yet finished.
Definition abg-hash.h:36
@ HASHING_FINISHED_STATE
Hashing of the given IR node started, is done and a hash value has been stored onto the node....
Definition abg-hash.h:50
@ HASHING_CYCLED_TYPE_STATE
A cycle has been detected in the graph on the current node.
Definition abg-hash.h:44
@ HASHING_NOT_DONE_STATE
No hashing has been done/started.
Definition abg-hash.h:33
void remove_from_hashing_state(const ir::type_or_decl_base &tod, hashing::hashing_state s)
Remove a state to the hashing state of a given IR node.
Definition abg-hash.cc:315
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
The namespace of the internal representation of ABI artifacts like types and decls.
bool get_member_function_is_dtor(const function_decl &f)
Test whether a member function is a destructor.
Definition abg-ir.cc:7544
hash_t peek_hash_value(const type_or_decl_base &artefact)
Get the hash value associated to an IR node.
Definition abg-ir.cc:30142
shared_ptr< method_type > method_type_sptr
Convenience typedef for shared pointer to method_type.
Definition abg-fwd.h:222
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:6684
ssize_t get_member_function_vtable_offset(const function_decl &f)
Get the vtable offset of a member function.
Definition abg-ir.cc:7675
bool is_type(const type_or_decl_base &tod)
Test whether a declaration is a type.
Definition abg-ir.cc:12031
bool is_class_type(const type_or_decl_base &t)
Test whether a type is a class.
Definition abg-ir.cc:12395
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:12626
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:13257
shared_ptr< class_decl > class_decl_sptr
Convenience typedef for a shared pointer on a class_decl.
Definition abg-fwd.h:194
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:13197
typedef_decl_sptr is_typedef(const type_or_decl_base_sptr t)
Test whether a type is a typedef.
Definition abg-ir.cc:12241
abg_compat::optional< uint64_t > hash_t
The abstraction for an 8 bytes hash value.
Definition abg-ir.h:109
shared_ptr< function_type > function_type_sptr
Convenience typedef for a shared pointer on a function_type.
Definition abg-fwd.h:211
reference_type_def * is_reference_type(type_or_decl_base *t, bool look_through_qualifiers)
Test whether a type is a reference_type_def.
Definition abg-ir.cc:12881
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:12330
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:240
shared_ptr< type_or_decl_base > type_or_decl_base_sptr
A convenience typedef for a shared_ptr to type_or_decl_base.
Definition abg-fwd.h:118
decl_base * is_decl(const type_or_decl_base *d)
Test if an ABI artifact is a declaration.
Definition abg-ir.cc:11971
shared_ptr< enum_type_decl > enum_type_decl_sptr
Convenience typedef for shared pointer to a enum_type_decl.
Definition abg-fwd.h:176
const pointer_type_def * is_pointer_type(const type_or_decl_base *t, bool look_through_qualifiers)
Test whether a type is a pointer_type_def.
Definition abg-ir.cc:12709
class_or_union * look_through_decl_only_class(class_or_union *the_class)
If a class (or union) is a decl-only class, get its definition. Otherwise, just return the initial cl...
Definition abg-ir.cc:13148
bool is_union_type(const type_or_decl_base &t)
Test if a type is a union_decl.
Definition abg-ir.cc:12675
type_base_sptr peel_typedef_type(const type_base_sptr &type)
Return the leaf underlying type node of a typedef_decl node.
Definition abg-ir.cc:8155
hash_t get_subtype_hash(const type_or_decl_base *t)
Compute (or get) the hash of a sub-type of the type for which we are currently computing the hash....
Definition abg-hash.cc:349
qualified_type_def * is_qualified_type(const type_or_decl_base *t)
Test whether a type is a reference_type_def.
Definition abg-ir.cc:13068
bool is_member_decl(const decl_base_sptr d)
Tests if a declaration is a class member.
Definition abg-ir.cc:6514
Toplevel namespace for libabigail.
hash_t operator()(const array_type_def &t) const
Hashing function for a array_type_def IR node.
Definition abg-hash.cc:836
hash_t operator()(const base_spec &t) const
Hashing function for a class_decl::base_spec IR node.
Definition abg-hash.cc:1122
hash_t operator()(const class_decl &t) const
Compute a hash for a class_decl.
Definition abg-hash.cc:1210
Hasher for the class_or_union type.
Definition abg-hash.h:243
hash_t operator()(const class_or_union &t) const
Compute a hash for a class_or_union.
Definition abg-hash.cc:1162
hash_t operator()(const decl_base &d) const
Hash function for an instance of decl_base.
Definition abg-hash.cc:579
hash_t operator()(const enum_type_decl &t) const
Hashing function for a enum_type_decl IR node.
Definition abg-hash.cc:945
hash_t operator()(const function_type &t) const
Hashing function for function_type.
Definition abg-hash.cc:1003
The hashing functor for member_base.
Definition abg-hash.h:236
hash_t operator()(const member_base &m) const
Hashing function for a member_base IR node.
Definition abg-hash.cc:1111
hash_t operator()(const method_type &t) const
Hashing function for a method_type IR node.
Definition abg-hash.cc:1054
Hash functor for instances of pointer_type_def.
Definition abg-hash.h:137
hash_t operator()(const pointer_type_def &t) const
Hashing function for a pointer_type_def IR node.
Definition abg-hash.cc:729
hash_t operator()(const ptr_to_mbr_type &t) const
Hashing function for a ptr_to_mbr_type IR node.
Definition abg-hash.cc:891
Hash functor for instances of qualified_type_def.
Definition abg-hash.h:127
hash_t operator()(const qualified_type_def &t) const
Hashing function for a qualified_type_def IR node.
Definition abg-hash.cc:688
Hash functor for instances of reference_type_def.
Definition abg-hash.h:147
hash_t operator()(const reference_type_def &t) const
Hashing function for a reference_type_def IR node.
Definition abg-hash.cc:769
Hash functor for instances of type_base.
Definition abg-hash.h:104
hash_t operator()(const type_base &t) const
The hashing functor for using instances of type_or_decl_base as values in a hash map or set.
Definition abg-hash.cc:548
hash_t operator()(const type_decl &t) const
Hashing function for a type_decl IR node.
Definition abg-hash.cc:616
Hash functor for instances of typedef_decl.
Definition abg-hash.h:200
hash_t operator()(const typedef_decl &t) const
Hashing function for a typedef_decl IR node.
Definition abg-hash.cc:654