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