libabigail
Loading...
Searching...
No Matches
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-2026 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
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 /// Get the number of canonical types in the system.
810 ///
811 /// @return the number of canonical types in the system.
812 size_t
814 {
815 size_t n = 0;
816 for (auto& entry : canonical_types_)
817 for(unsigned i = 0; i < entry.second.size(); ++i)
818 ++n;
819
820 return n;
821 }
822
823#ifdef WITH_DEBUG_SELF_COMPARISON
824
825 const unordered_map<string, uintptr_t>&
826 get_type_id_canonical_type_map() const
827 {return type_id_canonical_type_map_;}
828
829 unordered_map<string, uintptr_t>&
830 get_type_id_canonical_type_map()
831 {return type_id_canonical_type_map_;}
832
833 const unordered_map<uintptr_t, string>&
834 get_pointer_type_id_map() const
835 {return pointer_type_id_map_;}
836
837 unordered_map<uintptr_t, string>&
838 get_pointer_type_id_map()
839 {return pointer_type_id_map_;}
840
841 string
842 get_type_id_from_pointer(uintptr_t ptr) const
843 {
844 auto it = get_pointer_type_id_map().find(ptr);
845 if (it != get_pointer_type_id_map().end())
846 return it->second;
847 return "";
848 }
849
850 string
851 get_type_id_from_type(const type_base *t) const
852 {return get_type_id_from_pointer(reinterpret_cast<uintptr_t>(t));}
853
854 uintptr_t
855 get_canonical_type_from_type_id(const char* type_id) const
856 {
857 if (!type_id)
858 return 0;
859 auto it = get_type_id_canonical_type_map().find(type_id);
860 if (it != get_type_id_canonical_type_map().end())
861 return it->second;
862 return 0;
863 }
864
865 /// When debugging self comparison, verify that a type T
866 /// de-serialized from abixml has the same canonical type as the
867 /// initial type built from DWARF that was serialized into T in the
868 /// first place.
869 ///
870 /// @param t deserialized type (from abixml) to consider.
871 ///
872 /// @param c the canonical type that @p t has, as computed freshly
873 /// from the abixml file.
874 ///
875 /// @return true iff @p c has the same value as the canonical type
876 /// that @p t had before being serialized into abixml.
877 bool
878 check_canonical_type_from_abixml_during_self_comp(const type_base* t,
879 const type_base* c)
880 {
881 if (!t || !t->get_corpus() || !c)
882 return false;
883
884 if (!(t->get_corpus()->get_origin() == ir::corpus::NATIVE_XML_ORIGIN))
885 return false;
886
887 // Get the abixml type-id that this type was constructed from.
888 string type_id;
889 {
890 unordered_map<uintptr_t, string>::const_iterator it =
891 pointer_type_id_map_.find(reinterpret_cast<uintptr_t>(t));
892 if (it == pointer_type_id_map_.end())
893 // This type didn't have a type-id in the abixml file. Maybe
894 // it's a function or method type. So let's just keep going.
895 return true;
896 type_id = it->second;
897 }
898
899 // Get the canonical type the original in-memory type (constructed
900 // from DWARF) had when it was serialized into abixml in the first place.
901 type_base *original_canonical_type = nullptr;
902 if (!type_id.empty())
903 {
904 unordered_map<string, uintptr_t>::const_iterator it =
905 type_id_canonical_type_map_.find(type_id);
906 if (it == type_id_canonical_type_map_.end())
907 return false;
908 original_canonical_type = reinterpret_cast<type_base*>(it->second);
909 }
910
911 // Now perform the real check.
912 //
913 // We want to ensure that the canonical type 'c' of 't' is the
914 // same as the canonical type of initial in-memory type (built
915 // from DWARF) that was serialized into 't' (in abixml) in the
916 // first place.
917 if (original_canonical_type == c)
918 return true;
919
920 return false;
921 }
922
923 /// When debugging self comparison, verify that a type T
924 /// de-serialized from abixml has the same canonical type as the
925 /// initial type built from DWARF that was serialized into T in the
926 /// first place.
927 ///
928 /// @param t deserialized type (from abixml) to consider.
929 ///
930 /// @return true iff @p c is the canonical type that @p t should
931 /// have.
932 bool
933 check_abixml_canonical_type_propagation_during_self_comp(const type_base* t)
934 {
935 if (t->get_corpus()
936 && t->get_corpus()->get_origin() == ir::corpus::NATIVE_XML_ORIGIN)
937 {
938 type_base* c = t->get_naked_canonical_type();
939 if (c && !check_canonical_type_from_abixml_during_self_comp(t, c))
940 {
941 string repr = t->get_pretty_representation(true, true);
942 string type_id = get_type_id_from_type(t);
943 std::cerr << "error: canonical type propagation error for '"
944 << repr
945 << "' of type-id: '"
946 << type_id
947 << "' / type: @"
948 << std::hex
949 << t
950 << "/ canon: @"
951 << c
952 << ", should have had canonical type: "
953 << std::hex
954 << get_canonical_type_from_type_id(type_id.c_str())
955 << "\n";
956 return false;
957 }
958 }
959 return true;
960 }
961
962 /// When debugging self comparison, verify that a type T
963 /// de-serialized from abixml has the same canonical type as the
964 /// initial type built from DWARF that was serialized into T in the
965 /// first place.
966 ///
967 /// @param t deserialized type (from abixml) to consider.
968 ///
969 /// @param c the canonical type @p t should have.
970 ///
971 /// @return true iff @p c is the canonical type that @p t should
972 /// have.
973 bool
974 check_canonical_type_from_abixml_during_self_comp(const type_base_sptr& t,
975 const type_base_sptr& c)
976 {
977 return check_canonical_type_from_abixml_during_self_comp(t.get(), c.get());
978 }
979#endif
980};// end struct environment::priv
981
982bool
983compare_using_locations(const decl_base *f,
984 const decl_base *s);
985
986/// A functor to sort decls somewhat topologically. That is, types
987/// are sorted in a way that makes the ones that are defined "first"
988/// to come first.
989///
990/// The topological criteria is a lexicographic sort of the definition
991/// location of the type. For types that have no location (or the
992/// same location), it's their qualified name that is used for the
993/// lexicographic sort.
995{
996 /// Test if a decl has an artificial or natural location.
997 ///
998 /// @param d the decl to consider
999 ///
1000 /// @return true iff @p d has a location.
1001 bool
1004
1005 /// Test if a type has an artificial or natural location.
1006 ///
1007 /// @param t the type to consider
1008 ///
1009 /// @return true iff @p t has a location.
1010 bool
1012 {
1013 if (decl_base *d = is_decl(t))
1015 return false;
1016 }
1017
1018 /// The "Less Than" comparison operator of this functor.
1019 ///
1020 /// @param f the first decl to be considered for the comparison.
1021 ///
1022 /// @param s the second decl to be considered for the comparison.
1023 ///
1024 /// @return true iff @p f is less than @p s.
1025 bool
1027 const decl_base *s)
1028 {
1029 if (!!f != !!s)
1030 return f && !s;
1031
1032 if (!f)
1033 return false;
1034
1035 // Unique types that are artificially created in the environment
1036 // don't have locations. They ought to be compared on the basis
1037 // of their pretty representation before we start looking at IR
1038 // nodes' locations down the road.
1040 return (f->get_cached_pretty_representation(/*internal=*/false)
1041 < s->get_cached_pretty_representation(/*internal=*/false));
1042
1043 // If both decls come from an abixml file, keep the order they
1044 // have from that abixml file.
1047 && (((!f->get_corpus() && !s->get_corpus())
1048 || (f->get_corpus() && f->get_corpus()->get_origin() == corpus::NATIVE_XML_ORIGIN
1049 && s->get_corpus() && s->get_corpus()->get_origin() == corpus::NATIVE_XML_ORIGIN))))
1050 return compare_using_locations(f, s);
1051
1052 // If a decl has artificial location, then use that one over the
1053 // natural one.
1056
1057 if (fl.get_value() && sl.get_value())
1058 return compare_using_locations(f, s);
1059 else if (!!fl != !!sl)
1060 // So one of the decls doesn't have location data.
1061 // The first decl is less than the second if it's the one not
1062 // having location data.
1063 return !fl && sl;
1064
1065 // We reach this point if location data is useless.
1066 if (f->get_is_anonymous()
1067 && s->get_is_anonymous()
1068 && (f->get_cached_pretty_representation(/*internal=*/false)
1069 == s->get_cached_pretty_representation(/*internal=*/false)))
1070 return f->get_name() < s->get_name();
1071
1072 return (f->get_cached_pretty_representation(/*internal=*/false)
1073 < s->get_cached_pretty_representation(/*internal=*/false));
1074 }
1075
1076 /// The "Less Than" comparison operator of this functor.
1077 ///
1078 /// @param f the first decl to be considered for the comparison.
1079 ///
1080 /// @param s the second decl to be considered for the comparison.
1081 ///
1082 /// @return true iff @p f is less than @p s.
1083 bool
1084 operator()(const decl_base_sptr &f,
1085 const decl_base_sptr &s)
1086 {return operator()(f.get(), s.get());}
1087
1088}; // end struct decl_topo_comp
1089
1090bool
1092
1093/// A functor to sort types somewhat topologically. That is, types
1094/// are sorted in a way that makes the ones that are defined "first"
1095/// to come first.
1096///
1097/// The topological criteria is a lexicographic sort of the definition
1098/// location of the type. For types that have no location, it's their
1099/// qualified name that is used for the lexicographic sort.
1101{
1102 /// Test if a decl has an artificial or natural location.
1103 ///
1104 /// @param d the decl to consider
1105 ///
1106 /// @return true iff @p d has a location.
1107 bool
1110
1111 /// Test if a type has an artificial or natural location.
1112 ///
1113 /// @param t the type to consider
1114 ///
1115 /// @return true iff @p t has a location.
1116 bool
1118 {
1119 if (decl_base *d = is_decl(t))
1121 return false;
1122 }
1123
1124 /// The "Less Than" comparison operator of this functor.
1125 ///
1126 /// @param f the first type to be considered for the comparison.
1127 ///
1128 /// @param s the second type to be considered for the comparison.
1129 ///
1130 /// @return true iff @p f is less than @p s.
1131 bool
1132 operator()(const type_base_sptr &f,
1133 const type_base_sptr &s)
1134 {return operator()(f.get(), s.get());}
1135
1136 /// The "Less Than" comparison operator of this functor.
1137 ///
1138 /// @param f the first type to be considered for the comparison.
1139 ///
1140 /// @param s the second type to be considered for the comparison.
1141 ///
1142 /// @return true iff @p f is less than @p s.
1143 bool
1145 const type_base *s)
1146 {
1147 if (f == s || !f || !s)
1148 return false;
1149
1150 // If both decls come from an abixml file, keep the order they
1151 // have from that abixml file.
1152 if (is_decl(f) && is_decl(s)
1155 && ((!f->get_corpus() && !s->get_corpus())
1156 || (f->get_corpus()
1157 && f->get_corpus()->get_origin() == corpus::NATIVE_XML_ORIGIN
1158 && s->get_corpus()
1159 && (s->get_corpus()->get_origin()
1160 == corpus::NATIVE_XML_ORIGIN))))
1162
1163 bool f_is_ptr_ref_or_qual = is_ptr_ref_or_qual_type(f);
1164 bool s_is_ptr_ref_or_qual = is_ptr_ref_or_qual_type(s);
1165
1166 if (f_is_ptr_ref_or_qual != s_is_ptr_ref_or_qual)
1167 return !f_is_ptr_ref_or_qual && s_is_ptr_ref_or_qual;
1168
1169 if (f_is_ptr_ref_or_qual && s_is_ptr_ref_or_qual
1172 {
1173 interned_string s1 = f->get_cached_pretty_representation(/*internal=*/false);
1174 interned_string s2 = s->get_cached_pretty_representation(/*internal=*/false);
1175 if (s1 == s2)
1176 {
1178 {
1179 if (q->get_cv_quals() == qualified_type_def::CV_NONE)
1180 if (!is_qualified_type(s))
1181 // We are looking at two types that are the result of
1182 // an optimization that happens during the IR
1183 // construction. Namely, type f is a cv-qualified
1184 // type with no qualifier (no const, no volatile, no
1185 // nothing, we call it an empty-qualified type).
1186 // These are the result of an optimization which
1187 // removes "redundant qualifiers" from some types.
1188 // For instance, consider a "const reference". The
1189 // const there is redundant because a reference is
1190 // always const. So as a result of the optimizaton
1191 // that type is going to be transformed into an
1192 // empty-qualified reference. If we don't make that
1193 // optimization, then we risk having spurious change
1194 // reports down the road. But then, as a consequence
1195 // of that optimization, we need to sort the
1196 // empty-qualified type and its non-qualified variant
1197 // e.g, to ensure stability in the abixml output; both
1198 // types are logically equal, but here, we decide that
1199 // the empty-qualified one is topologically "less
1200 // than" the non-qualified counterpart.
1201 //
1202 // So here, type f is an empty-qualified type and type
1203 // s is its non-qualified variant. We decide that f
1204 // is topologically less than s.
1205 return true;
1206 }
1207 // Now let's peel off the pointer (or reference types) and
1208 // see if the ultimate underlying types have the same
1209 // textual representation; if not, use that as sorting
1210 // criterion.
1211 type_base *peeled_f =
1213 type_base *peeled_s =
1215
1216 s1 = peeled_f->get_cached_pretty_representation(/*internal=*/false);
1217 s2 = peeled_s->get_cached_pretty_representation(/*internal=*/false);
1218 if (s1 != s2)
1219 return s1 < s2;
1220
1221 // The underlying type of pointer/reference have the same
1222 // textual representation; let's try to peel of typedefs
1223 // as well and we'll consider sorting the result as decls.
1224 peeled_f = peel_typedef_pointer_or_reference_type(peeled_f, true);
1225 peeled_s = peel_typedef_pointer_or_reference_type(peeled_s, true);
1226
1227 s1 = peeled_f->get_cached_pretty_representation(false);
1228 s2 = peeled_s->get_cached_pretty_representation(false);
1229 if (s1 != s2)
1230 return s1 < s2;
1231 }
1232 }
1233
1236
1237 if (s1 != s2)
1238 return s1 < s2;
1239
1240 if (is_typedef(f) && is_typedef(s))
1241 {
1242 s1 = is_typedef(f)->get_underlying_type()->get_cached_pretty_representation(false);
1243 s2 = is_typedef(s)->get_underlying_type()->get_cached_pretty_representation(false);
1244 if (s1 != s2)
1245 return s1 < s2;
1246 }
1247
1250
1251 s1 = peeled_f->get_cached_pretty_representation(false);
1252 s2 = peeled_s->get_cached_pretty_representation(false);
1253
1254 if (s1 != s2)
1255 return s1 < s2;
1256
1257 if (method_type* m_f = is_method_type(peeled_f))
1258 if (method_type* m_s = is_method_type(peeled_s))
1259 {
1260 // If two method types differ from their const-ness, make the
1261 // const one come first.
1262 if (m_f->get_is_const() != m_s->get_is_const())
1263 return m_f->get_is_const();
1264
1265 // If two method types have the same name (textual
1266 // representation), make the non-static one come first.
1267 if (m_f->get_is_for_static_method() != m_s->get_is_for_static_method())
1268 return m_f->get_is_for_static_method() < m_s->get_is_for_static_method();
1269 }
1270
1271 decl_base *fd = is_decl(f);
1272 decl_base *sd = is_decl(s);
1273
1274 if (!!fd != !!sd)
1275 return fd && !sd;
1276
1277 if (!fd
1278 && f->get_translation_unit()
1279 && s->get_translation_unit())
1280 {
1281 string s1 = f->get_translation_unit()->get_absolute_path();
1282 string s2 = s->get_translation_unit()->get_absolute_path();
1283 return s1 < s2;
1284 }
1285
1286 // If all pretty representions are equal, sort by
1287 // hash value and canonical type index.
1288 hash_t h_f = peek_hash_value(*f);
1289 hash_t h_s = peek_hash_value(*s);
1290 if (h_f && h_s && *h_f != *h_s)
1291 return *h_f < *h_s;
1292
1293 size_t cti_f = get_canonical_type_index(*f);
1294 size_t cti_s = get_canonical_type_index(*s);
1295 if (cti_f != cti_s)
1296 return cti_f < cti_s;
1297
1298 // If the two types have no decls, how come we could not sort them
1299 // until now? Let's investigate.
1300 ABG_ASSERT(fd);
1301
1302 // From this point, fd and sd should be non-nil
1303 decl_topo_comp decl_comp;
1304 return decl_comp(fd, sd);
1305 }
1306}; //end struct type_topo_comp
1307
1308/// Functor used to sort types before hashing them.
1310{
1311 /// Return the rank of a given kind of IR node.
1312 ///
1313 /// The rank is used to sort a kind of IR node relative to another
1314 /// one of a different kind. For instance, a an IR node of
1315 /// BASIC_TYPE kind has a lower rank than an IR node of ENUM_TYPE
1316 /// kind.
1317 ///
1318 /// @param k the kind of a given IR node.
1319 ///
1320 /// @return the rank of the IR node.
1321 size_t
1323 {
1324 size_t result = 0;
1325
1326 if (k & type_or_decl_base::BASIC_TYPE)
1327 result = 1;
1328 if (k & type_or_decl_base::SUBRANGE_TYPE)
1329 result = 2;
1330 else if (k & type_or_decl_base::ENUM_TYPE)
1331 result = 3;
1332 else if (k & type_or_decl_base::CLASS_TYPE)
1333 result = 4;
1334 else if (k & type_or_decl_base::UNION_TYPE)
1335 result = 5;
1336 else if (k & type_or_decl_base::FUNCTION_TYPE)
1337 result = 6;
1338 else if (k & type_or_decl_base::METHOD_TYPE)
1339 result = 7;
1340 else if (k & type_or_decl_base::TYPEDEF_TYPE)
1341 result = 8;
1342 else if (k & type_or_decl_base::QUALIFIED_TYPE)
1343 result = 9;
1344 else if (k & type_or_decl_base::POINTER_TYPE)
1345 result = 10;
1346 else if (k & type_or_decl_base::REFERENCE_TYPE)
1347 result = 11;
1348 else if (k & type_or_decl_base::POINTER_TO_MEMBER_TYPE)
1349 result = 12;
1350 else if (k & type_or_decl_base::ARRAY_TYPE)
1351 result = 13;
1352
1353 return result;
1354 }
1355
1356 /// "Less Than" operator for type IR nodes.
1357 ///
1358 /// This returns true iff the first operand is less than the second
1359 /// one.
1360 ///
1361 /// IR nodes are first sorted using their rank. Two IR node of the
1362 /// same rank are then sorted using their qualified name.
1363 ///
1364 /// @param f the first operand to consider.
1365 ///
1366 /// @param s the second operand to consider.
1367 bool
1368 operator()(const type_base& f, const type_base& s)
1369 {
1370 size_t rank_f = rank(f.kind()),
1371 rank_s = rank(s.kind());
1372
1373 // If rank_f or rank_s is zero, it probably means there is a new
1374 // type IR kind that needs proper ranking.
1375 ABG_ASSERT(rank_f != 0 && rank_s != 0);
1376
1377 bool result = false;
1378 if (rank_f < rank_s)
1379 result = true;
1380 else if (rank_f == rank_s)
1381 {
1382 type_topo_comp comp;
1383 result = comp(&f,&s);
1384 }
1385 return result;
1386 }
1387
1388 /// "Less Than" operator for type IR nodes.
1389 ///
1390 /// This returns true iff the first operand is less than the second
1391 /// one.
1392 ///
1393 /// IR nodes are first sorted using their rank. Two IR node of the
1394 /// same rank are then sorted using their qualified name.
1395 ///
1396 /// @param f the first operand to consider.
1397 ///
1398 /// @param s the second operand to consider.
1399 bool
1400 operator()(const type_base* f, const type_base* s)
1401 {
1402 return operator()(*f, *s);
1403 }
1404
1405 /// "Less Than" operator for type IR nodes.
1406 ///
1407 /// This returns true iff the first operand is less than the second
1408 /// one.
1409 ///
1410 /// IR nodes are first sorted using their rank. Two IR node of the
1411 /// same rank are then sorted using their qualified name.
1412 ///
1413 /// @param f the first operand to consider.
1414 ///
1415 /// @param s the second operand to consider.
1416 bool
1417 operator()(const type_base_sptr& f, const type_base_sptr& s)
1418 {
1419 return operator()(f.get(), s.get());
1420 }
1421};//end struct sort_for_hash_functor
1422
1423/// Sort types before hashing (and then canonicalizing) them.
1424///
1425/// @param begin an iterator pointing to the beginning of the sequence
1426/// of types to sort.
1427///
1428/// @param end an iterator pointing to the end of the sequence of
1429/// types to sort.
1430template <typename IteratorType>
1431void
1433 IteratorType end)
1434{
1436 return std::stable_sort(begin, end, comp);
1437}
1438
1439void
1440sort_types_for_hash_computing_and_c14n(vector<type_base_sptr>& types);
1441
1442/// Compute the canonical type for all the IR types of the system.
1443///
1444/// After invoking this function, the time it takes to compare two
1445/// types of the IR is equivalent to the time it takes to compare
1446/// their pointer value. That is faster than performing a structural
1447/// (A.K.A. member-wise) comparison.
1448///
1449/// Note that this function performs some sanity checks after* the
1450/// canonicalization process. It ensures that at the end of the
1451/// canonicalization process, all types have been canonicalized. This
1452/// is important because the canonicalization algorithm sometimes
1453/// clears some canonical types after having speculatively set them
1454/// for performance purposes. At the end of the process however, all
1455/// types must be canonicalized, and this function detects violations
1456/// of that assertion.
1457///
1458/// @tparam input_iterator the type of the input iterator of the @p
1459/// beging and @p end.
1460///
1461/// @tparam deref_lambda a lambda function which takes in parameter
1462/// the input iterator of type @p input_iterator and dereferences it
1463/// to return the type to canonicalize.
1464///
1465/// @param begin an iterator pointing to the first type of the set of types
1466/// to canonicalize.
1467///
1468/// @param end an iterator pointing past-the-end (after the last type) of
1469/// the set of types to canonicalize.
1470///
1471/// @param deref a lambda function that knows how to dereference the
1472/// iterator @p begin to return the type to canonicalize.
1473template<typename input_iterator,
1474 typename deref_lambda>
1475void
1476canonicalize_types(const input_iterator& begin,
1477 const input_iterator& end,
1478 deref_lambda deref,
1479 bool do_log = false,
1480 bool show_stats = false)
1481{
1482 if (begin == end)
1483 return;
1484
1485 auto first_iter = begin;
1486 auto first = deref(first_iter);
1487 environment& env = const_cast<environment&>(first->get_environment());
1488
1489 env.canonicalization_started(true);
1490
1491 int i;
1492 input_iterator t;
1493 // First, let's compute the canonical type of this type.
1495 if (do_log)
1496 {
1497 std::cerr << "Canonicalizing types ...\n";
1498 tmr.start();
1499 }
1500
1501 for (t = begin,i = 0; t != end; ++t, ++i)
1502 {
1503 if (do_log && show_stats)
1504 std::cerr << "#" << std::dec << i << " ";
1505
1506 canonicalize(deref(t));
1507 }
1508
1509 env.canonicalization_is_done(true);
1510
1511 if (do_log)
1512 {
1513 tmr.stop();
1514 std::cerr << "Canonicalizing of types DONE in: " << tmr << "\n\n";
1515 tmr.start();
1516 }
1517}
1518
1519/// Hash and canonicalize a sequence of types.
1520///
1521/// Note that this function first sorts the types, then hashes them
1522/// and then canonicalizes them.
1523///
1524/// Operations must be done in that order to get predictable results.
1525///
1526/// @param begin an iterator pointing to the first element of the
1527/// sequence of types to hash and canonicalize.
1528///
1529/// @param begin an iterator pointing past-the-end of the sequence of
1530/// types to hash and canonicalize.
1531///
1532/// @param deref this is a lambda that is used to dereference the
1533/// types contained in the sequence referenced by iterators @p begin
1534/// and @p end.
1535template <typename IteratorType,
1536 typename deref_lambda>
1537void
1539 IteratorType end,
1540 deref_lambda deref,
1541 bool do_log = false,
1542 bool show_stats = false)
1543{
1545 if (do_log)
1546 {
1547 std::cerr << "sorting types before canonicalization ... \n";
1548 tmr.start();
1549 }
1550
1552
1553 if (do_log)
1554 {
1555 tmr.stop();
1556 std::cerr << "sorted types for c14n in: " << tmr << "\n\n";
1557
1558 std::cerr << "hashing types before c14n ...\n";
1559 tmr.start();
1560 }
1561
1562 for (IteratorType t = begin; t != end; ++t)
1563 if (!peek_hash_value(*deref(t)))
1564 (*t)->hash_value();
1565
1566 if (do_log)
1567 {
1568 tmr.stop();
1569 std::cerr << "hashed types in: " << tmr << "\n\n";
1570 }
1571
1572 canonicalize_types(begin, end, deref, do_log, show_stats);
1573}
1574
1575/// Sort and canonicalize a sequence of types.
1576///
1577/// Note that this function does NOT hash the types. It thus assumes
1578/// that the types are allready hashed.
1579///
1580/// Operations must be done in that order (sorting and then
1581/// canonicalizing) to get predictable results.
1582///
1583/// @param begin an iterator pointing to the first element of the
1584/// sequence of types to hash and canonicalize.
1585///
1586/// @param begin an iterator pointing past-the-end of the sequence of
1587/// types to hash and canonicalize.
1588///
1589/// @param deref this is a lambda that is used to dereference the
1590/// types contained in the sequence referenced by iterators @p begin
1591/// and @p end.
1592template <typename IteratorType,
1593 typename deref_lambda>
1594void
1596 IteratorType end,
1597 deref_lambda deref)
1598{
1600 canonicalize_types(begin, end, deref);
1601}
1602
1603// <class_or_union::priv definitions>
1605{
1606 typedef_decl_wptr naming_typedef_;
1607 data_members data_members_;
1608 data_members static_data_members_;
1609 data_members non_static_data_members_;
1610 member_functions member_functions_;
1611 // A map that associates a linkage name to a member function.
1612 string_mem_fn_sptr_map_type mem_fns_map_;
1613 // A map that associates function signature strings to member
1614 // function.
1615 string_mem_fn_ptr_map_type signature_2_mem_fn_map_;
1616 member_function_templates member_function_templates_;
1617 member_class_templates member_class_templates_;
1618 bool is_printing_flat_representation_ = false;
1619 // The set of classes which layouts are currently being compared
1620 // against this one. This is to avoid endless loops.
1621 unordered_set<type_base*> comparing_class_layouts_;
1622 priv()
1623 {}
1624
1627 : data_members_(data_mbrs),
1628 member_functions_(mbr_fns)
1629 {
1630 for (const auto& data_member: data_members_)
1631 if (get_member_is_static(data_member))
1632 static_data_members_.push_back(data_member);
1633 else
1634 non_static_data_members_.push_back(data_member);
1635 }
1636
1637 /// Mark a pair of classes or unions as being currently compared
1638 /// using the class_or_union== operator.
1639 ///
1640 /// Note that this marking business is to avoid infinite loop when
1641 /// comparing a pair of classes or unions. If via the comparison of
1642 /// a data member or a member function a recursive re-comparison of
1643 /// the class or union is attempted, the marking process helps to
1644 /// detect that infinite loop possibility and avoid it.
1645 ///
1646 /// @param first the class or union (of the pair) to mark as being
1647 /// currently compared.
1648 ///
1649 /// @param second the second class or union (of the pair) to mark as
1650 /// being currently compared.
1651 void
1653 const class_or_union& second) const
1654 {
1655 const environment& env = first.get_environment();
1656
1657 env.priv_->left_classes_being_compared_.insert(&first);
1658 env.priv_->right_classes_being_compared_.insert(&second);
1659 }
1660
1661 /// Mark a pair of classes or unions as being currently compared
1662 /// using the class_or_union== operator.
1663 ///
1664 /// Note that this marking business is to avoid infinite loop when
1665 /// comparing a pair of classes or unions. If via the comparison of
1666 /// a data member or a member function a recursive re-comparison of
1667 /// the class or union is attempted, the marking process helps to
1668 /// detect that infinite loop possibility and avoid it.
1669 ///
1670 /// @param first the class or union (of the pair) to mark as being
1671 /// currently compared.
1672 ///
1673 /// @param second the second class or union (of the pair) to mark as
1674 /// being currently compared.
1675 void
1677 const class_or_union* second) const
1678 {mark_as_being_compared(*first, *second);}
1679
1680 /// Mark a pair of classes or unions as being currently compared
1681 /// using the class_or_union== operator.
1682 ///
1683 /// Note that this marking business is to avoid infinite loop when
1684 /// comparing a pair of classes or unions. If via the comparison of
1685 /// a data member or a member function a recursive re-comparison of
1686 /// the class or union is attempted, the marking process helps to
1687 /// detect that infinite loop possibility and avoid it.
1688 ///
1689 /// @param first the class or union (of the pair) to mark as being
1690 /// currently compared.
1691 ///
1692 /// @param second the second class or union (of the pair) to mark as
1693 /// being currently compared.
1694 void
1695 mark_as_being_compared(const class_or_union_sptr& first,
1696 const class_or_union_sptr& second) const
1697 {mark_as_being_compared(*first, *second);}
1698
1699 /// If a pair of class_or_union has been previously marked as
1700 /// being compared -- via an invocation of mark_as_being_compared()
1701 /// this method unmarks it. Otherwise is has no effect.
1702 ///
1703 /// This method is not thread safe because it uses the static data
1704 /// member classes_being_compared_. If you wish to use it in a
1705 /// multi-threaded environment you should probably protect the
1706 /// access to that static data member with a mutex or somesuch.
1707 ///
1708 /// @param first the first instance of class_or_union (of the pair)
1709 /// to unmark.
1710 ///
1711 /// @param second the second instance of class_or_union (of the
1712 /// pair) to unmark.
1713 void
1715 const class_or_union& second) const
1716 {
1717 const environment& env = first.get_environment();
1718
1719 env.priv_->left_classes_being_compared_.erase(&first);
1720 env.priv_->right_classes_being_compared_.erase(&second);
1721 }
1722
1723 /// If a pair of class_or_union has been previously marked as
1724 /// being compared -- via an invocation of mark_as_being_compared()
1725 /// this method unmarks it. Otherwise is has no effect.
1726 ///
1727 /// This method is not thread safe because it uses the static data
1728 /// member classes_being_compared_. If you wish to use it in a
1729 /// multi-threaded environment you should probably protect the
1730 /// access to that static data member with a mutex or somesuch.
1731 ///
1732 /// @param first the first instance of class_or_union (of the pair)
1733 /// to unmark.
1734 ///
1735 /// @param second the second instance of class_or_union (of the
1736 /// pair) to unmark.
1737 void
1739 const class_or_union* second) const
1740 {
1741 if (!first || !second)
1742 return;
1743 unmark_as_being_compared(*first, *second);
1744 }
1745
1746 /// Test if a pair of class_or_union is being currently compared.
1747 ///
1748 ///@param first the first class or union (of the pair) to test for.
1749 ///
1750 ///@param second the second class or union (of the pair) to test for.
1751 ///
1752 /// @return true if the pair {@p first, @p second} is being
1753 /// compared, false otherwise.
1754 bool
1756 const class_or_union& second) const
1757 {
1758 const environment& env = first.get_environment();
1759
1760 return (env.priv_->left_classes_being_compared_.count(&first)
1761 || env.priv_->right_classes_being_compared_.count(&second)
1762 || env.priv_->right_classes_being_compared_.count(&first)
1763 || env.priv_->left_classes_being_compared_.count(&second));
1764 }
1765
1766 /// Test if a pair of class_or_union is being currently compared.
1767 ///
1768 ///@param first the first class or union (of the pair) to test for.
1769 ///
1770 ///@param second the second class or union (of the pair) to test for.
1771 ///
1772 /// @return true if the pair {@p first, @p second} is being
1773 /// compared, false otherwise.
1774 bool
1776 const class_or_union* second) const
1777 {
1778 if (first && second)
1779 return comparison_started(*first, *second);
1780 return false;
1781 }
1782
1783 /// Set the 'is_printing_flat_representation_' boolean to true.
1784 ///
1785 /// That boolean marks the fact that the current @ref class_or_union
1786 /// (and its sub-types graph) is being walked for the purpose of
1787 /// printing its flat representation. This is useful to detect
1788 /// cycles in the graph and avoid endless loops.
1789 void
1791 {is_printing_flat_representation_ = true;}
1792
1793 /// Set the 'is_printing_flat_representation_' boolean to false.
1794 ///
1795 /// That boolean marks the fact that the current @ref class_or_union
1796 /// (and its sub-types graph) is being walked for the purpose of
1797 /// printing its flat representation. This is useful to detect
1798 /// cycles in the graph and avoid endless loops.
1799 void
1801 {is_printing_flat_representation_ = false;}
1802
1803 /// Getter of the 'is_printing_flat_representation_' boolean.
1804 ///
1805 /// That boolean marks the fact that the current @ref class_or_union
1806 /// (and its sub-types graph) is being walked for the purpose of
1807 /// printing its flat representation. This is useful to detect
1808 /// cycles in the graph and avoid endless loops.
1809 bool
1811 {return is_printing_flat_representation_;}
1812}; // end struct class_or_union::priv
1813
1814// <function_type::priv definitions>
1815
1816/// The type of the private data of the @ref function_type type.
1818{
1819 parameters parms_;
1820 type_base_wptr return_type_;
1821 interned_string cached_name_;
1822 interned_string internal_cached_name_;
1823 interned_string temp_internal_cached_name_;
1824 bool is_pretty_printing_ = false;
1825 priv()
1826 {}
1827
1828 priv(const parameters& parms,
1829 type_base_sptr return_type)
1830 : parms_(parms),
1831 return_type_(return_type)
1832 {}
1833
1834 priv(type_base_sptr return_type)
1835 : return_type_(return_type)
1836 {}
1837
1838 /// Mark a given pair of @ref function_type as being compared.
1839 ///
1840 /// @param first the first @ref function_type of the pair being
1841 /// compared, to mark.
1842 ///
1843 /// @param second the second @ref function_type of the pair being
1844 /// compared, to mark.
1845 void
1847 const function_type& second) const
1848 {
1849 const environment& env = first.get_environment();
1850
1851 env.priv_->left_fn_types_being_compared_.insert(&first);
1852 env.priv_->right_fn_types_being_compared_.insert(&second);
1853 }
1854
1855 /// Mark a given pair of @ref function_type as being compared.
1856 ///
1857 /// @param first the first @ref function_type of the pair being
1858 /// compared, to mark.
1859 ///
1860 /// @param second the second @ref function_type of the pair being
1861 /// compared, to mark.
1862 void
1864 const function_type& second) const
1865 {
1866 const environment& env = first.get_environment();
1867
1868 env.priv_->left_fn_types_being_compared_.erase(&first);
1869 env.priv_->right_fn_types_being_compared_.erase(&second);
1870 }
1871
1872 /// Tests if a @ref function_type is currently being compared.
1873 ///
1874 /// @param type the function type to take into account.
1875 ///
1876 /// @return true if @p type is being compared.
1877 bool
1879 const function_type& second) const
1880 {
1881 const environment& env = first.get_environment();
1882
1883 return (env.priv_->left_fn_types_being_compared_.count(&first)
1884 ||
1885 env.priv_->right_fn_types_being_compared_.count(&second));
1886 }
1887
1888 /// Set the 'is_pretty_printing_' boolean to true.
1889 ///
1890 /// That boolean marks the fact that the current @ref function_type
1891 /// (and its sub-types graph) is being walked for the purpose of
1892 /// printing its flat representation. This is useful to detect
1893 /// cycles in the graph and avoid endless loops.
1894 void
1896 {is_pretty_printing_ = true;}
1897
1898 /// Set the 'is_pretty_printing_' boolean to false.
1899 ///
1900 /// That boolean marks the fact that the current @ref function_type
1901 /// (and its sub-types graph) is being walked for the purpose of
1902 /// printing its flat representation. This is useful to detect
1903 /// cycles in the graph and avoid endless loops.
1904 void
1906 {is_pretty_printing_ = false;}
1907
1908 /// Getter of the 'is_pretty_printing_' boolean.
1909 ///
1910 /// That boolean marks the fact that the current @ref function_type
1911 /// (and its sub-types graph) is being walked for the purpose of
1912 /// printing its flat representation. This is useful to detect
1913 /// cycles in the graph and avoid endless loops.
1914 bool
1916 {return is_pretty_printing_;}
1917};// end struc function_type::priv
1918
1919// </function_type::priv definitions>
1920
1921size_t
1923
1924bool
1925type_originates_from_corpus(type_base_sptr t, corpus_sptr& c);
1926} // end namespace ir
1927
1928} // end namespace abigail
1929
1930#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:3967
vector< method_decl_sptr > member_functions
Convenience typedef.
Definition abg-ir.h:3998
unordered_map< string, method_decl * > string_mem_fn_ptr_map_type
Convenience typedef.
Definition abg-ir.h:4000
vector< var_decl_sptr > data_members
Convenience typedef.
Definition abg-ir.h:3997
unordered_map< string, method_decl_sptr > string_mem_fn_sptr_map_type
Convenience typedef.
Definition abg-ir.h:4001
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.
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:4901
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:5582
virtual const interned_string & get_name() const
Getter for the name of the current decl.
Definition abg-ir.cc:4818
bool get_is_anonymous() const
Test if the current declaration is anonymous.
Definition abg-ir.cc:4675
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:3538
bool canonicalization_started() const
Getter of a flag saying if the canonicalization process has started or not.
Definition abg-ir.cc:3565
Abstraction of a function type.
Definition abg-ir.h:3410
std::vector< parameter_sptr > parameters
Convenience typedef for a vector of parameter_sptr.
Definition abg-ir.h:3422
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:3496
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:16837
string to_string(bool internal=false) const
Return the string representation of the current instance of real_type.
Definition abg-ir.cc:16860
base_type get_base_type() const
Getter of the base type of the real_type.
Definition abg-ir.cc:16823
bool operator==(const real_type &) const
Equality operator for the real_type.
Definition abg-ir.cc:16847
real_type()
Default constructor of the real_type.
Definition abg-ir.cc:16793
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.
@ 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:16830
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:16423
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:4277
enum type_or_decl_kind kind() const
Getter for the "kind" property of type_or_decl_base type.
Definition abg-ir.cc:4121
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:4209
const translation_unit * get_translation_unit() const
Get the translation_unit this ABI artifact belongs to.
Definition abg-ir.cc:4302
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
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:16585
bool is_non_canonicalized_type(const type_base *t)
Test if a given type is allowed to be non canonicalized.
Definition abg-ir.cc:28565
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:28538
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:16261
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....
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:15835
corpus::origin operator|=(corpus::origin &l, corpus::origin r)
Bitwise |= operator for the corpus::origin type.
bool is_type(const type_or_decl_base &tod)
Test whether a declaration is a type.
Definition abg-ir.cc:10817
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.
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:16778
unordered_set< const function_type * > fn_set_type
A convenience typedef for a set of pointer to function_type.
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:7416
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.
void sort_and_canonicalize_types(IteratorType begin, IteratorType end, deref_lambda deref)
Sort and canonicalize a sequence of types.
hash_t set_or_get_cached_hash_value(const T &tod)
Set the hash value of an IR node and return it.
typedef_decl_sptr is_typedef(const type_or_decl_base_sptr t)
Test whether a type is a typedef.
Definition abg-ir.cc:11021
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:7518
corpus::origin operator|(corpus::origin l, corpus::origin r)
Bitwise | operator for the corpus::origin type.
corpus::origin operator&(corpus::origin l, corpus::origin r)
Bitwise & operator for the corpus::origin type.
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.
decl_base * is_decl(const type_or_decl_base *d)
Test if an ABI artifact is a declaration.
Definition abg-ir.cc:10757
void sort_types_for_hash_computing_and_c14n(IteratorType begin, IteratorType end)
Sort types before hashing (and then canonicalizing) them.
const location & get_artificial_or_natural_location(const decl_base *decl)
Get the artificial location of a decl.
Definition abg-ir.cc:10078
bool compare_using_locations(const decl_base *f, const decl_base *s)
Compare decls using their locations.
Definition abg-ir.cc:3420
bool is_unique_type(const type_base_sptr &t)
Test if a type is unique in the entire environment.
Definition abg-ir.cc:28601
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.
corpus::origin operator&=(corpus::origin &l, corpus::origin r)
Bitwise &= operator for the corpus::origin type.
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:11898
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:11848
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:3403
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...
hash_t do_hash_value(const T &tod)
Compute the hash value of an IR node and return it.
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.
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.
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.
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.
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.
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_...
bool is_printing_flat_representation() const
Getter of the 'is_printing_flat_representation_' boolean.
void unset_printing_flat_representation()
Set the 'is_printing_flat_representation_' boolean to false.
void set_printing_flat_representation()
Set the 'is_printing_flat_representation_' boolean to true.
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_...
A functor to sort decls somewhat topologically. That is, types are sorted in a way that makes the one...
bool operator()(const decl_base *f, const decl_base *s)
The "Less Than" comparison operator of this functor.
bool operator()(const decl_base_sptr &f, const decl_base_sptr &s)
The "Less Than" comparison operator of this functor.
bool has_artificial_or_natural_location(const type_base *t)
Test if a type has an artificial or natural location.
bool has_artificial_or_natural_location(const decl_base *d)
Test if a decl has an artificial or natural location.
The private data of the environment type.
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.
void clear_type_comparison_results_cache()
Clear the cache type comparison results.
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...
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.
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...
bool allow_type_comparison_results_caching() const
Check whether if caching of the sub-types comparison results during the invocation of the equal overl...
void cache_type_comparison_result(T &first, T &second, bool r)
Cache the result of comparing two sub-types.
size_t get_number_of_canonical_types()
Get the number of canonical types in the system.
The type of the private data of the function_type type.
void unset_is_pretty_printing()
Set the 'is_pretty_printing_' boolean to false.
void mark_as_being_compared(const function_type &first, const function_type &second) const
Mark a given pair of function_type as being compared.
void set_is_pretty_printing()
Set the 'is_pretty_printing_' boolean to true.
bool comparison_started(const function_type &first, const function_type &second) const
Tests if a function_type is currently being compared.
bool is_pretty_printing() const
Getter of the 'is_pretty_printing_' boolean.
void unmark_as_being_compared(const function_type &first, const function_type &second) const
Mark a given pair of function_type as being compared.
Functor used to sort types before hashing them.
size_t rank(enum type_or_decl_base::type_or_decl_kind k)
Return the rank of a given kind of IR node.
bool operator()(const type_base &f, const type_base &s)
"Less Than" operator for type IR nodes.
bool operator()(const type_base_sptr &f, const type_base_sptr &s)
"Less Than" operator for type IR nodes.
bool operator()(const type_base *f, const type_base *s)
"Less Than" operator for type IR nodes.
Private type to hold private members of translation_unit.
Definition of the private data of type_base.
The private data of type_or_decl_base.
void set_hashing_state(hashing::hashing_state s) const
Setter of the hashing state of the current IR node.
void is_recursive_artefact(bool f)
Setter of the property which flags the current artefact as being recursive or not.
void kind(enum type_or_decl_kind k)
Setter of the kind of the IR node.
void set_hash_value(hash_t h)
Setter of the hashing value of the current IR node.
enum type_or_decl_kind kind() const
Getter of the kind of the IR node.
priv(const environment &e, enum type_or_decl_kind k=ABSTRACT_TYPE_OR_DECL)
Constructor of the type_or_decl_base::priv private type.
bool is_recursive_artefact() const
Getter of the property which flags the current artefact as being recursive or not.
void force_set_hash_value(hash_t h)
Setter of the hashing value of the current IR node.
hashing::hashing_state get_hashing_state() const
Getter the hashing state of the current IR node.
A functor to sort types somewhat topologically. That is, types are sorted in a way that makes the one...
bool has_artificial_or_natural_location(const type_base *t)
Test if a type has an artificial or natural location.
bool has_artificial_or_natural_location(const decl_base *d)
Test if a decl has an artificial or natural location.
bool operator()(const type_base_sptr &f, const type_base_sptr &s)
The "Less Than" comparison operator of this functor.
bool operator()(const type_base *f, const type_base *s)
The "Less Than" comparison operator of this functor.
The hashing functor for a pair of uint64_t.
uint64_t operator()(const std::pair< uint64_t, uint64_t > &p) const
Hashing function for a pair of uint64_t.