libabigail
abg-ir-priv.h
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2// -*- Mode: C++ -*-
3//
4// Copyright (C) 2016-2025 Red Hat, Inc.
5//
6// Author: Dodji Seketeli
7
8/// @file
9///
10/// This contains the private implementation of the suppression engine
11/// of libabigail.
12
13#ifndef __ABG_IR_PRIV_H__
14#define __ABG_IR_PRIV_H__
15
16#include <algorithm>
17#include <iostream>
18#include <string>
19
20#include "abg-hash.h"
21#include "abg-corpus.h"
22#include "abg-tools-utils.h"
23
24namespace abigail
25{
26
27namespace ir
28{
29
30using std::string;
31using std::unordered_set;
33
34/// The result of structural comparison of type ABI artifacts.
36{
37 COMPARISON_RESULT_DIFFERENT = 0,
38 COMPARISON_RESULT_EQUAL = 1,
39 COMPARISON_RESULT_CYCLE_DETECTED = 2,
40 COMPARISON_RESULT_UNKNOWN = 3,
41}; //end enum comparison_result
42
43/// The internal representation of an integral type.
44///
45/// This is a "utility type" used internally to canonicalize the name
46/// of fundamental integral types, so that "unsignd long" and "long
47/// unsined int" end-up having the same name.
49{
50public:
51 /// The possible base types of integral types. We might have
52 /// forgotten many of these, so do not hesitate to add new ones.
53 ///
54 /// If you do add new ones, please also consider updating functions
55 /// parse_base_real_type and real_type::to_string.
57 {
58 /// The "int" base type.
60 /// The "char" base type.
62 /// The "bool" base type in C++ or "_Bool" in C11.
64 /// The "double" base type.
66 /// The "float" base type.
68 /// The "char16_t base type.
70 /// The "char32_t" base type.
72 /// The "wchar_t" base type.
74 SIZE_BASE_TYPE,
75 SSIZE_BASE_TYPE,
76 BIT_SIZE_BASE_TYPE,
77 SBIT_SIZE_BASE_TYPE,
78 /// The aray size type used by Clang.
80 };
81
82 /// The modifiers of the base types above. Several modifiers can be
83 /// combined for a given base type. The presence of modifiers is
84 /// usually modelled by a bitmap of modifiers.
85 ///
86 /// If you add a new modifier, please consider updating functions
87 /// parse_real_type_modifier and real_type::to_string.
89 {
90 NO_MODIFIER = 0,
91 /// The "signed" modifier.
93 /// The "unsigned" modier.
95 /// The "short" modifier.
97 /// The "long" modifier.
98 LONG_MODIFIER = 1 << 3,
99 /// The "long long" modifier.
100 LONG_LONG_MODIFIER = 1 << 4
101 };
102
103private:
104 base_type base_;
105 modifiers_type modifiers_;
106
107public:
108
109 real_type();
110 real_type(const string& name);
112
114 get_base_type() const;
115
117 get_modifiers() const;
118
119 void
121
122 bool
123 operator==(const real_type&) const;
124
125 string
126 to_string(bool internal=false) const;
127
128 operator string() const;
129}; // end class real_type
130
133
136
139
142
145
146bool
147parse_real_type(const string& type_name,
148 real_type& type);
149
150/// Private type to hold private members of @ref translation_unit
152{
153 const environment& env_;
154 corpus* corp;
155 bool is_constructed_;
156 char address_size_;
157 language language_;
158 std::string path_;
159 std::string comp_dir_path_;
160 std::string abs_path_;
161 location_manager loc_mgr_;
162 mutable global_scope_sptr global_scope_;
163 mutable vector<type_base_sptr> synthesized_types_;
164 vector<function_type_sptr> live_fn_types_;
165 type_maps types_;
166
167
168 priv(const environment& env)
169 : env_(env),
170 corp(),
171 is_constructed_(),
172 address_size_(),
173 language_(LANG_UNKNOWN)
174 {}
175
176 ~priv()
177 {}
178
179 type_maps&
180 get_types()
181 {return types_;}
182}; // end translation_unit::priv
183
184// <type_or_decl_base stuff>
185
186/// The private data of @ref type_or_decl_base.
188{
189 // This holds the kind of dynamic type of particular instance.
190 // Yes, this is part of the implementation of a "poor man" runtime
191 // type identification. We are doing this because profiling shows
192 // that using dynamic_cast in some places is really to slow and is
193 // constituting a hotspot. This poor man's implementation made
194 // things be much faster.
195 enum type_or_decl_kind kind_;
196 // This holds the runtime type instance pointer of particular
197 // instance. In other words, this is the "this pointer" of the
198 // dynamic type of a particular instance.
199 void* rtti_;
200 // This holds a pointer to either the type_base sub-object (if the
201 // current instance is a type) or the decl_base sub-object (if the
202 // current instance is a decl). This is used by the is_decl() and
203 // is_type() functions, which also show up during profiling as
204 // hotspots, due to their use of dynamic_cast.
205 void* type_or_decl_ptr_;
206 mutable hashing::hashing_state hashing_state_;
207 bool is_recursive_artefact_;
208 hash_t hash_value_;
209 const environment& env_;
210 translation_unit* translation_unit_;
211 // The location of an artifact as seen from its input by the
212 // artifact reader. This might be different from the source
213 // location advertised by the original emitter of the artifact
214 // emitter.
215 location artificial_location_;
216 // Flags if the current ABI artifact is artificial (i.e, *NOT*
217 // generated from the initial source code, but rather either
218 // artificially by the compiler or by libabigail itself).
219 bool is_artificial_;
220
221 /// Constructor of the type_or_decl_base::priv private type.
222 ///
223 /// @param e the environment in which the ABI artifact was created.
224 ///
225 /// @param k the identifier of the runtime type of the current
226 /// instance of ABI artifact.
228 enum type_or_decl_kind k = ABSTRACT_TYPE_OR_DECL)
229 : kind_(k),
230 rtti_(),
231 type_or_decl_ptr_(),
232 hashing_state_(hashing::HASHING_NOT_DONE_STATE),
233 is_recursive_artefact_(),
234 env_(e),
235 translation_unit_(),
236 is_artificial_()
237 {}
238
239 /// Getter of the kind of the IR node.
240 ///
241 /// @return the kind of the IR node.
243 kind() const
244 {return kind_;}
245
246 /// Setter of the kind of the IR node.
247 ///
248 /// @param k the new IR node kind.
249 void
251 {kind_ |= k;}
252
253 /// Getter the hashing state of the current IR node.
254 ///
255 /// @return the hashing state of the current IR node.
258 {return hashing_state_;}
259
260 /// Getter of the property which flags the current artefact as being
261 /// recursive or not.
262 ///
263 /// @return true iff the current artefact it recursive.
264 bool
266 {return is_recursive_artefact_;}
267
268 /// Setter of the property which flags the current artefact as being
269 /// recursive or not.
270 ///
271 /// @param f the new value of the property.
272 void
274 {is_recursive_artefact_ = f;}
275
276 /// Setter of the hashing state of the current IR node.
277 ///
278 /// @param s the hashing state of the current IR node.
279 void
281 {hashing_state_ = s;}
282
283 /// Setter of the hashing value of the current IR node.
284 ///
285 /// An empty value is just ignored. Also, if the IR node is NEITHER
286 /// in the hashing::HASHING_NOT_DONE_STATE nor in the
287 /// hashing::HASHING_CYCLED_TYPE_STATE, then the function does
288 /// nothing.
289 ///
290 /// @param h the new hash value.
291 void
293 {
295
300 if (h.has_value()
303 {
304 hash_value_ = h;
306 }
307 }
308
309 /// Setter of the hashing value of the current IR node.
310 ///
311 /// Unlike set_hash_value above, this function always sets a new
312 /// hash value regardless of the hash value or of the hashing state
313 /// of the IR node.
314 ///
315 /// @param h the new hash value.
316 void
318 {
319 if (h.has_value())
320 {
321 hash_value_ = h;
323 }
324 }
325}; // end struct type_or_decl_base::priv
326
327/// Compute the hash value of an IR node and return it.
328///
329/// Note that if the IR node is a non-canonicalizeable type, no hash
330/// value is computed and an empty hash is returned. Also, if the IR
331/// node already has a hash value, then this function just returns it.
332///
333/// This is a sub-routine of the internal hashing functions defined in
334/// abg-hash.cc
335///
336/// @param tod the IR node to compute the value for.
337///
338/// @return the computed hash value computed.
339template<typename T>
340hash_t
341do_hash_value(const T& tod)
342{
343 if (type_base* type = is_type(&tod))
345 // Non canonicalized types are not hashed. They must always be
346 // compared structurally.
347 return hash_t();
348
349 typename T::hash do_hash;
350 hash_t h = do_hash(tod);
351 return h;
352}
353
354/// Compute the hash value of an IR node and return it.
355///
356/// Note that if the IR node is a non-canonicalizeable type, no hash
357/// value is computed and an empty hash is returned. Also, if the IR
358/// node already has a hash value, then this function just returns it.
359///
360/// This is a sub-routine of the internal hashing functions defined in
361/// abg-hash.cc
362///
363/// @param tod the IR node to compute the value for.
364///
365/// @return the computed hash value computed.
366template<typename T>
367hash_t
368do_hash_value(const T* tod)
369{
370 if (!tod)
371 return hash_t();
372 return hash_value(*tod);
373}
374
375/// Compute the hash value of an IR node and return it.
376///
377/// Note that if the IR node is a non-canonicalizeable type, no hash
378/// value is computed and an empty hash is returned. Also, if the IR
379/// node already has a hash value, then this function just returns it.
380///
381/// This is a sub-routine of the internal hashing functions defined in
382/// abg-hash.cc
383///
384/// @param tod the IR node to compute the value for.
385///
386/// @return the computed hash value computed.
387template<typename T>
388hash_t
389do_hash_value(const shared_ptr<T>& tod)
390{
391 if (!tod)
392 return hash_t();
393 return do_hash_value(*tod);
394}
395
396
397/// Set the hash value of an IR node and return it.
398///
399/// If the IR node already has a hash value set, this function just
400/// returns it. Otherwise, the function computes a new hash value and
401/// sets it to the IR node.
402///
403/// Note that if the IR node is a non-canonicalizeable type, no hash
404/// value is computed and an empty hash is returned.
405///
406/// This is a sub-routine of the type_or_decl_base::hash_value()
407/// virtual member functions.
408///
409/// @param type_or_decl the IR node to compute the value for.
410///
411/// @return the hash value computed and set to the IR node, or the
412/// hash value the IR node already had.
413template<typename T>
414hash_t
416{
417 hash_t h = do_hash_value(tod);
418 const_cast<T&>(tod).set_hash_value(h);
419 return h;
420}
421
422/// Set the hash value of an IR node and return it.
423///
424/// If the IR node already has a hash value set, this function just
425/// returns it. Otherwise, the function computes a new hash value and
426/// sets it to the IR node.
427///
428/// Note that if the IR node is a non-canonicalizeable type, no hash
429/// value is computed and an empty hash is returned.
430///
431/// This is a sub-routine of the type_or_decl_base::hash_value()
432/// virtual member functions.
433///
434/// @param type_or_decl the IR node to compute the value for.
435///
436/// @return the hash value computed and set to the IR node, or the
437/// hash value the IR node already had.
438template<typename T>
439hash_t
441{
442 if (!artifact)
443 return hash_t();
444 return set_or_get_cached_hash_value(*artifact);
445}
446
447// </type_or_decl_base stuff>
448
449
450// <type_base definitions>
451
452size_t
454
455size_t
457
458size_t
459get_canonical_type_index(const type_base_sptr& t);
460
461/// Definition of the private data of @ref type_base.
463{
464 size_t size_in_bits;
465 size_t alignment_in_bits;
466 size_t canonical_type_index;
467 type_base_wptr canonical_type;
468 // The data member below holds the canonical type that is managed by
469 // the smart pointer referenced by the canonical_type data member
470 // above. We are storing this underlying (naked) pointer here, so
471 // that users can access it *fast*. Otherwise, accessing
472 // canonical_type above implies creating a shared_ptr, and that has
473 // been measured to be slow for some performance hot spots.
474 type_base* naked_canonical_type;
475 // Computing the representation of a type again and again can be
476 // costly. So we cache the internal and non-internal type
477 // representation strings here.
478 interned_string internal_cached_repr_;
479 interned_string cached_repr_;
480
481 priv()
482 : size_in_bits(),
483 alignment_in_bits(),
484 canonical_type_index(),
485 naked_canonical_type()
486 {}
487
488 priv(size_t s,
489 size_t a,
490 type_base_sptr c = type_base_sptr())
491 : size_in_bits(s),
492 alignment_in_bits(a),
493 canonical_type_index(),
494 canonical_type(c),
495 naked_canonical_type(c.get())
496 {}
497}; // end struct type_base::priv
498
499bool
501
502// <environment definitions>
503
504/// The hashing functor for a pair of uint64_t.
506{
507 /// Hashing function for a pair of uint64_t.
508 ///
509 /// @param p the pair to hash.
510 uint64_t
511 operator()(const std::pair<uint64_t, uint64_t>& p) const
512 {
514 hash_t(p.second));
515 }
516};
517
518/// A convenience typedef for a pair of uint64_t which is initially
519/// intended to store a pair of pointer values.
520typedef std::pair<uint64_t, uint64_t> uint64_t_pair_type;
521
522/// A convenience typedef for a set of @ref uint64_t_pair
523typedef unordered_set<uint64_t_pair_type,
525
526/// A convenience typedef for a set of pointer to @ref class_or_union
527typedef unordered_set<const class_or_union*> class_set_type;
528
529/// A convenience typedef for a set of pointer to @ref function_type.
530typedef unordered_set<const function_type*> fn_set_type;
531
532/// A convenience typedef for a map which key is a pair of uint64_t
533/// and which value is a boolean. This is initially intended to cache
534/// the result of comparing two (sub-)types.
535typedef unordered_map<uint64_t_pair_type, bool,
537
538/// The private data of the @ref environment type.
540{
541 config config_;
542 canonical_types_map_type canonical_types_;
543 mutable vector<type_base_sptr> sorted_canonical_types_;
544 type_base_sptr void_type_;
545 type_base_sptr void_pointer_type_;
546 type_base_sptr variadic_marker_type_;
547 // The set of pairs of class types being currently compared. It's
548 // used to avoid endless loops while recursively comparing types.
549 // This should be empty when none of the 'equal' overloads are
550 // currently being invoked.
551 class_set_type left_classes_being_compared_;
552 class_set_type right_classes_being_compared_;
553 // The set of pairs of function types being currently compared. It's used
554 // to avoid endless loops while recursively comparing types. This
555 // should be empty when none of the 'equal' overloads are currently
556 // being invoked.
557 fn_set_type left_fn_types_being_compared_;
558 fn_set_type right_fn_types_being_compared_;
559 // This is a cache for the result of comparing two sub-types (of
560 // either class or function types) that are designated by their
561 // memory address in the IR.
562 type_comparison_result_type type_comparison_results_cache_;
563 vector<type_base_sptr> extra_live_types_;
564 interned_string_pool string_pool_;
565 // The two vectors below represent the stack of left and right
566 // operands of the current type comparison operation that is
567 // happening during type canonicalization.
568 //
569 // Basically, that stack of operand looks like below.
570 //
571 // First, suppose we have a type T_L that has two sub-types as this:
572 //
573 // T_L
574 // |
575 // +-- L_OP0
576 // |
577 // +-- L_OP1
578 //
579 // Now suppose that we have another type T_R that has two sub-types
580 // as this:
581 //
582 // T_R
583 // |
584 // +-- R_OP0
585 // |
586 // +-- R_OP1
587 //
588 // Now suppose that we compare T_L against T_R. We are going to
589 // have a stack of pair of types. Each pair of types represents
590 // two (sub) types being compared against each other.
591 //
592 // On the stack, we will thus first have the pair (T_L, T_R)
593 // being compared. Then, we will have the pair (L_OP0, R_OP0)
594 // being compared, and then the pair (L_OP1, R_OP1) being
595 // compared. Like this:
596 //
597 // | T_L | L_OP0 | L_OP1 | <-- this goes into left_type_comp_operands_;
598 // -------- -------------
599 // | T_R | R_OP0 | R_OP1 | <-- this goes into right_type_comp_operands_;
600 //
601 vector<const type_base*> left_type_comp_operands_;
602 vector<const type_base*> right_type_comp_operands_;
603
604#ifdef WITH_DEBUG_SELF_COMPARISON
605 // This is used for debugging purposes.
606 // When abidw is used with the option --debug-abidiff, some
607 // libabigail internals need to get a hold on the initial binary
608 // input of abidw, as well as as the abixml file that represents the
609 // ABI of that binary.
610 //
611 // So this one is the corpus for the input binary.
612 corpus_wptr first_self_comparison_corpus_;
613 // This one is the corpus for the ABIXML file representing the
614 // serialization of the input binary.
615 corpus_wptr second_self_comparison_corpus_;
616 // This is also used for debugging purposes, when using
617 // 'abidw --debug-abidiff <binary>'. It holds the set of mapping of
618 // an abixml (canonical) type and its type-id.
619 unordered_map<string, uintptr_t> type_id_canonical_type_map_;
620 // Likewise. It holds a map that associates the pointer to a type
621 // read from abixml and the type-id string it corresponds to.
622 unordered_map<uintptr_t, string> pointer_type_id_map_;
623#endif
624 bool canonicalization_started_;
625 bool canonicalization_is_done_;
626 bool decl_only_class_equals_definition_;
627 bool use_enum_binary_only_equality_;
628 bool allow_type_comparison_results_caching_;
629 bool do_log_;
630 optional<bool> analyze_exported_interfaces_only_;
631#ifdef WITH_DEBUG_SELF_COMPARISON
632 bool self_comparison_debug_on_;
633#endif
634#ifdef WITH_DEBUG_TYPE_CANONICALIZATION
635 // This controls whether to use canonical type comparison during
636 // type comparison or not. This is only used for debugging, when we
637 // want to ensure that comparing types using canonical or structural
638 // comparison yields the same result.
639 bool use_canonical_type_comparison_;
640 // Whether we are debugging type canonicalization or not. When
641 // debugging type canonicalization, a type is compared to its
642 // potential canonical type twice: The first time with canonical
643 // comparison activated, and the second time with structural
644 // comparison activated. The two comparison should yield the same
645 // result, otherwise, canonicalization is "broken" for that
646 // particular type.
647 bool debug_type_canonicalization_;
648 bool debug_die_canonicalization_;
649#endif
650
651 priv()
652 : canonicalization_started_(),
653 canonicalization_is_done_(),
654 decl_only_class_equals_definition_(false),
655 use_enum_binary_only_equality_(true),
656 allow_type_comparison_results_caching_(false),
657 do_log_(false)
658#ifdef WITH_DEBUG_SELF_COMPARISON
659 ,
660 self_comparison_debug_on_(false)
661#endif
662#ifdef WITH_DEBUG_TYPE_CANONICALIZATION
663 ,
664 use_canonical_type_comparison_(true),
665 debug_type_canonicalization_(false),
666 debug_die_canonicalization_(false)
667#endif
668 {}
669
670 /// Allow caching of the sub-types comparison results during the
671 /// invocation of the @ref equal overloads for class and function
672 /// types.
673 ///
674 /// @param f if true, allow type comparison result caching.
675 void
677 {allow_type_comparison_results_caching_ = f;}
678
679 /// Check whether if caching of the sub-types comparison results during the
680 /// invocation of the @ref equal overloads for class and function
681 /// types is in effect.
682 ///
683 /// @return true iff caching of the sub-types comparison results
684 /// during the invocation of the @ref equal overloads for class and
685 /// function types is in effect.
686 bool
688 {return allow_type_comparison_results_caching_;}
689
690 void
691 do_log(bool f)
692 {do_log_ = f;}
693
694 bool
695 do_log() const
696 {return do_log_;}
697
698 /// Cache the result of comparing two sub-types.
699 ///
700 /// @param first the first sub-type that has been compared. Its
701 /// address is going to be stored in the cache.
702 ///
703 /// @param second the second sub-type that has been compared. Its
704 /// address is going to be stored in the cache.
705 ///
706 /// @param r the result of comparing @p first and @p second. This
707 /// is going to be stored in the cache, as well as the addresses of
708 /// @p first and @p second.
709 template<typename T>
710 void
711 cache_type_comparison_result(T& first, T& second, bool r)
712 {
714 {
715 type_comparison_results_cache_.emplace
716 (std::make_pair(reinterpret_cast<uint64_t>(&first),
717 reinterpret_cast<uint64_t>(&second)),
718 r);
719 }
720 }
721
722 /// Retrieve the result of comparing two sub-types from the cache,
723 /// if it was previously stored.
724 ///
725 /// @param first the first sub-type to consider.
726 ///
727 /// @param second the second sub-type to consider. The pair of
728 /// addresses of {@p first, @p second} is going to be looked up in
729 /// the cache. If it's present, then the associated result of the
730 /// comparison of @p first against @p second is present as well, and
731 /// is returned.
732 ///
733 /// @param r this is an out parameter which is set to the result of
734 /// the comparison of @p first against @p second if the pair of
735 /// addresses of {@p first, @p second} is present in the cache.
736 ///
737 /// @return true iff the pair of addresses of {@p first, @p second}
738 /// is present in the cache. In that case, the associated result of
739 /// the comparison of @p first against @p second is returned in the
740 /// argument of @p r.
741 template<typename T>
742 bool
743 is_type_comparison_cached(T& first, T& second, bool& r)
744 {
746 return false;
747
748 type_comparison_result_type::const_iterator it =
749 type_comparison_results_cache_.find
750 (std::make_pair(reinterpret_cast<uint64_t>(&first),
751 reinterpret_cast<uint64_t>(&second)));
752 if (it == type_comparison_results_cache_.end())
753 return false;
754
755 r = it->second;
756 return true;
757 }
758
759 /// Clear the cache type comparison results.
760 void
762 {type_comparison_results_cache_.clear();}
763
764 /// Push a pair of operands on the stack of operands of the current
765 /// type comparison, during type canonicalization.
766 ///
767 /// For more information on this, please look at the description of
768 /// the right_type_comp_operands_ data member.
769 ///
770 /// @param left the left-hand-side comparison operand to push.
771 ///
772 /// @param right the right-hand-side comparison operand to push.
773 void
775 const type_base* right)
776 {
777 ABG_ASSERT(left && right);
778
779 left_type_comp_operands_.push_back(left);
780 right_type_comp_operands_.push_back(right);
781 }
782
783 /// Pop a pair of operands from the stack of operands to the current
784 /// type comparison.
785 ///
786 /// For more information on this, please look at the description of
787 /// the right_type_comp_operands_ data member.
788 ///
789 /// @param left the left-hand-side comparison operand we expect to
790 /// pop from the top of the stack. If this doesn't match the
791 /// operand found on the top of the stack, the function aborts.
792 ///
793 /// @param right the right-hand-side comparison operand we expect to
794 /// pop from the bottom of the stack. If this doesn't match the
795 /// operand found on the top of the stack, the function aborts.
796 void
798 const type_base* right)
799 {
800 const type_base *t = left_type_comp_operands_.back();
801 ABG_ASSERT(t == left);
802 t = right_type_comp_operands_.back();
803 ABG_ASSERT(t == right);
804
805 left_type_comp_operands_.pop_back();
806 right_type_comp_operands_.pop_back();
807 }
808
809#ifdef WITH_DEBUG_SELF_COMPARISON
810
811 const unordered_map<string, uintptr_t>&
812 get_type_id_canonical_type_map() const
813 {return type_id_canonical_type_map_;}
814
815 unordered_map<string, uintptr_t>&
816 get_type_id_canonical_type_map()
817 {return type_id_canonical_type_map_;}
818
819 const unordered_map<uintptr_t, string>&
820 get_pointer_type_id_map() const
821 {return pointer_type_id_map_;}
822
823 unordered_map<uintptr_t, string>&
824 get_pointer_type_id_map()
825 {return pointer_type_id_map_;}
826
827 string
828 get_type_id_from_pointer(uintptr_t ptr) const
829 {
830 auto it = get_pointer_type_id_map().find(ptr);
831 if (it != get_pointer_type_id_map().end())
832 return it->second;
833 return "";
834 }
835
836 string
837 get_type_id_from_type(const type_base *t) const
838 {return get_type_id_from_pointer(reinterpret_cast<uintptr_t>(t));}
839
840 uintptr_t
841 get_canonical_type_from_type_id(const char* type_id) const
842 {
843 if (!type_id)
844 return 0;
845 auto it = get_type_id_canonical_type_map().find(type_id);
846 if (it != get_type_id_canonical_type_map().end())
847 return it->second;
848 return 0;
849 }
850
851 /// When debugging self comparison, verify that a type T
852 /// de-serialized from abixml has the same canonical type as the
853 /// initial type built from DWARF that was serialized into T in the
854 /// first place.
855 ///
856 /// @param t deserialized type (from abixml) to consider.
857 ///
858 /// @param c the canonical type that @p t has, as computed freshly
859 /// from the abixml file.
860 ///
861 /// @return true iff @p c has the same value as the canonical type
862 /// that @p t had before being serialized into abixml.
863 bool
864 check_canonical_type_from_abixml_during_self_comp(const type_base* t,
865 const type_base* c)
866 {
867 if (!t || !t->get_corpus() || !c)
868 return false;
869
870 if (!(t->get_corpus()->get_origin() == ir::corpus::NATIVE_XML_ORIGIN))
871 return false;
872
873 // Get the abixml type-id that this type was constructed from.
874 string type_id;
875 {
876 unordered_map<uintptr_t, string>::const_iterator it =
877 pointer_type_id_map_.find(reinterpret_cast<uintptr_t>(t));
878 if (it == pointer_type_id_map_.end())
879 // This type didn't have a type-id in the abixml file. Maybe
880 // it's a function or method type. So let's just keep going.
881 return true;
882 type_id = it->second;
883 }
884
885 // Get the canonical type the original in-memory type (constructed
886 // from DWARF) had when it was serialized into abixml in the first place.
887 type_base *original_canonical_type = nullptr;
888 if (!type_id.empty())
889 {
890 unordered_map<string, uintptr_t>::const_iterator it =
891 type_id_canonical_type_map_.find(type_id);
892 if (it == type_id_canonical_type_map_.end())
893 return false;
894 original_canonical_type = reinterpret_cast<type_base*>(it->second);
895 }
896
897 // Now perform the real check.
898 //
899 // We want to ensure that the canonical type 'c' of 't' is the
900 // same as the canonical type of initial in-memory type (built
901 // from DWARF) that was serialized into 't' (in abixml) in the
902 // first place.
903 if (original_canonical_type == c)
904 return true;
905
906 return false;
907 }
908
909 /// When debugging self comparison, verify that a type T
910 /// de-serialized from abixml has the same canonical type as the
911 /// initial type built from DWARF that was serialized into T in the
912 /// first place.
913 ///
914 /// @param t deserialized type (from abixml) to consider.
915 ///
916 /// @return true iff @p c is the canonical type that @p t should
917 /// have.
918 bool
919 check_abixml_canonical_type_propagation_during_self_comp(const type_base* t)
920 {
921 if (t->get_corpus()
922 && t->get_corpus()->get_origin() == ir::corpus::NATIVE_XML_ORIGIN)
923 {
924 type_base* c = t->get_naked_canonical_type();
925 if (c && !check_canonical_type_from_abixml_during_self_comp(t, c))
926 {
927 string repr = t->get_pretty_representation(true, true);
928 string type_id = get_type_id_from_type(t);
929 std::cerr << "error: canonical type propagation error for '"
930 << repr
931 << "' of type-id: '"
932 << type_id
933 << "' / type: @"
934 << std::hex
935 << t
936 << "/ canon: @"
937 << c
938 << ", should have had canonical type: "
939 << std::hex
940 << get_canonical_type_from_type_id(type_id.c_str())
941 << "\n";
942 return false;
943 }
944 }
945 return true;
946 }
947
948 /// When debugging self comparison, verify that a type T
949 /// de-serialized from abixml has the same canonical type as the
950 /// initial type built from DWARF that was serialized into T in the
951 /// first place.
952 ///
953 /// @param t deserialized type (from abixml) to consider.
954 ///
955 /// @param c the canonical type @p t should have.
956 ///
957 /// @return true iff @p c is the canonical type that @p t should
958 /// have.
959 bool
960 check_canonical_type_from_abixml_during_self_comp(const type_base_sptr& t,
961 const type_base_sptr& c)
962 {
963 return check_canonical_type_from_abixml_during_self_comp(t.get(), c.get());
964 }
965#endif
966};// end struct environment::priv
967
968bool
969compare_using_locations(const decl_base *f,
970 const decl_base *s);
971
972/// A functor to sort decls somewhat topologically. That is, types
973/// are sorted in a way that makes the ones that are defined "first"
974/// to come first.
975///
976/// The topological criteria is a lexicographic sort of the definition
977/// location of the type. For types that have no location (or the
978/// same location), it's their qualified name that is used for the
979/// lexicographic sort.
981{
982 /// Test if a decl has an artificial or natural location.
983 ///
984 /// @param d the decl to consider
985 ///
986 /// @return true iff @p d has a location.
987 bool
990
991 /// Test if a type has an artificial or natural location.
992 ///
993 /// @param t the type to consider
994 ///
995 /// @return true iff @p t has a location.
996 bool
998 {
999 if (decl_base *d = is_decl(t))
1001 return false;
1002 }
1003
1004 /// The "Less Than" comparison operator of this functor.
1005 ///
1006 /// @param f the first decl to be considered for the comparison.
1007 ///
1008 /// @param s the second decl to be considered for the comparison.
1009 ///
1010 /// @return true iff @p f is less than @p s.
1011 bool
1013 const decl_base *s)
1014 {
1015 if (!!f != !!s)
1016 return f && !s;
1017
1018 if (!f)
1019 return false;
1020
1021 // Unique types that are artificially created in the environment
1022 // don't have locations. They ought to be compared on the basis
1023 // of their pretty representation before we start looking at IR
1024 // nodes' locations down the road.
1026 return (f->get_cached_pretty_representation(/*internal=*/false)
1027 < s->get_cached_pretty_representation(/*internal=*/false));
1028
1029 // If both decls come from an abixml file, keep the order they
1030 // have from that abixml file.
1033 && (((!f->get_corpus() && !s->get_corpus())
1034 || (f->get_corpus() && f->get_corpus()->get_origin() == corpus::NATIVE_XML_ORIGIN
1035 && s->get_corpus() && s->get_corpus()->get_origin() == corpus::NATIVE_XML_ORIGIN))))
1036 return compare_using_locations(f, s);
1037
1038 // If a decl has artificial location, then use that one over the
1039 // natural one.
1042
1043 if (fl.get_value() && sl.get_value())
1044 return compare_using_locations(f, s);
1045 else if (!!fl != !!sl)
1046 // So one of the decls doesn't have location data.
1047 // The first decl is less than the second if it's the one not
1048 // having location data.
1049 return !fl && sl;
1050
1051 // We reach this point if location data is useless.
1052 if (f->get_is_anonymous()
1053 && s->get_is_anonymous()
1054 && (f->get_cached_pretty_representation(/*internal=*/false)
1055 == s->get_cached_pretty_representation(/*internal=*/false)))
1056 return f->get_name() < s->get_name();
1057
1058 return (f->get_cached_pretty_representation(/*internal=*/false)
1059 < s->get_cached_pretty_representation(/*internal=*/false));
1060 }
1061
1062 /// The "Less Than" comparison operator of this functor.
1063 ///
1064 /// @param f the first decl to be considered for the comparison.
1065 ///
1066 /// @param s the second decl to be considered for the comparison.
1067 ///
1068 /// @return true iff @p f is less than @p s.
1069 bool
1070 operator()(const decl_base_sptr &f,
1071 const decl_base_sptr &s)
1072 {return operator()(f.get(), s.get());}
1073
1074}; // end struct decl_topo_comp
1075
1076bool
1078
1079/// A functor to sort types somewhat topologically. That is, types
1080/// are sorted in a way that makes the ones that are defined "first"
1081/// to come first.
1082///
1083/// The topological criteria is a lexicographic sort of the definition
1084/// location of the type. For types that have no location, it's their
1085/// qualified name that is used for the lexicographic sort.
1087{
1088 /// Test if a decl has an artificial or natural location.
1089 ///
1090 /// @param d the decl to consider
1091 ///
1092 /// @return true iff @p d has a location.
1093 bool
1096
1097 /// Test if a type has an artificial or natural location.
1098 ///
1099 /// @param t the type to consider
1100 ///
1101 /// @return true iff @p t has a location.
1102 bool
1104 {
1105 if (decl_base *d = is_decl(t))
1107 return false;
1108 }
1109
1110 /// The "Less Than" comparison operator of this functor.
1111 ///
1112 /// @param f the first type to be considered for the comparison.
1113 ///
1114 /// @param s the second type to be considered for the comparison.
1115 ///
1116 /// @return true iff @p f is less than @p s.
1117 bool
1118 operator()(const type_base_sptr &f,
1119 const type_base_sptr &s)
1120 {return operator()(f.get(), s.get());}
1121
1122 /// The "Less Than" comparison operator of this functor.
1123 ///
1124 /// @param f the first type to be considered for the comparison.
1125 ///
1126 /// @param s the second type to be considered for the comparison.
1127 ///
1128 /// @return true iff @p f is less than @p s.
1129 bool
1131 const type_base *s)
1132 {
1133 if (f == s || !f || !s)
1134 return false;
1135
1136 // If both decls come from an abixml file, keep the order they
1137 // have from that abixml file.
1138 if (is_decl(f) && is_decl(s)
1141 && ((!f->get_corpus() && !s->get_corpus())
1142 || (f->get_corpus()
1143 && f->get_corpus()->get_origin() == corpus::NATIVE_XML_ORIGIN
1144 && s->get_corpus()
1145 && (s->get_corpus()->get_origin()
1146 == corpus::NATIVE_XML_ORIGIN))))
1148
1149 bool f_is_ptr_ref_or_qual = is_ptr_ref_or_qual_type(f);
1150 bool s_is_ptr_ref_or_qual = is_ptr_ref_or_qual_type(s);
1151
1152 if (f_is_ptr_ref_or_qual != s_is_ptr_ref_or_qual)
1153 return !f_is_ptr_ref_or_qual && s_is_ptr_ref_or_qual;
1154
1155 if (f_is_ptr_ref_or_qual && s_is_ptr_ref_or_qual
1158 {
1159 interned_string s1 = f->get_cached_pretty_representation(/*internal=*/false);
1160 interned_string s2 = s->get_cached_pretty_representation(/*internal=*/false);
1161 if (s1 == s2)
1162 {
1164 {
1165 if (q->get_cv_quals() == qualified_type_def::CV_NONE)
1166 if (!is_qualified_type(s))
1167 // We are looking at two types that are the result of
1168 // an optimization that happens during the IR
1169 // construction. Namely, type f is a cv-qualified
1170 // type with no qualifier (no const, no volatile, no
1171 // nothing, we call it an empty-qualified type).
1172 // These are the result of an optimization which
1173 // removes "redundant qualifiers" from some types.
1174 // For instance, consider a "const reference". The
1175 // const there is redundant because a reference is
1176 // always const. So as a result of the optimizaton
1177 // that type is going to be transformed into an
1178 // empty-qualified reference. If we don't make that
1179 // optimization, then we risk having spurious change
1180 // reports down the road. But then, as a consequence
1181 // of that optimization, we need to sort the
1182 // empty-qualified type and its non-qualified variant
1183 // e.g, to ensure stability in the abixml output; both
1184 // types are logically equal, but here, we decide that
1185 // the empty-qualified one is topologically "less
1186 // than" the non-qualified counterpart.
1187 //
1188 // So here, type f is an empty-qualified type and type
1189 // s is its non-qualified variant. We decide that f
1190 // is topologically less than s.
1191 return true;
1192 }
1193 // Now let's peel off the pointer (or reference types) and
1194 // see if the ultimate underlying types have the same
1195 // textual representation; if not, use that as sorting
1196 // criterion.
1197 type_base *peeled_f =
1199 type_base *peeled_s =
1201
1202 s1 = peeled_f->get_cached_pretty_representation(/*internal=*/false);
1203 s2 = peeled_s->get_cached_pretty_representation(/*internal=*/false);
1204 if (s1 != s2)
1205 return s1 < s2;
1206
1207 // The underlying type of pointer/reference have the same
1208 // textual representation; let's try to peel of typedefs
1209 // as well and we'll consider sorting the result as decls.
1210 peeled_f = peel_typedef_pointer_or_reference_type(peeled_f, true);
1211 peeled_s = peel_typedef_pointer_or_reference_type(peeled_s, true);
1212
1213 s1 = peeled_f->get_cached_pretty_representation(false);
1214 s2 = peeled_s->get_cached_pretty_representation(false);
1215 if (s1 != s2)
1216 return s1 < s2;
1217 }
1218 }
1219
1222
1223 if (s1 != s2)
1224 return s1 < s2;
1225
1226 if (is_typedef(f) && is_typedef(s))
1227 {
1228 s1 = is_typedef(f)->get_underlying_type()->get_cached_pretty_representation(false);
1229 s2 = is_typedef(s)->get_underlying_type()->get_cached_pretty_representation(false);
1230 if (s1 != s2)
1231 return s1 < s2;
1232 }
1233
1236
1237 s1 = peeled_f->get_cached_pretty_representation(false);
1238 s2 = peeled_s->get_cached_pretty_representation(false);
1239
1240 if (s1 != s2)
1241 return s1 < s2;
1242
1243 if (method_type* m_f = is_method_type(peeled_f))
1244 if (method_type* m_s = is_method_type(peeled_s))
1245 {
1246 // If two method types differ from their const-ness, make the
1247 // const one come first.
1248 if (m_f->get_is_const() != m_s->get_is_const())
1249 return m_f->get_is_const();
1250
1251 // If two method types have the same name (textual
1252 // representation), make the non-static one come first.
1253 if (m_f->get_is_for_static_method() != m_s->get_is_for_static_method())
1254 return m_f->get_is_for_static_method() < m_s->get_is_for_static_method();
1255 }
1256
1257 decl_base *fd = is_decl(f);
1258 decl_base *sd = is_decl(s);
1259
1260 if (!!fd != !!sd)
1261 return fd && !sd;
1262
1263 if (!fd
1264 && f->get_translation_unit()
1265 && s->get_translation_unit())
1266 {
1267 string s1 = f->get_translation_unit()->get_absolute_path();
1268 string s2 = s->get_translation_unit()->get_absolute_path();
1269 return s1 < s2;
1270 }
1271
1272 // If all pretty representions are equal, sort by
1273 // hash value and canonical type index.
1274 hash_t h_f = peek_hash_value(*f);
1275 hash_t h_s = peek_hash_value(*s);
1276 if (h_f && h_s && *h_f != *h_s)
1277 return *h_f < *h_s;
1278
1279 size_t cti_f = get_canonical_type_index(*f);
1280 size_t cti_s = get_canonical_type_index(*s);
1281 if (cti_f != cti_s)
1282 return cti_f < cti_s;
1283
1284 // If the two types have no decls, how come we could not sort them
1285 // until now? Let's investigate.
1286 ABG_ASSERT(fd);
1287
1288 // From this point, fd and sd should be non-nil
1289 decl_topo_comp decl_comp;
1290 return decl_comp(fd, sd);
1291 }
1292}; //end struct type_topo_comp
1293
1294/// Functor used to sort types before hashing them.
1296{
1297 /// Return the rank of a given kind of IR node.
1298 ///
1299 /// The rank is used to sort a kind of IR node relative to another
1300 /// one of a different kind. For instance, a an IR node of
1301 /// BASIC_TYPE kind has a lower rank than an IR node of ENUM_TYPE
1302 /// kind.
1303 ///
1304 /// @param k the kind of a given IR node.
1305 ///
1306 /// @return the rank of the IR node.
1307 size_t
1309 {
1310 size_t result = 0;
1311
1312 if (k & type_or_decl_base::BASIC_TYPE)
1313 result = 1;
1314 if (k & type_or_decl_base::SUBRANGE_TYPE)
1315 result = 2;
1316 else if (k & type_or_decl_base::ENUM_TYPE)
1317 result = 3;
1318 else if (k & type_or_decl_base::CLASS_TYPE)
1319 result = 4;
1320 else if (k & type_or_decl_base::UNION_TYPE)
1321 result = 5;
1322 else if (k & type_or_decl_base::FUNCTION_TYPE)
1323 result = 6;
1324 else if (k & type_or_decl_base::METHOD_TYPE)
1325 result = 7;
1326 else if (k & type_or_decl_base::TYPEDEF_TYPE)
1327 result = 8;
1328 else if (k & type_or_decl_base::QUALIFIED_TYPE)
1329 result = 9;
1330 else if (k & type_or_decl_base::POINTER_TYPE)
1331 result = 10;
1332 else if (k & type_or_decl_base::REFERENCE_TYPE)
1333 result = 11;
1334 else if (k & type_or_decl_base::POINTER_TO_MEMBER_TYPE)
1335 result = 12;
1336 else if (k & type_or_decl_base::ARRAY_TYPE)
1337 result = 13;
1338
1339 return result;
1340 }
1341
1342 /// "Less Than" operator for type IR nodes.
1343 ///
1344 /// This returns true iff the first operand is less than the second
1345 /// one.
1346 ///
1347 /// IR nodes are first sorted using their rank. Two IR node of the
1348 /// same rank are then sorted using their qualified name.
1349 ///
1350 /// @param f the first operand to consider.
1351 ///
1352 /// @param s the second operand to consider.
1353 bool
1354 operator()(const type_base& f, const type_base& s)
1355 {
1356 size_t rank_f = rank(f.kind()),
1357 rank_s = rank(s.kind());
1358
1359 // If rank_f or rank_s is zero, it probably means there is a new
1360 // type IR kind that needs proper ranking.
1361 ABG_ASSERT(rank_f != 0 && rank_s != 0);
1362
1363 bool result = false;
1364 if (rank_f < rank_s)
1365 result = true;
1366 else if (rank_f == rank_s)
1367 {
1368 type_topo_comp comp;
1369 result = comp(&f,&s);
1370 }
1371 return result;
1372 }
1373
1374 /// "Less Than" operator for type IR nodes.
1375 ///
1376 /// This returns true iff the first operand is less than the second
1377 /// one.
1378 ///
1379 /// IR nodes are first sorted using their rank. Two IR node of the
1380 /// same rank are then sorted using their qualified name.
1381 ///
1382 /// @param f the first operand to consider.
1383 ///
1384 /// @param s the second operand to consider.
1385 bool
1386 operator()(const type_base* f, const type_base* s)
1387 {
1388 return operator()(*f, *s);
1389 }
1390
1391 /// "Less Than" operator for type IR nodes.
1392 ///
1393 /// This returns true iff the first operand is less than the second
1394 /// one.
1395 ///
1396 /// IR nodes are first sorted using their rank. Two IR node of the
1397 /// same rank are then sorted using their qualified name.
1398 ///
1399 /// @param f the first operand to consider.
1400 ///
1401 /// @param s the second operand to consider.
1402 bool
1403 operator()(const type_base_sptr& f, const type_base_sptr& s)
1404 {
1405 return operator()(f.get(), s.get());
1406 }
1407};//end struct sort_for_hash_functor
1408
1409/// Sort types before hashing (and then canonicalizing) them.
1410///
1411/// @param begin an iterator pointing to the beginning of the sequence
1412/// of types to sort.
1413///
1414/// @param end an iterator pointing to the end of the sequence of
1415/// types to sort.
1416template <typename IteratorType>
1417void
1419 IteratorType end)
1420{
1422 return std::stable_sort(begin, end, comp);
1423}
1424
1425void
1426sort_types_for_hash_computing_and_c14n(vector<type_base_sptr>& types);
1427
1428/// Compute the canonical type for all the IR types of the system.
1429///
1430/// After invoking this function, the time it takes to compare two
1431/// types of the IR is equivalent to the time it takes to compare
1432/// their pointer value. That is faster than performing a structural
1433/// (A.K.A. member-wise) comparison.
1434///
1435/// Note that this function performs some sanity checks after* the
1436/// canonicalization process. It ensures that at the end of the
1437/// canonicalization process, all types have been canonicalized. This
1438/// is important because the canonicalization algorithm sometimes
1439/// clears some canonical types after having speculatively set them
1440/// for performance purposes. At the end of the process however, all
1441/// types must be canonicalized, and this function detects violations
1442/// of that assertion.
1443///
1444/// @tparam input_iterator the type of the input iterator of the @p
1445/// beging and @p end.
1446///
1447/// @tparam deref_lambda a lambda function which takes in parameter
1448/// the input iterator of type @p input_iterator and dereferences it
1449/// to return the type to canonicalize.
1450///
1451/// @param begin an iterator pointing to the first type of the set of types
1452/// to canonicalize.
1453///
1454/// @param end an iterator pointing past-the-end (after the last type) of
1455/// the set of types to canonicalize.
1456///
1457/// @param deref a lambda function that knows how to dereference the
1458/// iterator @p begin to return the type to canonicalize.
1459template<typename input_iterator,
1460 typename deref_lambda>
1461void
1462canonicalize_types(const input_iterator& begin,
1463 const input_iterator& end,
1464 deref_lambda deref,
1465 bool do_log = false,
1466 bool show_stats = false)
1467{
1468 if (begin == end)
1469 return;
1470
1471 auto first_iter = begin;
1472 auto first = deref(first_iter);
1473 environment& env = const_cast<environment&>(first->get_environment());
1474
1475 env.canonicalization_started(true);
1476
1477 int i;
1478 input_iterator t;
1479 // First, let's compute the canonical type of this type.
1481 if (do_log)
1482 {
1483 std::cerr << "Canonicalizing types ...\n";
1484 tmr.start();
1485 }
1486
1487 for (t = begin,i = 0; t != end; ++t, ++i)
1488 {
1489 if (do_log && show_stats)
1490 std::cerr << "#" << std::dec << i << " ";
1491
1492 canonicalize(deref(t));
1493 }
1494
1495 env.canonicalization_is_done(true);
1496
1497 if (do_log)
1498 {
1499 tmr.stop();
1500 std::cerr << "Canonicalizing of types DONE in: " << tmr << "\n\n";
1501 tmr.start();
1502 }
1503}
1504
1505/// Hash and canonicalize a sequence of types.
1506///
1507/// Note that this function first sorts the types, then hashes them
1508/// and then canonicalizes them.
1509///
1510/// Operations must be done in that order to get predictable results.
1511///
1512/// @param begin an iterator pointing to the first element of the
1513/// sequence of types to hash and canonicalize.
1514///
1515/// @param begin an iterator pointing past-the-end of the sequence of
1516/// types to hash and canonicalize.
1517///
1518/// @param deref this is a lambda that is used to dereference the
1519/// types contained in the sequence referenced by iterators @p begin
1520/// and @p end.
1521template <typename IteratorType,
1522 typename deref_lambda>
1523void
1525 IteratorType end,
1526 deref_lambda deref,
1527 bool do_log = false,
1528 bool show_stats = false)
1529{
1531 if (do_log)
1532 {
1533 std::cerr << "sorting types before canonicalization ... \n";
1534 tmr.start();
1535 }
1536
1538
1539 if (do_log)
1540 {
1541 tmr.stop();
1542 std::cerr << "sorted types for c14n in: " << tmr << "\n\n";
1543
1544 std::cerr << "hashing types before c14n ...\n";
1545 tmr.start();
1546 }
1547
1548 for (IteratorType t = begin; t != end; ++t)
1549 if (!peek_hash_value(*deref(t)))
1550 (*t)->hash_value();
1551
1552 if (do_log)
1553 {
1554 tmr.stop();
1555 std::cerr << "hashed types in: " << tmr << "\n\n";
1556 }
1557
1558 canonicalize_types(begin, end, deref, do_log, show_stats);
1559}
1560
1561/// Sort and canonicalize a sequence of types.
1562///
1563/// Note that this function does NOT hash the types. It thus assumes
1564/// that the types are allready hashed.
1565///
1566/// Operations must be done in that order (sorting and then
1567/// canonicalizing) to get predictable results.
1568///
1569/// @param begin an iterator pointing to the first element of the
1570/// sequence of types to hash and canonicalize.
1571///
1572/// @param begin an iterator pointing past-the-end of the sequence of
1573/// types to hash and canonicalize.
1574///
1575/// @param deref this is a lambda that is used to dereference the
1576/// types contained in the sequence referenced by iterators @p begin
1577/// and @p end.
1578template <typename IteratorType,
1579 typename deref_lambda>
1580void
1582 IteratorType end,
1583 deref_lambda deref)
1584{
1586 canonicalize_types(begin, end, deref);
1587}
1588
1589// <class_or_union::priv definitions>
1591{
1592 typedef_decl_wptr naming_typedef_;
1593 data_members data_members_;
1594 data_members static_data_members_;
1595 data_members non_static_data_members_;
1596 member_functions member_functions_;
1597 // A map that associates a linkage name to a member function.
1598 string_mem_fn_sptr_map_type mem_fns_map_;
1599 // A map that associates function signature strings to member
1600 // function.
1601 string_mem_fn_ptr_map_type signature_2_mem_fn_map_;
1602 member_function_templates member_function_templates_;
1603 member_class_templates member_class_templates_;
1604 bool is_printing_flat_representation_ = false;
1605 // The set of classes which layouts are currently being compared
1606 // against this one. This is to avoid endless loops.
1607 unordered_set<type_base*> comparing_class_layouts_;
1608 priv()
1609 {}
1610
1613 : data_members_(data_mbrs),
1614 member_functions_(mbr_fns)
1615 {
1616 for (const auto& data_member: data_members_)
1617 if (get_member_is_static(data_member))
1618 static_data_members_.push_back(data_member);
1619 else
1620 non_static_data_members_.push_back(data_member);
1621 }
1622
1623 /// Mark a pair of classes or unions as being currently compared
1624 /// using the class_or_union== operator.
1625 ///
1626 /// Note that this marking business is to avoid infinite loop when
1627 /// comparing a pair of classes or unions. If via the comparison of
1628 /// a data member or a member function a recursive re-comparison of
1629 /// the class or union is attempted, the marking process helps to
1630 /// detect that infinite loop possibility and avoid it.
1631 ///
1632 /// @param first the class or union (of the pair) to mark as being
1633 /// currently compared.
1634 ///
1635 /// @param second the second class or union (of the pair) to mark as
1636 /// being currently compared.
1637 void
1639 const class_or_union& second) const
1640 {
1641 const environment& env = first.get_environment();
1642
1643 env.priv_->left_classes_being_compared_.insert(&first);
1644 env.priv_->right_classes_being_compared_.insert(&second);
1645 }
1646
1647 /// Mark a pair of classes or unions as being currently compared
1648 /// using the class_or_union== operator.
1649 ///
1650 /// Note that this marking business is to avoid infinite loop when
1651 /// comparing a pair of classes or unions. If via the comparison of
1652 /// a data member or a member function a recursive re-comparison of
1653 /// the class or union is attempted, the marking process helps to
1654 /// detect that infinite loop possibility and avoid it.
1655 ///
1656 /// @param first the class or union (of the pair) to mark as being
1657 /// currently compared.
1658 ///
1659 /// @param second the second class or union (of the pair) to mark as
1660 /// being currently compared.
1661 void
1663 const class_or_union* second) const
1664 {mark_as_being_compared(*first, *second);}
1665
1666 /// Mark a pair of classes or unions as being currently compared
1667 /// using the class_or_union== operator.
1668 ///
1669 /// Note that this marking business is to avoid infinite loop when
1670 /// comparing a pair of classes or unions. If via the comparison of
1671 /// a data member or a member function a recursive re-comparison of
1672 /// the class or union is attempted, the marking process helps to
1673 /// detect that infinite loop possibility and avoid it.
1674 ///
1675 /// @param first the class or union (of the pair) to mark as being
1676 /// currently compared.
1677 ///
1678 /// @param second the second class or union (of the pair) to mark as
1679 /// being currently compared.
1680 void
1681 mark_as_being_compared(const class_or_union_sptr& first,
1682 const class_or_union_sptr& second) const
1683 {mark_as_being_compared(*first, *second);}
1684
1685 /// If a pair of class_or_union has been previously marked as
1686 /// being compared -- via an invocation of mark_as_being_compared()
1687 /// this method unmarks it. Otherwise is has no effect.
1688 ///
1689 /// This method is not thread safe because it uses the static data
1690 /// member classes_being_compared_. If you wish to use it in a
1691 /// multi-threaded environment you should probably protect the
1692 /// access to that static data member with a mutex or somesuch.
1693 ///
1694 /// @param first the first instance of class_or_union (of the pair)
1695 /// to unmark.
1696 ///
1697 /// @param second the second instance of class_or_union (of the
1698 /// pair) to unmark.
1699 void
1701 const class_or_union& second) const
1702 {
1703 const environment& env = first.get_environment();
1704
1705 env.priv_->left_classes_being_compared_.erase(&first);
1706 env.priv_->right_classes_being_compared_.erase(&second);
1707 }
1708
1709 /// If a pair of class_or_union has been previously marked as
1710 /// being compared -- via an invocation of mark_as_being_compared()
1711 /// this method unmarks it. Otherwise is has no effect.
1712 ///
1713 /// This method is not thread safe because it uses the static data
1714 /// member classes_being_compared_. If you wish to use it in a
1715 /// multi-threaded environment you should probably protect the
1716 /// access to that static data member with a mutex or somesuch.
1717 ///
1718 /// @param first the first instance of class_or_union (of the pair)
1719 /// to unmark.
1720 ///
1721 /// @param second the second instance of class_or_union (of the
1722 /// pair) to unmark.
1723 void
1725 const class_or_union* second) const
1726 {
1727 if (!first || !second)
1728 return;
1729 unmark_as_being_compared(*first, *second);
1730 }
1731
1732 /// Test if a pair of class_or_union is being currently compared.
1733 ///
1734 ///@param first the first class or union (of the pair) to test for.
1735 ///
1736 ///@param second the second class or union (of the pair) to test for.
1737 ///
1738 /// @return true if the pair {@p first, @p second} is being
1739 /// compared, false otherwise.
1740 bool
1742 const class_or_union& second) const
1743 {
1744 const environment& env = first.get_environment();
1745
1746 return (env.priv_->left_classes_being_compared_.count(&first)
1747 || env.priv_->right_classes_being_compared_.count(&second)
1748 || env.priv_->right_classes_being_compared_.count(&first)
1749 || env.priv_->left_classes_being_compared_.count(&second));
1750 }
1751
1752 /// Test if a pair of class_or_union is being currently compared.
1753 ///
1754 ///@param first the first class or union (of the pair) to test for.
1755 ///
1756 ///@param second the second class or union (of the pair) to test for.
1757 ///
1758 /// @return true if the pair {@p first, @p second} is being
1759 /// compared, false otherwise.
1760 bool
1762 const class_or_union* second) const
1763 {
1764 if (first && second)
1765 return comparison_started(*first, *second);
1766 return false;
1767 }
1768
1769 /// Set the 'is_printing_flat_representation_' boolean to true.
1770 ///
1771 /// That boolean marks the fact that the current @ref class_or_union
1772 /// (and its sub-types graph) is being walked for the purpose of
1773 /// printing its flat representation. This is useful to detect
1774 /// cycles in the graph and avoid endless loops.
1775 void
1777 {is_printing_flat_representation_ = true;}
1778
1779 /// Set the 'is_printing_flat_representation_' boolean to false.
1780 ///
1781 /// That boolean marks the fact that the current @ref class_or_union
1782 /// (and its sub-types graph) is being walked for the purpose of
1783 /// printing its flat representation. This is useful to detect
1784 /// cycles in the graph and avoid endless loops.
1785 void
1787 {is_printing_flat_representation_ = false;}
1788
1789 /// Getter of the 'is_printing_flat_representation_' boolean.
1790 ///
1791 /// That boolean marks the fact that the current @ref class_or_union
1792 /// (and its sub-types graph) is being walked for the purpose of
1793 /// printing its flat representation. This is useful to detect
1794 /// cycles in the graph and avoid endless loops.
1795 bool
1797 {return is_printing_flat_representation_;}
1798}; // end struct class_or_union::priv
1799
1800// <function_type::priv definitions>
1801
1802/// The type of the private data of the @ref function_type type.
1804{
1805 parameters parms_;
1806 type_base_wptr return_type_;
1807 interned_string cached_name_;
1808 interned_string internal_cached_name_;
1809 interned_string temp_internal_cached_name_;
1810 bool is_pretty_printing_ = false;
1811 priv()
1812 {}
1813
1814 priv(const parameters& parms,
1815 type_base_sptr return_type)
1816 : parms_(parms),
1817 return_type_(return_type)
1818 {}
1819
1820 priv(type_base_sptr return_type)
1821 : return_type_(return_type)
1822 {}
1823
1824 /// Mark a given pair of @ref function_type as being compared.
1825 ///
1826 /// @param first the first @ref function_type of the pair being
1827 /// compared, to mark.
1828 ///
1829 /// @param second the second @ref function_type of the pair being
1830 /// compared, to mark.
1831 void
1833 const function_type& second) const
1834 {
1835 const environment& env = first.get_environment();
1836
1837 env.priv_->left_fn_types_being_compared_.insert(&first);
1838 env.priv_->right_fn_types_being_compared_.insert(&second);
1839 }
1840
1841 /// Mark a given pair of @ref function_type as being compared.
1842 ///
1843 /// @param first the first @ref function_type of the pair being
1844 /// compared, to mark.
1845 ///
1846 /// @param second the second @ref function_type of the pair being
1847 /// compared, to mark.
1848 void
1850 const function_type& second) const
1851 {
1852 const environment& env = first.get_environment();
1853
1854 env.priv_->left_fn_types_being_compared_.erase(&first);
1855 env.priv_->right_fn_types_being_compared_.erase(&second);
1856 }
1857
1858 /// Tests if a @ref function_type is currently being compared.
1859 ///
1860 /// @param type the function type to take into account.
1861 ///
1862 /// @return true if @p type is being compared.
1863 bool
1865 const function_type& second) const
1866 {
1867 const environment& env = first.get_environment();
1868
1869 return (env.priv_->left_fn_types_being_compared_.count(&first)
1870 ||
1871 env.priv_->right_fn_types_being_compared_.count(&second));
1872 }
1873
1874 /// Set the 'is_pretty_printing_' boolean to true.
1875 ///
1876 /// That boolean marks the fact that the current @ref function_type
1877 /// (and its sub-types graph) is being walked for the purpose of
1878 /// printing its flat representation. This is useful to detect
1879 /// cycles in the graph and avoid endless loops.
1880 void
1882 {is_pretty_printing_ = true;}
1883
1884 /// Set the 'is_pretty_printing_' boolean to false.
1885 ///
1886 /// That boolean marks the fact that the current @ref function_type
1887 /// (and its sub-types graph) is being walked for the purpose of
1888 /// printing its flat representation. This is useful to detect
1889 /// cycles in the graph and avoid endless loops.
1890 void
1892 {is_pretty_printing_ = false;}
1893
1894 /// Getter of the 'is_pretty_printing_' boolean.
1895 ///
1896 /// That boolean marks the fact that the current @ref function_type
1897 /// (and its sub-types graph) is being walked for the purpose of
1898 /// printing its flat representation. This is useful to detect
1899 /// cycles in the graph and avoid endless loops.
1900 bool
1902 {return is_pretty_printing_;}
1903};// end struc function_type::priv
1904
1905// </function_type::priv definitions>
1906
1907size_t
1909
1910bool
1911type_originates_from_corpus(type_base_sptr t, corpus_sptr& c);
1912} // end namespace ir
1913
1914} // end namespace abigail
1915
1916#endif // __ABG_IR_PRIV_H__
#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:1743
Simplified implementation of std::optional just enough to be used as a replacement for our purposes a...
This type abstracts the configuration information of the library.
Definition: abg-config.h:18
The interned string pool.
The abstraction of an interned string.
The base type of class_decl and union_decl.
Definition: abg-ir.h:3977
vector< method_decl_sptr > member_functions
Convenience typedef.
Definition: abg-ir.h:4008
unordered_map< string, method_decl * > string_mem_fn_ptr_map_type
Convenience typedef.
Definition: abg-ir.h:4010
vector< var_decl_sptr > data_members
Convenience typedef.
Definition: abg-ir.h:4007
unordered_map< string, method_decl_sptr > string_mem_fn_sptr_map_type
Convenience typedef.
Definition: abg-ir.h:4011
This is the abstraction of a set of translation units (themselves seen as bundles of unitary abi arte...
Definition: abg-corpus.h:25
origin get_origin() const
Getter for the origin of the corpus.
Definition: abg-corpus.cc:930
The base type of all declarations.
Definition: abg-ir.h:1585
const interned_string & get_cached_pretty_representation(bool internal=false) const
Get the pretty representation of the current decl.
Definition: abg-ir.cc:4894
friend 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
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
This is an abstraction of the set of resources necessary to manage several aspects of the internal re...
Definition: abg-ir.h:148
std::unordered_map< string, std::vector< type_base_sptr > > canonical_types_map_type
A convenience typedef for a map of canonical types. The key is the pretty representation string of a ...
Definition: abg-ir.h:158
bool canonicalization_is_done() const
Test if the canonicalization of types created out of the current environment is done.
Definition: abg-ir.cc:3531
bool canonicalization_started() const
Getter of a flag saying if the canonicalization process has started or not.
Definition: abg-ir.cc:3558
Abstraction of a function type.
Definition: abg-ir.h:3420
std::vector< parameter_sptr > parameters
Convenience typedef for a vector of parameter_sptr.
Definition: abg-ir.h:3432
The entry point to manage locations.
Definition: abg-ir.h:449
The source location of a token.
Definition: abg-ir.h:307
unsigned get_value() const
Get the value of the location.
Definition: abg-ir.h:395
Abstracts the type of a class member function.
Definition: abg-ir.h:3506
The abstraction of a qualified type.
Definition: abg-ir.h:2236
The internal representation of an integral type.
Definition: abg-ir-priv.h:49
void set_modifiers(modifiers_type)
Setter of the modifiers bitmap of the real_type.
Definition: abg-ir.cc:16819
string to_string(bool internal=false) const
Return the string representation of the current instance of real_type.
Definition: abg-ir.cc:16842
base_type get_base_type() const
Getter of the base type of the real_type.
Definition: abg-ir.cc:16805
bool operator==(const real_type &) const
Equality operator for the real_type.
Definition: abg-ir.cc:16829
real_type()
Default constructor of the real_type.
Definition: abg-ir.cc:16775
modifiers_type
The modifiers of the base types above. Several modifiers can be combined for a given base type....
Definition: abg-ir-priv.h:89
@ LONG_LONG_MODIFIER
The "long long" modifier.
Definition: abg-ir-priv.h:100
@ LONG_MODIFIER
The "long" modifier.
Definition: abg-ir-priv.h:98
@ SIGNED_MODIFIER
The "signed" modifier.
Definition: abg-ir-priv.h:92
@ UNSIGNED_MODIFIER
The "unsigned" modier.
Definition: abg-ir-priv.h:94
@ SHORT_MODIFIER
The "short" modifier.
Definition: abg-ir-priv.h:96
base_type
The possible base types of integral types. We might have forgotten many of these, so do not hesitate ...
Definition: abg-ir-priv.h:57
@ WCHAR_T_BASE_TYPE
The "wchar_t" base type.
Definition: abg-ir-priv.h:73
@ CHAR32_T_BASE_TYPE
The "char32_t" base type.
Definition: abg-ir-priv.h:71
@ FLOAT_BASE_TYPE
The "float" base type.
Definition: abg-ir-priv.h:67
@ BOOL_BASE_TYPE
The "bool" base type in C++ or "_Bool" in C11.
Definition: abg-ir-priv.h:63
@ CHAR_BASE_TYPE
The "char" base type.
Definition: abg-ir-priv.h:61
@ CHAR16_T_BASE_TYPE
The "char16_t base type.
Definition: abg-ir-priv.h:69
@ INT_BASE_TYPE
The "int" base type.
Definition: abg-ir-priv.h:59
@ ARRAY_SIZE_BASE_TYPE
The aray size type used by Clang.
Definition: abg-ir-priv.h:79
@ DOUBLE_BASE_TYPE
The "double" base type.
Definition: abg-ir-priv.h:65
modifiers_type get_modifiers() const
Getter of the modifiers bitmap of the real_type.
Definition: abg-ir.cc:16812
This is the abstraction of the set of relevant artefacts (types, variable declarations,...
Definition: abg-ir.h:695
const std::string & get_absolute_path() const
Get the concatenation of the build directory and the relative path of the translation unit.
Definition: abg-ir.cc:1341
language
The language of the translation unit.
Definition: abg-ir.h:708
shared_ptr< scope_decl > global_scope_sptr
Convenience typedef for a shared pointer on a global_scope.
Definition: abg-ir.h:704
An abstraction helper for type declarations.
Definition: abg-ir.h:2003
const interned_string & get_cached_pretty_representation(bool internal=false) const
Get the pretty representation of the current type.
Definition: abg-ir.cc:16405
This is a type that aggregates maps of all the kinds of types that are supported by libabigail.
Definition: abg-ir.h:602
const corpus * get_corpus() const
Get the corpus this ABI artifact belongs to.
Definition: abg-ir.cc:4270
enum type_or_decl_kind kind() const
Getter for the "kind" property of type_or_decl_base type.
Definition: abg-ir.cc:4114
type_or_decl_kind
This is a bitmap type which instance is meant to contain the runtime type of a given ABI artifact....
Definition: abg-ir.h:1418
const environment & get_environment() const
Getter of the environment of the current ABI artifact.
Definition: abg-ir.cc:4202
const translation_unit * get_translation_unit() const
Get the translation_unit this ABI artifact belongs to.
Definition: abg-ir.cc:4295
A type used to time various part of the libabigail system.
bool stop()
Stop the timer.
bool start()
Start the timer.
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
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_FINISHED_STATE
Hashing of given IR node started and is now done. If an ABI artifact is in this state,...
Definition: abg-hash.h:61
@ HASHING_CYCLED_TYPE_STATE
A cycle has been detected in the graph on the current node node.
Definition: abg-hash.h:46
@ 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
real_type::modifiers_type operator~(real_type::modifiers_type l)
Bitwise one's complement operator for real_type::modifiers_type.
Definition: abg-ir.cc:16567
bool is_non_canonicalized_type(const type_base *t)
Test if a given type is allowed to be non canonicalized.
Definition: abg-ir.cc:28562
weak_ptr< typedef_decl > typedef_decl_wptr
Convenience typedef for a weak pointer on a typedef_decl.
Definition: abg-fwd.h:170
hash_t peek_hash_value(const type_or_decl_base &artefact)
Get the hash value associated to an IR node.
Definition: abg-ir.cc:28535
type_base_sptr canonicalize(type_base_sptr t, bool do_log, bool show_stats)
Compute the canonical type of a given type.
Definition: abg-ir.cc:16243
unordered_map< uint64_t_pair_type, bool, uint64_t_pair_hash > type_comparison_result_type
A convenience typedef for a map which key is a pair of uint64_t and which value is a boolean....
Definition: abg-ir-priv.h:536
size_t get_canonical_type_index(const type_base &t)
Getter of the canonical type index of a given type.
Definition: abg-ir.cc:345
bool type_is_suitable_for_hash_computing(const type_base &)
Test if we should attempt to compute a hash value for a given type.
Definition: abg-ir.cc:15825
corpus::origin operator|=(corpus::origin &l, corpus::origin r)
Bitwise |= operator for the corpus::origin type.
Definition: abg-corpus.cc:1788
bool is_type(const type_or_decl_base &tod)
Test whether a declaration is a type.
Definition: abg-ir.cc:10807
weak_ptr< type_base > type_base_wptr
Convenience typedef for a weak pointer on a type_base.
Definition: abg-fwd.h:128
unordered_set< const class_or_union * > class_set_type
A convenience typedef for a set of pointer to class_or_union.
Definition: abg-ir-priv.h:527
bool type_originates_from_corpus(type_base_sptr t, corpus_sptr &c)
Test if a type originates from a corpus.
Definition: abg-ir.cc:378
bool parse_real_type(const string &type_name, real_type &type)
Parse a real type from a string.
Definition: abg-ir.cc:16760
unordered_set< const function_type * > fn_set_type
A convenience typedef for a set of pointer to function_type.
Definition: abg-ir-priv.h:530
comparison_result
The result of structural comparison of type ABI artifacts.
Definition: abg-ir-priv.h:36
type_base_sptr peel_typedef_pointer_or_reference_type(const type_base_sptr type)
Return the leaf underlying or pointed-to type node of a typedef_decl, pointer_type_def,...
Definition: abg-ir.cc:7409
void canonicalize_types(const input_iterator &begin, const input_iterator &end, deref_lambda deref, bool do_log=false, bool show_stats=false)
Compute the canonical type for all the IR types of the system.
Definition: abg-ir-priv.h:1462
void sort_and_canonicalize_types(IteratorType begin, IteratorType end, deref_lambda deref)
Sort and canonicalize a sequence of types.
Definition: abg-ir-priv.h:1581
hash_t set_or_get_cached_hash_value(const T &tod)
Set the hash value of an IR node and return it.
Definition: abg-ir-priv.h:415
typedef_decl_sptr is_typedef(const type_or_decl_base_sptr t)
Test whether a type is a typedef.
Definition: abg-ir.cc:11011
abg_compat::optional< uint64_t > hash_t
The abstraction for an 8 bytes hash value.
Definition: abg-ir.h:105
weak_ptr< corpus > corpus_wptr
Convenience typedef for a weak pointer to a corpus.
Definition: abg-fwd.h:131
type_base * peel_pointer_or_reference_type(const type_base *type, bool peel_qual_type)
Return the leaf underlying or pointed-to type node of a, pointer_type_def, reference_type_def or qual...
Definition: abg-ir.cc:7511
corpus::origin operator|(corpus::origin l, corpus::origin r)
Bitwise | operator for the corpus::origin type.
Definition: abg-corpus.cc:1774
corpus::origin operator&(corpus::origin l, corpus::origin r)
Bitwise & operator for the corpus::origin type.
Definition: abg-corpus.cc:1802
void hash_and_canonicalize_types(IteratorType begin, IteratorType end, deref_lambda deref, bool do_log=false, bool show_stats=false)
Hash and canonicalize a sequence of types.
Definition: abg-ir-priv.h:1524
decl_base * is_decl(const type_or_decl_base *d)
Test if an ABI artifact is a declaration.
Definition: abg-ir.cc:10747
void sort_types_for_hash_computing_and_c14n(IteratorType begin, IteratorType end)
Sort types before hashing (and then canonicalizing) them.
Definition: abg-ir-priv.h:1418
const location & get_artificial_or_natural_location(const decl_base *decl)
Get the artificial location of a decl.
Definition: abg-ir.cc:10071
bool compare_using_locations(const decl_base *f, const decl_base *s)
Compare decls using their locations.
Definition: abg-ir.cc:3413
bool is_unique_type(const type_base_sptr &t)
Test if a type is unique in the entire environment.
Definition: abg-ir.cc:28598
unordered_set< uint64_t_pair_type, uint64_t_pair_hash > uint64_t_pairs_set_type
A convenience typedef for a set of uint64_t_pair.
Definition: abg-ir-priv.h:524
corpus::origin operator&=(corpus::origin &l, corpus::origin r)
Bitwise &= operator for the corpus::origin type.
Definition: abg-corpus.cc:1816
method_type_sptr is_method_type(const type_or_decl_base_sptr &t)
Test whether a type is a method_type.
Definition: abg-ir.cc:11888
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:11838
bool is_ptr_ref_or_qual_type(const type_base *t)
Helper to detect if a type is either a reference, a pointer, or a qualified type.
Definition: abg-ir.cc:3396
std::pair< uint64_t, uint64_t > uint64_t_pair_type
A convenience typedef for a pair of uint64_t which is initially intended to store a pair of pointer v...
Definition: abg-ir-priv.h:520
hash_t do_hash_value(const T &tod)
Compute the hash value of an IR node and return it.
Definition: abg-ir-priv.h:341
Toplevel namespace for libabigail.
bool comparison_started(const class_or_union &first, const class_or_union &second) const
Test if a pair of class_or_union is being currently compared.
Definition: abg-ir-priv.h:1741
bool comparison_started(const class_or_union *first, const class_or_union *second) const
Test if a pair of class_or_union is being currently compared.
Definition: abg-ir-priv.h:1761
void mark_as_being_compared(const class_or_union_sptr &first, const class_or_union_sptr &second) const
Mark a pair of classes or unions as being currently compared using the class_or_union== operator.
Definition: abg-ir-priv.h:1681
void mark_as_being_compared(const class_or_union &first, const class_or_union &second) const
Mark a pair of classes or unions as being currently compared using the class_or_union== operator.
Definition: abg-ir-priv.h:1638
void mark_as_being_compared(const class_or_union *first, const class_or_union *second) const
Mark a pair of classes or unions as being currently compared using the class_or_union== operator.
Definition: abg-ir-priv.h:1662
void unmark_as_being_compared(const class_or_union *first, const class_or_union *second) const
If a pair of class_or_union has been previously marked as being compared – via an invocation of mark_...
Definition: abg-ir-priv.h:1724
bool is_printing_flat_representation() const
Getter of the 'is_printing_flat_representation_' boolean.
Definition: abg-ir-priv.h:1796
void unset_printing_flat_representation()
Set the 'is_printing_flat_representation_' boolean to false.
Definition: abg-ir-priv.h:1786
void set_printing_flat_representation()
Set the 'is_printing_flat_representation_' boolean to true.
Definition: abg-ir-priv.h:1776
void unmark_as_being_compared(const class_or_union &first, const class_or_union &second) const
If a pair of class_or_union has been previously marked as being compared – via an invocation of mark_...
Definition: abg-ir-priv.h:1700
A functor to sort decls somewhat topologically. That is, types are sorted in a way that makes the one...
Definition: abg-ir-priv.h:981
bool operator()(const decl_base *f, const decl_base *s)
The "Less Than" comparison operator of this functor.
Definition: abg-ir-priv.h:1012
bool operator()(const decl_base_sptr &f, const decl_base_sptr &s)
The "Less Than" comparison operator of this functor.
Definition: abg-ir-priv.h:1070
bool has_artificial_or_natural_location(const type_base *t)
Test if a type has an artificial or natural location.
Definition: abg-ir-priv.h:997
bool has_artificial_or_natural_location(const decl_base *d)
Test if a decl has an artificial or natural location.
Definition: abg-ir-priv.h:988
The private data of the environment type.
Definition: abg-ir-priv.h:540
bool is_type_comparison_cached(T &first, T &second, bool &r)
Retrieve the result of comparing two sub-types from the cache, if it was previously stored.
Definition: abg-ir-priv.h:743
void clear_type_comparison_results_cache()
Clear the cache type comparison results.
Definition: abg-ir-priv.h:761
void push_composite_type_comparison_operands(const type_base *left, const type_base *right)
Push a pair of operands on the stack of operands of the current type comparison, during type canonica...
Definition: abg-ir-priv.h:774
void pop_composite_type_comparison_operands(const type_base *left, const type_base *right)
Pop a pair of operands from the stack of operands to the current type comparison.
Definition: abg-ir-priv.h:797
void allow_type_comparison_results_caching(bool f)
Allow caching of the sub-types comparison results during the invocation of the equal overloads for cl...
Definition: abg-ir-priv.h:676
bool allow_type_comparison_results_caching() const
Check whether if caching of the sub-types comparison results during the invocation of the equal overl...
Definition: abg-ir-priv.h:687
void cache_type_comparison_result(T &first, T &second, bool r)
Cache the result of comparing two sub-types.
Definition: abg-ir-priv.h:711
The type of the private data of the function_type type.
Definition: abg-ir-priv.h:1804
void unset_is_pretty_printing()
Set the 'is_pretty_printing_' boolean to false.
Definition: abg-ir-priv.h:1891
void mark_as_being_compared(const function_type &first, const function_type &second) const
Mark a given pair of function_type as being compared.
Definition: abg-ir-priv.h:1832
void set_is_pretty_printing()
Set the 'is_pretty_printing_' boolean to true.
Definition: abg-ir-priv.h:1881
bool comparison_started(const function_type &first, const function_type &second) const
Tests if a function_type is currently being compared.
Definition: abg-ir-priv.h:1864
bool is_pretty_printing() const
Getter of the 'is_pretty_printing_' boolean.
Definition: abg-ir-priv.h:1901
void unmark_as_being_compared(const function_type &first, const function_type &second) const
Mark a given pair of function_type as being compared.
Definition: abg-ir-priv.h:1849
Functor used to sort types before hashing them.
Definition: abg-ir-priv.h:1296
size_t rank(enum type_or_decl_base::type_or_decl_kind k)
Return the rank of a given kind of IR node.
Definition: abg-ir-priv.h:1308
bool operator()(const type_base &f, const type_base &s)
"Less Than" operator for type IR nodes.
Definition: abg-ir-priv.h:1354
bool operator()(const type_base_sptr &f, const type_base_sptr &s)
"Less Than" operator for type IR nodes.
Definition: abg-ir-priv.h:1403
bool operator()(const type_base *f, const type_base *s)
"Less Than" operator for type IR nodes.
Definition: abg-ir-priv.h:1386
Private type to hold private members of translation_unit.
Definition: abg-ir-priv.h:152
Definition of the private data of type_base.
Definition: abg-ir-priv.h:463
The private data of type_or_decl_base.
Definition: abg-ir-priv.h:188
void set_hashing_state(hashing::hashing_state s) const
Setter of the hashing state of the current IR node.
Definition: abg-ir-priv.h:280
void is_recursive_artefact(bool f)
Setter of the property which flags the current artefact as being recursive or not.
Definition: abg-ir-priv.h:273
void kind(enum type_or_decl_kind k)
Setter of the kind of the IR node.
Definition: abg-ir-priv.h:250
void set_hash_value(hash_t h)
Setter of the hashing value of the current IR node.
Definition: abg-ir-priv.h:292
enum type_or_decl_kind kind() const
Getter of the kind of the IR node.
Definition: abg-ir-priv.h:243
priv(const environment &e, enum type_or_decl_kind k=ABSTRACT_TYPE_OR_DECL)
Constructor of the type_or_decl_base::priv private type.
Definition: abg-ir-priv.h:227
bool is_recursive_artefact() const
Getter of the property which flags the current artefact as being recursive or not.
Definition: abg-ir-priv.h:265
void force_set_hash_value(hash_t h)
Setter of the hashing value of the current IR node.
Definition: abg-ir-priv.h:317
hashing::hashing_state get_hashing_state() const
Getter the hashing state of the current IR node.
Definition: abg-ir-priv.h:257
A functor to sort types somewhat topologically. That is, types are sorted in a way that makes the one...
Definition: abg-ir-priv.h:1087
bool has_artificial_or_natural_location(const type_base *t)
Test if a type has an artificial or natural location.
Definition: abg-ir-priv.h:1103
bool has_artificial_or_natural_location(const decl_base *d)
Test if a decl has an artificial or natural location.
Definition: abg-ir-priv.h:1094
bool operator()(const type_base_sptr &f, const type_base_sptr &s)
The "Less Than" comparison operator of this functor.
Definition: abg-ir-priv.h:1118
bool operator()(const type_base *f, const type_base *s)
The "Less Than" comparison operator of this functor.
Definition: abg-ir-priv.h:1130
The hashing functor for a pair of uint64_t.
Definition: abg-ir-priv.h:506
uint64_t operator()(const std::pair< uint64_t, uint64_t > &p) const
Hashing function for a pair of uint64_t.
Definition: abg-ir-priv.h:511