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-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);
110 real_type(base_type, modifiers_type);
111
112 base_type
113 get_base_type() const;
114
115 modifiers_type
116 get_modifiers() const;
117
118 void
119 set_modifiers(modifiers_type);
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_NOT_DONE_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
307
308 /// Setter of the hashing value of the current IR node.
309 ///
310 /// Unlike set_hash_value above, this function always sets a new
311 /// hash value regardless of the hash value or of the hashing state
312 /// of the IR node.
313 ///
314 /// @param h the new hash value.
315 void
317 {
318 if (h.has_value())
319 {
320 hash_value_ = h;
322 }
323 }
324}; // end struct type_or_decl_base::priv
325
326/// Compute the hash value of an IR node and return it.
327///
328/// Note that if the IR node is a non-canonicalizeable type, no hash
329/// value is computed and an empty hash is returned. Also, if the IR
330/// node already has a hash value, then this function just returns it.
331///
332/// This is a sub-routine of the internal hashing functions defined in
333/// abg-hash.cc
334///
335/// @param tod the IR node to compute the value for.
336///
337/// @return the computed hash value computed.
338template<typename T>
339hash_t
340do_hash_value(const T& tod)
341{
342 if (type_base* type = is_type(&tod))
344 // Non canonicalized types are not hashed. They must always be
345 // compared structurally.
346 return hash_t();
347
348 typename T::hash do_hash;
349 hash_t h = do_hash(tod);
350 return h;
351}
352
353/// Compute the hash value of an IR node and return it.
354///
355/// Note that if the IR node is a non-canonicalizeable type, no hash
356/// value is computed and an empty hash is returned. Also, if the IR
357/// node already has a hash value, then this function just returns it.
358///
359/// This is a sub-routine of the internal hashing functions defined in
360/// abg-hash.cc
361///
362/// @param tod the IR node to compute the value for.
363///
364/// @return the computed hash value computed.
365template<typename T>
366hash_t
367do_hash_value(const T* tod)
368{
369 if (!tod)
370 return hash_t();
371 return hash_value(*tod);
372}
373
374/// Compute the hash value of an IR node and return it.
375///
376/// Note that if the IR node is a non-canonicalizeable type, no hash
377/// value is computed and an empty hash is returned. Also, if the IR
378/// node already has a hash value, then this function just returns it.
379///
380/// This is a sub-routine of the internal hashing functions defined in
381/// abg-hash.cc
382///
383/// @param tod the IR node to compute the value for.
384///
385/// @return the computed hash value computed.
386template<typename T>
387hash_t
388do_hash_value(const shared_ptr<T>& tod)
389{
390 if (!tod)
391 return hash_t();
392 return do_hash_value(*tod);
393}
394
395
396/// Set the hash value of an IR node and return it.
397///
398/// If the IR node already has a hash value set, this function just
399/// returns it. Otherwise, the function computes a new hash value and
400/// sets it to the IR node.
401///
402/// Note that if the IR node is a non-canonicalizeable type, no hash
403/// value is computed and an empty hash is returned.
404///
405/// This is a sub-routine of the type_or_decl_base::hash_value()
406/// virtual member functions.
407///
408/// @param type_or_decl the IR node to compute the value for.
409///
410/// @return the hash value computed and set to the IR node, or the
411/// hash value the IR node already had.
412template<typename T>
413hash_t
415{
416 hash_t h = do_hash_value(tod);
417 const_cast<T&>(tod).set_hash_value(h);
418 return h;
419}
420
421/// Set the hash value of an IR node and return it.
422///
423/// If the IR node already has a hash value set, this function just
424/// returns it. Otherwise, the function computes a new hash value and
425/// sets it to the IR node.
426///
427/// Note that if the IR node is a non-canonicalizeable type, no hash
428/// value is computed and an empty hash is returned.
429///
430/// This is a sub-routine of the type_or_decl_base::hash_value()
431/// virtual member functions.
432///
433/// @param type_or_decl the IR node to compute the value for.
434///
435/// @return the hash value computed and set to the IR node, or the
436/// hash value the IR node already had.
437template<typename T>
438hash_t
440{
441 if (!artifact)
442 return hash_t();
443 return set_or_get_cached_hash_value(*artifact);
444}
445
446// </type_or_decl_base stuff>
447
448
449// <type_base definitions>
450
451size_t
453
454size_t
456
457size_t
458get_canonical_type_index(const type_base_sptr& t);
459
460/// Definition of the private data of @ref type_base.
462{
463 size_t size_in_bits;
464 size_t alignment_in_bits;
465 size_t canonical_type_index;
466 type_base_wptr canonical_type;
467 // The data member below holds the canonical type that is managed by
468 // the smart pointer referenced by the canonical_type data member
469 // above. We are storing this underlying (naked) pointer here, so
470 // that users can access it *fast*. Otherwise, accessing
471 // canonical_type above implies creating a shared_ptr, and that has
472 // been measured to be slow for some performance hot spots.
473 type_base* naked_canonical_type;
474 // Computing the representation of a type again and again can be
475 // costly. So we cache the internal and non-internal type
476 // representation strings here.
477 interned_string internal_cached_repr_;
478 interned_string cached_repr_;
479
480 priv()
481 : size_in_bits(),
482 alignment_in_bits(),
483 canonical_type_index(),
484 naked_canonical_type()
485 {}
486
487 priv(size_t s,
488 size_t a,
489 type_base_sptr c = type_base_sptr())
490 : size_in_bits(s),
491 alignment_in_bits(a),
492 canonical_type_index(),
493 canonical_type(c),
494 naked_canonical_type(c.get())
495 {}
496}; // end struct type_base::priv
497
498bool
500
501// <environment definitions>
502
503/// The hashing functor for a pair of uint64_t.
505{
506 /// Hashing function for a pair of uint64_t.
507 ///
508 /// @param p the pair to hash.
509 uint64_t
510 operator()(const std::pair<uint64_t, uint64_t>& p) const
511 {
513 hash_t(p.second));
514 }
515};
516
517/// A convenience typedef for a pair of uint64_t which is initially
518/// intended to store a pair of pointer values.
519typedef std::pair<uint64_t, uint64_t> uint64_t_pair_type;
520
521/// A convenience typedef for a set of @ref uint64_t_pair
522typedef unordered_set<uint64_t_pair_type,
524
525/// A convenience typedef for a set of pointer to @ref class_or_union
526typedef unordered_set<const class_or_union*> class_set_type;
527
528/// A convenience typedef for a set of pointer to @ref function_type.
529typedef unordered_set<const function_type*> fn_set_type;
530
531/// A convenience typedef for a map which key is a pair of uint64_t
532/// and which value is a boolean. This is initially intended to cache
533/// the result of comparing two (sub-)types.
534typedef unordered_map<uint64_t_pair_type, bool,
536
537/// The private data of the @ref environment type.
539{
540 config config_;
541 canonical_types_map_type canonical_types_;
542 mutable vector<type_base_sptr> sorted_canonical_types_;
543 type_base_sptr void_type_;
544 type_base_sptr void_pointer_type_;
545 type_base_sptr variadic_marker_type_;
546 // The set of pairs of class types being currently compared. It's
547 // used to avoid endless loops while recursively comparing types.
548 // This should be empty when none of the 'equal' overloads are
549 // currently being invoked.
550 class_set_type left_classes_being_compared_;
551 class_set_type right_classes_being_compared_;
552 // The set of pairs of function types being currently compared. It's used
553 // to avoid endless loops while recursively comparing types. This
554 // should be empty when none of the 'equal' overloads are currently
555 // being invoked.
556 fn_set_type left_fn_types_being_compared_;
557 fn_set_type right_fn_types_being_compared_;
558 // This is a cache for the result of comparing two sub-types (of
559 // either class or function types) that are designated by their
560 // memory address in the IR.
561 type_comparison_result_type type_comparison_results_cache_;
562 vector<type_base_sptr> extra_live_types_;
563 interned_string_pool string_pool_;
564 // The two vectors below represent the stack of left and right
565 // operands of the current type comparison operation that is
566 // happening during type canonicalization.
567 //
568 // Basically, that stack of operand looks like below.
569 //
570 // First, suppose we have a type T_L that has two sub-types as this:
571 //
572 // T_L
573 // |
574 // +-- L_OP0
575 // |
576 // +-- L_OP1
577 //
578 // Now suppose that we have another type T_R that has two sub-types
579 // as this:
580 //
581 // T_R
582 // |
583 // +-- R_OP0
584 // |
585 // +-- R_OP1
586 //
587 // Now suppose that we compare T_L against T_R. We are going to
588 // have a stack of pair of types. Each pair of types represents
589 // two (sub) types being compared against each other.
590 //
591 // On the stack, we will thus first have the pair (T_L, T_R)
592 // being compared. Then, we will have the pair (L_OP0, R_OP0)
593 // being compared, and then the pair (L_OP1, R_OP1) being
594 // compared. Like this:
595 //
596 // | T_L | L_OP0 | L_OP1 | <-- this goes into left_type_comp_operands_;
597 // -------- -------------
598 // | T_R | R_OP0 | R_OP1 | <-- this goes into right_type_comp_operands_;
599 //
600 vector<const type_base*> left_type_comp_operands_;
601 vector<const type_base*> right_type_comp_operands_;
602
603#ifdef WITH_DEBUG_SELF_COMPARISON
604 // This is used for debugging purposes.
605 // When abidw is used with the option --debug-abidiff, some
606 // libabigail internals need to get a hold on the initial binary
607 // input of abidw, as well as as the abixml file that represents the
608 // ABI of that binary.
609 //
610 // So this one is the corpus for the input binary.
611 corpus_wptr first_self_comparison_corpus_;
612 // This one is the corpus for the ABIXML file representing the
613 // serialization of the input binary.
614 corpus_wptr second_self_comparison_corpus_;
615 // This is also used for debugging purposes, when using
616 // 'abidw --debug-abidiff <binary>'. It holds the set of mapping of
617 // an abixml (canonical) type and its type-id.
618 unordered_map<string, uintptr_t> type_id_canonical_type_map_;
619 // Likewise. It holds a map that associates the pointer to a type
620 // read from abixml and the type-id string it corresponds to.
621 unordered_map<uintptr_t, string> pointer_type_id_map_;
622#endif
623 bool canonicalization_started_;
624 bool canonicalization_is_done_;
625 bool decl_only_class_equals_definition_;
626 bool use_enum_binary_only_equality_;
627 bool allow_type_comparison_results_caching_;
628 bool do_log_;
629 optional<bool> analyze_exported_interfaces_only_;
630#ifdef WITH_DEBUG_SELF_COMPARISON
631 bool self_comparison_debug_on_;
632#endif
633#ifdef WITH_DEBUG_TYPE_CANONICALIZATION
634 // This controls whether to use canonical type comparison during
635 // type comparison or not. This is only used for debugging, when we
636 // want to ensure that comparing types using canonical or structural
637 // comparison yields the same result.
638 bool use_canonical_type_comparison_;
639 // Whether we are debugging type canonicalization or not. When
640 // debugging type canonicalization, a type is compared to its
641 // potential canonical type twice: The first time with canonical
642 // comparison activated, and the second time with structural
643 // comparison activated. The two comparison should yield the same
644 // result, otherwise, canonicalization is "broken" for that
645 // particular type.
646 bool debug_type_canonicalization_;
647 bool debug_die_canonicalization_;
648#endif
649
650 priv()
651 : canonicalization_started_(),
652 canonicalization_is_done_(),
653 decl_only_class_equals_definition_(false),
654 use_enum_binary_only_equality_(true),
655 allow_type_comparison_results_caching_(false),
656 do_log_(false)
657#ifdef WITH_DEBUG_SELF_COMPARISON
658 ,
659 self_comparison_debug_on_(false)
660#endif
661#ifdef WITH_DEBUG_TYPE_CANONICALIZATION
662 ,
663 use_canonical_type_comparison_(true),
664 debug_type_canonicalization_(false),
665 debug_die_canonicalization_(false)
666#endif
667 {}
668
669 /// Allow caching of the sub-types comparison results during the
670 /// invocation of the @ref equal overloads for class and function
671 /// types.
672 ///
673 /// @param f if true, allow type comparison result caching.
674 void
676 {allow_type_comparison_results_caching_ = f;}
677
678 /// Check whether if caching of the sub-types comparison results during the
679 /// invocation of the @ref equal overloads for class and function
680 /// types is in effect.
681 ///
682 /// @return true iff caching of the sub-types comparison results
683 /// during the invocation of the @ref equal overloads for class and
684 /// function types is in effect.
685 bool
687 {return allow_type_comparison_results_caching_;}
688
689 void
690 do_log(bool f)
691 {do_log_ = f;}
692
693 bool
694 do_log() const
695 {return do_log_;}
696
697 /// Cache the result of comparing two sub-types.
698 ///
699 /// @param first the first sub-type that has been compared. Its
700 /// address is going to be stored in the cache.
701 ///
702 /// @param second the second sub-type that has been compared. Its
703 /// address is going to be stored in the cache.
704 ///
705 /// @param r the result of comparing @p first and @p second. This
706 /// is going to be stored in the cache, as well as the addresses of
707 /// @p first and @p second.
708 template<typename T>
709 void
710 cache_type_comparison_result(T& first, T& second, bool r)
711 {
713 {
714 type_comparison_results_cache_.emplace
715 (std::make_pair(reinterpret_cast<uint64_t>(&first),
716 reinterpret_cast<uint64_t>(&second)),
717 r);
718 }
719 }
720
721 /// Retrieve the result of comparing two sub-types from the cache,
722 /// if it was previously stored.
723 ///
724 /// @param first the first sub-type to consider.
725 ///
726 /// @param second the second sub-type to consider. The pair of
727 /// addresses of {@p first, @p second} is going to be looked up in
728 /// the cache. If it's present, then the associated result of the
729 /// comparison of @p first against @p second is present as well, and
730 /// is returned.
731 ///
732 /// @param r this is an out parameter which is set to the result of
733 /// the comparison of @p first against @p second if the pair of
734 /// addresses of {@p first, @p second} is present in the cache.
735 ///
736 /// @return true iff the pair of addresses of {@p first, @p second}
737 /// is present in the cache. In that case, the associated result of
738 /// the comparison of @p first against @p second is returned in the
739 /// argument of @p r.
740 template<typename T>
741 bool
742 is_type_comparison_cached(T& first, T& second, bool& r)
743 {
745 return false;
746
747 type_comparison_result_type::const_iterator it =
748 type_comparison_results_cache_.find
749 (std::make_pair(reinterpret_cast<uint64_t>(&first),
750 reinterpret_cast<uint64_t>(&second)));
751 if (it == type_comparison_results_cache_.end())
752 return false;
753
754 r = it->second;
755 return true;
756 }
757
758 /// Clear the cache type comparison results.
759 void
761 {type_comparison_results_cache_.clear();}
762
763 /// Push a pair of operands on the stack of operands of the current
764 /// type comparison, during type canonicalization.
765 ///
766 /// For more information on this, please look at the description of
767 /// the right_type_comp_operands_ data member.
768 ///
769 /// @param left the left-hand-side comparison operand to push.
770 ///
771 /// @param right the right-hand-side comparison operand to push.
772 void
774 const type_base* right)
775 {
776 ABG_ASSERT(left && right);
777
778 left_type_comp_operands_.push_back(left);
779 right_type_comp_operands_.push_back(right);
780 }
781
782 /// Pop a pair of operands from the stack of operands to the current
783 /// type comparison.
784 ///
785 /// For more information on this, please look at the description of
786 /// the right_type_comp_operands_ data member.
787 ///
788 /// @param left the left-hand-side comparison operand we expect to
789 /// pop from the top of the stack. If this doesn't match the
790 /// operand found on the top of the stack, the function aborts.
791 ///
792 /// @param right the right-hand-side comparison operand we expect to
793 /// pop from the bottom of the stack. If this doesn't match the
794 /// operand found on the top of the stack, the function aborts.
795 void
797 const type_base* right)
798 {
799 const type_base *t = left_type_comp_operands_.back();
800 ABG_ASSERT(t == left);
801 t = right_type_comp_operands_.back();
802 ABG_ASSERT(t == right);
803
804 left_type_comp_operands_.pop_back();
805 right_type_comp_operands_.pop_back();
806 }
807
808#ifdef WITH_DEBUG_SELF_COMPARISON
809
810 const unordered_map<string, uintptr_t>&
811 get_type_id_canonical_type_map() const
812 {return type_id_canonical_type_map_;}
813
814 unordered_map<string, uintptr_t>&
815 get_type_id_canonical_type_map()
816 {return type_id_canonical_type_map_;}
817
818 const unordered_map<uintptr_t, string>&
819 get_pointer_type_id_map() const
820 {return pointer_type_id_map_;}
821
822 unordered_map<uintptr_t, string>&
823 get_pointer_type_id_map()
824 {return pointer_type_id_map_;}
825
826 string
827 get_type_id_from_pointer(uintptr_t ptr) const
828 {
829 auto it = get_pointer_type_id_map().find(ptr);
830 if (it != get_pointer_type_id_map().end())
831 return it->second;
832 return "";
833 }
834
835 string
836 get_type_id_from_type(const type_base *t) const
837 {return get_type_id_from_pointer(reinterpret_cast<uintptr_t>(t));}
838
839 uintptr_t
840 get_canonical_type_from_type_id(const char* type_id) const
841 {
842 if (!type_id)
843 return 0;
844 auto it = get_type_id_canonical_type_map().find(type_id);
845 if (it != get_type_id_canonical_type_map().end())
846 return it->second;
847 return 0;
848 }
849
850 /// When debugging self comparison, verify that a type T
851 /// de-serialized from abixml has the same canonical type as the
852 /// initial type built from DWARF that was serialized into T in the
853 /// first place.
854 ///
855 /// @param t deserialized type (from abixml) to consider.
856 ///
857 /// @param c the canonical type that @p t has, as computed freshly
858 /// from the abixml file.
859 ///
860 /// @return true iff @p c has the same value as the canonical type
861 /// that @p t had before being serialized into abixml.
862 bool
863 check_canonical_type_from_abixml_during_self_comp(const type_base* t,
864 const type_base* c)
865 {
866 if (!t || !t->get_corpus() || !c)
867 return false;
868
869 if (!(t->get_corpus()->get_origin() == ir::corpus::NATIVE_XML_ORIGIN))
870 return false;
871
872 // Get the abixml type-id that this type was constructed from.
873 string type_id;
874 {
875 unordered_map<uintptr_t, string>::const_iterator it =
876 pointer_type_id_map_.find(reinterpret_cast<uintptr_t>(t));
877 if (it == pointer_type_id_map_.end())
878 // This type didn't have a type-id in the abixml file. Maybe
879 // it's a function or method type. So let's just keep going.
880 return true;
881 type_id = it->second;
882 }
883
884 // Get the canonical type the original in-memory type (constructed
885 // from DWARF) had when it was serialized into abixml in the first place.
886 type_base *original_canonical_type = nullptr;
887 if (!type_id.empty())
888 {
889 unordered_map<string, uintptr_t>::const_iterator it =
890 type_id_canonical_type_map_.find(type_id);
891 if (it == type_id_canonical_type_map_.end())
892 return false;
893 original_canonical_type = reinterpret_cast<type_base*>(it->second);
894 }
895
896 // Now perform the real check.
897 //
898 // We want to ensure that the canonical type 'c' of 't' is the
899 // same as the canonical type of initial in-memory type (built
900 // from DWARF) that was serialized into 't' (in abixml) in the
901 // first place.
902 if (original_canonical_type == c)
903 return true;
904
905 return false;
906 }
907
908 /// When debugging self comparison, verify that a type T
909 /// de-serialized from abixml has the same canonical type as the
910 /// initial type built from DWARF that was serialized into T in the
911 /// first place.
912 ///
913 /// @param t deserialized type (from abixml) to consider.
914 ///
915 /// @return true iff @p c is the canonical type that @p t should
916 /// have.
917 bool
918 check_abixml_canonical_type_propagation_during_self_comp(const type_base* t)
919 {
920 if (t->get_corpus()
921 && t->get_corpus()->get_origin() == ir::corpus::NATIVE_XML_ORIGIN)
922 {
923 type_base* c = t->get_naked_canonical_type();
924 if (c && !check_canonical_type_from_abixml_during_self_comp(t, c))
925 {
926 string repr = t->get_pretty_representation(true, true);
927 string type_id = get_type_id_from_type(t);
928 std::cerr << "error: canonical type propagation error for '"
929 << repr
930 << "' of type-id: '"
931 << type_id
932 << "' / type: @"
933 << std::hex
934 << t
935 << "/ canon: @"
936 << c
937 << ", should have had canonical type: "
938 << std::hex
939 << get_canonical_type_from_type_id(type_id.c_str())
940 << "\n";
941 return false;
942 }
943 }
944 return true;
945 }
946
947 /// When debugging self comparison, verify that a type T
948 /// de-serialized from abixml has the same canonical type as the
949 /// initial type built from DWARF that was serialized into T in the
950 /// first place.
951 ///
952 /// @param t deserialized type (from abixml) to consider.
953 ///
954 /// @param c the canonical type @p t should have.
955 ///
956 /// @return true iff @p c is the canonical type that @p t should
957 /// have.
958 bool
959 check_canonical_type_from_abixml_during_self_comp(const type_base_sptr& t,
960 const type_base_sptr& c)
961 {
962 return check_canonical_type_from_abixml_during_self_comp(t.get(), c.get());
963 }
964#endif
965};// end struct environment::priv
966
967bool
968compare_using_locations(const decl_base *f,
969 const decl_base *s);
970
971/// A functor to sort decls somewhat topologically. That is, types
972/// are sorted in a way that makes the ones that are defined "first"
973/// to come first.
974///
975/// The topological criteria is a lexicographic sort of the definition
976/// location of the type. For types that have no location (or the
977/// same location), it's their qualified name that is used for the
978/// lexicographic sort.
980{
981 /// Test if a decl has an artificial or natural location.
982 ///
983 /// @param d the decl to consider
984 ///
985 /// @return true iff @p d has a location.
986 bool
989
990 /// Test if a type has an artificial or natural location.
991 ///
992 /// @param t the type to consider
993 ///
994 /// @return true iff @p t has a location.
995 bool
997 {
998 if (decl_base *d = is_decl(t))
1000 return false;
1001 }
1002
1003 /// The "Less Than" comparison operator of this functor.
1004 ///
1005 /// @param f the first decl to be considered for the comparison.
1006 ///
1007 /// @param s the second decl to be considered for the comparison.
1008 ///
1009 /// @return true iff @p f is less than @p s.
1010 bool
1012 const decl_base *s)
1013 {
1014 if (!!f != !!s)
1015 return f && !s;
1016
1017 if (!f)
1018 return false;
1019
1020 // Unique types that are artificially created in the environment
1021 // don't have locations. They ought to be compared on the basis
1022 // of their pretty representation before we start looking at IR
1023 // nodes' locations down the road.
1025 return (f->get_cached_pretty_representation(/*internal=*/false)
1026 < s->get_cached_pretty_representation(/*internal=*/false));
1027
1028 // If both decls come from an abixml file, keep the order they
1029 // have from that abixml file.
1032 && (((!f->get_corpus() && !s->get_corpus())
1033 || (f->get_corpus() && f->get_corpus()->get_origin() == corpus::NATIVE_XML_ORIGIN
1034 && s->get_corpus() && s->get_corpus()->get_origin() == corpus::NATIVE_XML_ORIGIN))))
1035 return compare_using_locations(f, s);
1036
1037 // If a decl has artificial location, then use that one over the
1038 // natural one.
1041
1042 if (fl.get_value() && sl.get_value())
1043 return compare_using_locations(f, s);
1044 else if (!!fl != !!sl)
1045 // So one of the decls doesn't have location data.
1046 // The first decl is less than the second if it's the one not
1047 // having location data.
1048 return !fl && sl;
1049
1050 // We reach this point if location data is useless.
1051 if (f->get_is_anonymous()
1052 && s->get_is_anonymous()
1053 && (f->get_cached_pretty_representation(/*internal=*/false)
1054 == s->get_cached_pretty_representation(/*internal=*/false)))
1055 return f->get_name() < s->get_name();
1056
1057 return (f->get_cached_pretty_representation(/*internal=*/false)
1058 < s->get_cached_pretty_representation(/*internal=*/false));
1059 }
1060
1061 /// The "Less Than" comparison operator of this functor.
1062 ///
1063 /// @param f the first decl to be considered for the comparison.
1064 ///
1065 /// @param s the second decl to be considered for the comparison.
1066 ///
1067 /// @return true iff @p f is less than @p s.
1068 bool
1069 operator()(const decl_base_sptr &f,
1070 const decl_base_sptr &s)
1071 {return operator()(f.get(), s.get());}
1072
1073}; // end struct decl_topo_comp
1074
1075bool
1077
1078/// A functor to sort types somewhat topologically. That is, types
1079/// are sorted in a way that makes the ones that are defined "first"
1080/// to come first.
1081///
1082/// The topological criteria is a lexicographic sort of the definition
1083/// location of the type. For types that have no location, it's their
1084/// qualified name that is used for the lexicographic sort.
1086{
1087 /// Test if a decl has an artificial or natural location.
1088 ///
1089 /// @param d the decl to consider
1090 ///
1091 /// @return true iff @p d has a location.
1092 bool
1095
1096 /// Test if a type has an artificial or natural location.
1097 ///
1098 /// @param t the type to consider
1099 ///
1100 /// @return true iff @p t has a location.
1101 bool
1103 {
1104 if (decl_base *d = is_decl(t))
1106 return false;
1107 }
1108
1109 /// The "Less Than" comparison operator of this functor.
1110 ///
1111 /// @param f the first type to be considered for the comparison.
1112 ///
1113 /// @param s the second type to be considered for the comparison.
1114 ///
1115 /// @return true iff @p f is less than @p s.
1116 bool
1117 operator()(const type_base_sptr &f,
1118 const type_base_sptr &s)
1119 {return operator()(f.get(), s.get());}
1120
1121 /// The "Less Than" comparison operator of this functor.
1122 ///
1123 /// @param f the first type to be considered for the comparison.
1124 ///
1125 /// @param s the second type to be considered for the comparison.
1126 ///
1127 /// @return true iff @p f is less than @p s.
1128 bool
1130 const type_base *s)
1131 {
1132 if (f == s || !f || !s)
1133 return false;
1134
1135 // If both decls come from an abixml file, keep the order they
1136 // have from that abixml file.
1137 if (is_decl(f) && is_decl(s)
1140 && ((!f->get_corpus() && !s->get_corpus())
1141 || (f->get_corpus()
1142 && f->get_corpus()->get_origin() == corpus::NATIVE_XML_ORIGIN
1143 && s->get_corpus()
1144 && (s->get_corpus()->get_origin()
1145 == corpus::NATIVE_XML_ORIGIN))))
1147
1148 bool f_is_ptr_ref_or_qual = is_ptr_ref_or_qual_type(f);
1149 bool s_is_ptr_ref_or_qual = is_ptr_ref_or_qual_type(s);
1150
1151 if (f_is_ptr_ref_or_qual != s_is_ptr_ref_or_qual)
1152 return !f_is_ptr_ref_or_qual && s_is_ptr_ref_or_qual;
1153
1154 if (f_is_ptr_ref_or_qual && s_is_ptr_ref_or_qual
1157 {
1158 interned_string s1 = f->get_cached_pretty_representation(/*internal=*/false);
1159 interned_string s2 = s->get_cached_pretty_representation(/*internal=*/false);
1160 if (s1 == s2)
1161 {
1163 {
1164 if (q->get_cv_quals() == qualified_type_def::CV_NONE)
1165 if (!is_qualified_type(s))
1166 // We are looking at two types that are the result of
1167 // an optimization that happens during the IR
1168 // construction. Namely, type f is a cv-qualified
1169 // type with no qualifier (no const, no volatile, no
1170 // nothing, we call it an empty-qualified type).
1171 // These are the result of an optimization which
1172 // removes "redundant qualifiers" from some types.
1173 // For instance, consider a "const reference". The
1174 // const there is redundant because a reference is
1175 // always const. So as a result of the optimizaton
1176 // that type is going to be transformed into an
1177 // empty-qualified reference. If we don't make that
1178 // optimization, then we risk having spurious change
1179 // reports down the road. But then, as a consequence
1180 // of that optimization, we need to sort the
1181 // empty-qualified type and its non-qualified variant
1182 // e.g, to ensure stability in the abixml output; both
1183 // types are logically equal, but here, we decide that
1184 // the empty-qualified one is topologically "less
1185 // than" the non-qualified counterpart.
1186 //
1187 // So here, type f is an empty-qualified type and type
1188 // s is its non-qualified variant. We decide that f
1189 // is topologically less than s.
1190 return true;
1191 }
1192 // Now let's peel off the pointer (or reference types) and
1193 // see if the ultimate underlying types have the same
1194 // textual representation; if not, use that as sorting
1195 // criterion.
1196 type_base *peeled_f =
1198 type_base *peeled_s =
1200
1201 s1 = peeled_f->get_cached_pretty_representation(/*internal=*/false);
1202 s2 = peeled_s->get_cached_pretty_representation(/*internal=*/false);
1203 if (s1 != s2)
1204 return s1 < s2;
1205
1206 // The underlying type of pointer/reference have the same
1207 // textual representation; let's try to peel of typedefs
1208 // as well and we'll consider sorting the result as decls.
1209 peeled_f = peel_typedef_pointer_or_reference_type(peeled_f, true);
1210 peeled_s = peel_typedef_pointer_or_reference_type(peeled_s, true);
1211
1212 s1 = peeled_f->get_cached_pretty_representation(false);
1213 s2 = peeled_s->get_cached_pretty_representation(false);
1214 if (s1 != s2)
1215 return s1 < s2;
1216 }
1217 }
1218
1221
1222 if (s1 != s2)
1223 return s1 < s2;
1224
1225 if (is_typedef(f) && is_typedef(s))
1226 {
1227 s1 = is_typedef(f)->get_underlying_type()->get_cached_pretty_representation(false);
1228 s2 = is_typedef(s)->get_underlying_type()->get_cached_pretty_representation(false);
1229 if (s1 != s2)
1230 return s1 < s2;
1231 }
1232
1235
1236 s1 = peeled_f->get_cached_pretty_representation(false);
1237 s2 = peeled_s->get_cached_pretty_representation(false);
1238
1239 if (s1 != s2)
1240 return s1 < s2;
1241
1242 if (method_type* m_f = is_method_type(peeled_f))
1243 if (method_type* m_s = is_method_type(peeled_s))
1244 {
1245 // If two method types differ from their const-ness, make the
1246 // const one come first.
1247 if (m_f->get_is_const() != m_s->get_is_const())
1248 return m_f->get_is_const();
1249
1250 // If two method types have the same name (textual
1251 // representation), make the non-static one come first.
1252 if (m_f->get_is_for_static_method() != m_s->get_is_for_static_method())
1253 return m_f->get_is_for_static_method() < m_s->get_is_for_static_method();
1254 }
1255
1256 decl_base *fd = is_decl(f);
1257 decl_base *sd = is_decl(s);
1258
1259 if (!!fd != !!sd)
1260 return fd && !sd;
1261
1262 if (!fd
1263 && f->get_translation_unit()
1264 && s->get_translation_unit())
1265 {
1266 string s1 = f->get_translation_unit()->get_absolute_path();
1267 string s2 = s->get_translation_unit()->get_absolute_path();
1268 return s1 < s2;
1269 }
1270
1271 // If all pretty representions are equal, sort by
1272 // hash value and canonical type index.
1273 hash_t h_f = peek_hash_value(*f);
1274 hash_t h_s = peek_hash_value(*s);
1275 if (h_f && h_s && *h_f != *h_s)
1276 return *h_f < *h_s;
1277
1278 size_t cti_f = get_canonical_type_index(*f);
1279 size_t cti_s = get_canonical_type_index(*s);
1280 if (cti_f != cti_s)
1281 return cti_f < cti_s;
1282
1283 // If the two types have no decls, how come we could not sort them
1284 // until now? Let's investigate.
1285 ABG_ASSERT(fd);
1286
1287 // From this point, fd and sd should be non-nil
1288 decl_topo_comp decl_comp;
1289 return decl_comp(fd, sd);
1290 }
1291}; //end struct type_topo_comp
1292
1293/// Functor used to sort types before hashing them.
1295{
1296 /// Return the rank of a given kind of IR node.
1297 ///
1298 /// The rank is used to sort a kind of IR node relative to another
1299 /// one of a different kind. For instance, a an IR node of
1300 /// BASIC_TYPE kind has a lower rank than an IR node of ENUM_TYPE
1301 /// kind.
1302 ///
1303 /// @param k the kind of a given IR node.
1304 ///
1305 /// @return the rank of the IR node.
1306 size_t
1308 {
1309 size_t result = 0;
1310
1311 if (k & type_or_decl_base::BASIC_TYPE)
1312 result = 1;
1313 if (k & type_or_decl_base::SUBRANGE_TYPE)
1314 result = 2;
1315 else if (k & type_or_decl_base::ENUM_TYPE)
1316 result = 3;
1317 else if (k & type_or_decl_base::CLASS_TYPE)
1318 result = 4;
1319 else if (k & type_or_decl_base::UNION_TYPE)
1320 result = 5;
1321 else if (k & type_or_decl_base::FUNCTION_TYPE)
1322 result = 6;
1323 else if (k & type_or_decl_base::METHOD_TYPE)
1324 result = 7;
1325 else if (k & type_or_decl_base::TYPEDEF_TYPE)
1326 result = 8;
1327 else if (k & type_or_decl_base::QUALIFIED_TYPE)
1328 result = 9;
1329 else if (k & type_or_decl_base::POINTER_TYPE)
1330 result = 10;
1331 else if (k & type_or_decl_base::REFERENCE_TYPE)
1332 result = 11;
1333 else if (k & type_or_decl_base::POINTER_TO_MEMBER_TYPE)
1334 result = 12;
1335 else if (k & type_or_decl_base::ARRAY_TYPE)
1336 result = 13;
1337
1338 return result;
1339 }
1340
1341 /// "Less Than" operator for type IR nodes.
1342 ///
1343 /// This returns true iff the first operand is less than the second
1344 /// one.
1345 ///
1346 /// IR nodes are first sorted using their rank. Two IR node of the
1347 /// same rank are then sorted using their qualified name.
1348 ///
1349 /// @param f the first operand to consider.
1350 ///
1351 /// @param s the second operand to consider.
1352 bool
1353 operator()(const type_base& f, const type_base& s)
1354 {
1355 size_t rank_f = rank(f.kind()),
1356 rank_s = rank(s.kind());
1357
1358 // If rank_f or rank_s is zero, it probably means there is a new
1359 // type IR kind that needs proper ranking.
1360 ABG_ASSERT(rank_f != 0 && rank_s != 0);
1361
1362 bool result = false;
1363 if (rank_f < rank_s)
1364 result = true;
1365 else if (rank_f == rank_s)
1366 {
1367 type_topo_comp comp;
1368 result = comp(&f,&s);
1369 }
1370 return result;
1371 }
1372
1373 /// "Less Than" operator for type IR nodes.
1374 ///
1375 /// This returns true iff the first operand is less than the second
1376 /// one.
1377 ///
1378 /// IR nodes are first sorted using their rank. Two IR node of the
1379 /// same rank are then sorted using their qualified name.
1380 ///
1381 /// @param f the first operand to consider.
1382 ///
1383 /// @param s the second operand to consider.
1384 bool
1385 operator()(const type_base* f, const type_base* s)
1386 {
1387 return operator()(*f, *s);
1388 }
1389
1390 /// "Less Than" operator for type IR nodes.
1391 ///
1392 /// This returns true iff the first operand is less than the second
1393 /// one.
1394 ///
1395 /// IR nodes are first sorted using their rank. Two IR node of the
1396 /// same rank are then sorted using their qualified name.
1397 ///
1398 /// @param f the first operand to consider.
1399 ///
1400 /// @param s the second operand to consider.
1401 bool
1402 operator()(const type_base_sptr& f, const type_base_sptr& s)
1403 {
1404 return operator()(f.get(), s.get());
1405 }
1406};//end struct sort_for_hash_functor
1407
1408/// Sort types before hashing (and then canonicalizing) them.
1409///
1410/// @param begin an iterator pointing to the beginning of the sequence
1411/// of types to sort.
1412///
1413/// @param end an iterator pointing to the end of the sequence of
1414/// types to sort.
1415template <typename IteratorType>
1416void
1418 IteratorType end)
1419{
1421 return std::stable_sort(begin, end, comp);
1422}
1423
1424void
1425sort_types_for_hash_computing_and_c14n(vector<type_base_sptr>& types);
1426
1427/// Compute the canonical type for all the IR types of the system.
1428///
1429/// After invoking this function, the time it takes to compare two
1430/// types of the IR is equivalent to the time it takes to compare
1431/// their pointer value. That is faster than performing a structural
1432/// (A.K.A. member-wise) comparison.
1433///
1434/// Note that this function performs some sanity checks after* the
1435/// canonicalization process. It ensures that at the end of the
1436/// canonicalization process, all types have been canonicalized. This
1437/// is important because the canonicalization algorithm sometimes
1438/// clears some canonical types after having speculatively set them
1439/// for performance purposes. At the end of the process however, all
1440/// types must be canonicalized, and this function detects violations
1441/// of that assertion.
1442///
1443/// @tparam input_iterator the type of the input iterator of the @p
1444/// beging and @p end.
1445///
1446/// @tparam deref_lambda a lambda function which takes in parameter
1447/// the input iterator of type @p input_iterator and dereferences it
1448/// to return the type to canonicalize.
1449///
1450/// @param begin an iterator pointing to the first type of the set of types
1451/// to canonicalize.
1452///
1453/// @param end an iterator pointing past-the-end (after the last type) of
1454/// the set of types to canonicalize.
1455///
1456/// @param deref a lambda function that knows how to dereference the
1457/// iterator @p begin to return the type to canonicalize.
1458template<typename input_iterator,
1459 typename deref_lambda>
1460void
1461canonicalize_types(const input_iterator& begin,
1462 const input_iterator& end,
1463 deref_lambda deref,
1464 bool do_log = false,
1465 bool show_stats = false)
1466{
1467 if (begin == end)
1468 return;
1469
1470 auto first_iter = begin;
1471 auto first = deref(first_iter);
1472 environment& env = const_cast<environment&>(first->get_environment());
1473
1474 env.canonicalization_started(true);
1475
1476 int i;
1477 input_iterator t;
1478 // First, let's compute the canonical type of this type.
1480 if (do_log)
1481 {
1482 std::cerr << "Canonicalizing types ...\n";
1483 tmr.start();
1484 }
1485
1486 for (t = begin,i = 0; t != end; ++t, ++i)
1487 {
1488 if (do_log && show_stats)
1489 std::cerr << "#" << std::dec << i << " ";
1490
1491 canonicalize(deref(t));
1492 }
1493
1494 env.canonicalization_is_done(true);
1495
1496 if (do_log)
1497 {
1498 tmr.stop();
1499 std::cerr << "Canonicalizing of types DONE in: " << tmr << "\n\n";
1500 tmr.start();
1501 }
1502}
1503
1504/// Hash and canonicalize a sequence of types.
1505///
1506/// Note that this function first sorts the types, then hashes them
1507/// and then canonicalizes them.
1508///
1509/// Operations must be done in that order to get predictable results.
1510///
1511/// @param begin an iterator pointing to the first element of the
1512/// sequence of types to hash and canonicalize.
1513///
1514/// @param begin an iterator pointing past-the-end of the sequence of
1515/// types to hash and canonicalize.
1516///
1517/// @param deref this is a lambda that is used to dereference the
1518/// types contained in the sequence referenced by iterators @p begin
1519/// and @p end.
1520template <typename IteratorType,
1521 typename deref_lambda>
1522void
1524 IteratorType end,
1525 deref_lambda deref,
1526 bool do_log = false,
1527 bool show_stats = false)
1528{
1530 if (do_log)
1531 {
1532 std::cerr << "sorting types before canonicalization ... \n";
1533 tmr.start();
1534 }
1535
1537
1538 if (do_log)
1539 {
1540 tmr.stop();
1541 std::cerr << "sorted types for c14n in: " << tmr << "\n\n";
1542
1543 std::cerr << "hashing types before c14n ...\n";
1544 tmr.start();
1545 }
1546
1547 for (IteratorType t = begin; t != end; ++t)
1548 if (!peek_hash_value(*deref(t)))
1549 (*t)->hash_value();
1550
1551 if (do_log)
1552 {
1553 tmr.stop();
1554 std::cerr << "hashed types in: " << tmr << "\n\n";
1555 }
1556
1557 canonicalize_types(begin, end, deref, do_log, show_stats);
1558}
1559
1560/// Sort and canonicalize a sequence of types.
1561///
1562/// Note that this function does NOT hash the types. It thus assumes
1563/// that the types are allready hashed.
1564///
1565/// Operations must be done in that order (sorting and then
1566/// canonicalizing) to get predictable results.
1567///
1568/// @param begin an iterator pointing to the first element of the
1569/// sequence of types to hash and canonicalize.
1570///
1571/// @param begin an iterator pointing past-the-end of the sequence of
1572/// types to hash and canonicalize.
1573///
1574/// @param deref this is a lambda that is used to dereference the
1575/// types contained in the sequence referenced by iterators @p begin
1576/// and @p end.
1577template <typename IteratorType,
1578 typename deref_lambda>
1579void
1581 IteratorType end,
1582 deref_lambda deref)
1583{
1585 canonicalize_types(begin, end, deref);
1586}
1587
1588// <class_or_union::priv definitions>
1590{
1591 typedef_decl_wptr naming_typedef_;
1592 data_members data_members_;
1593 data_members static_data_members_;
1594 data_members non_static_data_members_;
1595 member_functions member_functions_;
1596 // A map that associates a linkage name to a member function.
1597 string_mem_fn_sptr_map_type mem_fns_map_;
1598 // A map that associates function signature strings to member
1599 // function.
1600 string_mem_fn_ptr_map_type signature_2_mem_fn_map_;
1601 member_function_templates member_function_templates_;
1602 member_class_templates member_class_templates_;
1603 bool is_printing_flat_representation_ = false;
1604
1605 priv()
1606 {}
1607
1610 : data_members_(data_mbrs),
1611 member_functions_(mbr_fns)
1612 {
1613 for (const auto& data_member: data_members_)
1614 if (get_member_is_static(data_member))
1615 static_data_members_.push_back(data_member);
1616 else
1617 non_static_data_members_.push_back(data_member);
1618 }
1619
1620 /// Mark a pair of classes or unions as being currently compared
1621 /// using the class_or_union== operator.
1622 ///
1623 /// Note that this marking business is to avoid infinite loop when
1624 /// comparing a pair of classes or unions. If via the comparison of
1625 /// a data member or a member function a recursive re-comparison of
1626 /// the class or union is attempted, the marking process helps to
1627 /// detect that infinite loop possibility and avoid it.
1628 ///
1629 /// @param first the class or union (of the pair) to mark as being
1630 /// currently compared.
1631 ///
1632 /// @param second the second class or union (of the pair) to mark as
1633 /// being currently compared.
1634 void
1636 const class_or_union& second) const
1637 {
1638 const environment& env = first.get_environment();
1639
1640 env.priv_->left_classes_being_compared_.insert(&first);
1641 env.priv_->right_classes_being_compared_.insert(&second);
1642 }
1643
1644 /// Mark a pair of classes or unions as being currently compared
1645 /// using the class_or_union== operator.
1646 ///
1647 /// Note that this marking business is to avoid infinite loop when
1648 /// comparing a pair of classes or unions. If via the comparison of
1649 /// a data member or a member function a recursive re-comparison of
1650 /// the class or union is attempted, the marking process helps to
1651 /// detect that infinite loop possibility and avoid it.
1652 ///
1653 /// @param first the class or union (of the pair) to mark as being
1654 /// currently compared.
1655 ///
1656 /// @param second the second class or union (of the pair) to mark as
1657 /// being currently compared.
1658 void
1660 const class_or_union* second) const
1661 {mark_as_being_compared(*first, *second);}
1662
1663 /// Mark a pair of classes or unions as being currently compared
1664 /// using the class_or_union== operator.
1665 ///
1666 /// Note that this marking business is to avoid infinite loop when
1667 /// comparing a pair of classes or unions. If via the comparison of
1668 /// a data member or a member function a recursive re-comparison of
1669 /// the class or union is attempted, the marking process helps to
1670 /// detect that infinite loop possibility and avoid it.
1671 ///
1672 /// @param first the class or union (of the pair) to mark as being
1673 /// currently compared.
1674 ///
1675 /// @param second the second class or union (of the pair) to mark as
1676 /// being currently compared.
1677 void
1678 mark_as_being_compared(const class_or_union_sptr& first,
1679 const class_or_union_sptr& second) const
1680 {mark_as_being_compared(*first, *second);}
1681
1682 /// If a pair of class_or_union has been previously marked as
1683 /// being compared -- via an invocation of mark_as_being_compared()
1684 /// this method unmarks it. Otherwise is has no effect.
1685 ///
1686 /// This method is not thread safe because it uses the static data
1687 /// member classes_being_compared_. If you wish to use it in a
1688 /// multi-threaded environment you should probably protect the
1689 /// access to that static data member with a mutex or somesuch.
1690 ///
1691 /// @param first the first instance of class_or_union (of the pair)
1692 /// to unmark.
1693 ///
1694 /// @param second the second instance of class_or_union (of the
1695 /// pair) to unmark.
1696 void
1698 const class_or_union& second) const
1699 {
1700 const environment& env = first.get_environment();
1701
1702 env.priv_->left_classes_being_compared_.erase(&first);
1703 env.priv_->right_classes_being_compared_.erase(&second);
1704 }
1705
1706 /// If a pair of class_or_union has been previously marked as
1707 /// being compared -- via an invocation of mark_as_being_compared()
1708 /// this method unmarks it. Otherwise is has no effect.
1709 ///
1710 /// This method is not thread safe because it uses the static data
1711 /// member classes_being_compared_. If you wish to use it in a
1712 /// multi-threaded environment you should probably protect the
1713 /// access to that static data member with a mutex or somesuch.
1714 ///
1715 /// @param first the first instance of class_or_union (of the pair)
1716 /// to unmark.
1717 ///
1718 /// @param second the second instance of class_or_union (of the
1719 /// pair) to unmark.
1720 void
1722 const class_or_union* second) const
1723 {
1724 if (!first || !second)
1725 return;
1726 unmark_as_being_compared(*first, *second);
1727 }
1728
1729 /// Test if a pair of class_or_union is being currently compared.
1730 ///
1731 ///@param first the first class or union (of the pair) to test for.
1732 ///
1733 ///@param second the second class or union (of the pair) to test for.
1734 ///
1735 /// @return true if the pair {@p first, @p second} is being
1736 /// compared, false otherwise.
1737 bool
1739 const class_or_union& second) const
1740 {
1741 const environment& env = first.get_environment();
1742
1743 return (env.priv_->left_classes_being_compared_.count(&first)
1744 || env.priv_->right_classes_being_compared_.count(&second)
1745 || env.priv_->right_classes_being_compared_.count(&first)
1746 || env.priv_->left_classes_being_compared_.count(&second));
1747 }
1748
1749 /// Test if a pair of class_or_union is being currently compared.
1750 ///
1751 ///@param first the first class or union (of the pair) to test for.
1752 ///
1753 ///@param second the second class or union (of the pair) to test for.
1754 ///
1755 /// @return true if the pair {@p first, @p second} is being
1756 /// compared, false otherwise.
1757 bool
1759 const class_or_union* second) const
1760 {
1761 if (first && second)
1762 return comparison_started(*first, *second);
1763 return false;
1764 }
1765
1766 /// Set the 'is_printing_flat_representation_' boolean to true.
1767 ///
1768 /// That boolean marks the fact that the current @ref class_or_union
1769 /// (and its sub-types graph) is being walked for the purpose of
1770 /// printing its flat representation. This is useful to detect
1771 /// cycles in the graph and avoid endless loops.
1772 void
1774 {is_printing_flat_representation_ = true;}
1775
1776 /// Set the 'is_printing_flat_representation_' boolean to false.
1777 ///
1778 /// That boolean marks the fact that the current @ref class_or_union
1779 /// (and its sub-types graph) is being walked for the purpose of
1780 /// printing its flat representation. This is useful to detect
1781 /// cycles in the graph and avoid endless loops.
1782 void
1784 {is_printing_flat_representation_ = false;}
1785
1786 /// Getter of the 'is_printing_flat_representation_' boolean.
1787 ///
1788 /// That boolean marks the fact that the current @ref class_or_union
1789 /// (and its sub-types graph) is being walked for the purpose of
1790 /// printing its flat representation. This is useful to detect
1791 /// cycles in the graph and avoid endless loops.
1792 bool
1794 {return is_printing_flat_representation_;}
1795}; // end struct class_or_union::priv
1796
1797// <function_type::priv definitions>
1798
1799/// The type of the private data of the @ref function_type type.
1801{
1802 parameters parms_;
1803 type_base_wptr return_type_;
1804 interned_string cached_name_;
1805 interned_string internal_cached_name_;
1806 interned_string temp_internal_cached_name_;
1807 bool is_pretty_printing_ = false;
1808 priv()
1809 {}
1810
1811 priv(const parameters& parms,
1812 type_base_sptr return_type)
1813 : parms_(parms),
1814 return_type_(return_type)
1815 {}
1816
1817 priv(type_base_sptr return_type)
1818 : return_type_(return_type)
1819 {}
1820
1821 /// Mark a given pair of @ref function_type as being compared.
1822 ///
1823 /// @param first the first @ref function_type of the pair being
1824 /// compared, to mark.
1825 ///
1826 /// @param second the second @ref function_type of the pair being
1827 /// compared, to mark.
1828 void
1830 const function_type& second) const
1831 {
1832 const environment& env = first.get_environment();
1833
1834 env.priv_->left_fn_types_being_compared_.insert(&first);
1835 env.priv_->right_fn_types_being_compared_.insert(&second);
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_.erase(&first);
1852 env.priv_->right_fn_types_being_compared_.erase(&second);
1853 }
1854
1855 /// Tests if a @ref function_type is currently being compared.
1856 ///
1857 /// @param type the function type to take into account.
1858 ///
1859 /// @return true if @p type is being compared.
1860 bool
1862 const function_type& second) const
1863 {
1864 const environment& env = first.get_environment();
1865
1866 return (env.priv_->left_fn_types_being_compared_.count(&first)
1867 ||
1868 env.priv_->right_fn_types_being_compared_.count(&second));
1869 }
1870
1871 /// Set the 'is_pretty_printing_' boolean to true.
1872 ///
1873 /// That boolean marks the fact that the current @ref function_type
1874 /// (and its sub-types graph) is being walked for the purpose of
1875 /// printing its flat representation. This is useful to detect
1876 /// cycles in the graph and avoid endless loops.
1877 void
1879 {is_pretty_printing_ = true;}
1880
1881 /// Set the 'is_pretty_printing_' boolean to false.
1882 ///
1883 /// That boolean marks the fact that the current @ref function_type
1884 /// (and its sub-types graph) is being walked for the purpose of
1885 /// printing its flat representation. This is useful to detect
1886 /// cycles in the graph and avoid endless loops.
1887 void
1889 {is_pretty_printing_ = false;}
1890
1891 /// Getter of the 'is_pretty_printing_' boolean.
1892 ///
1893 /// That boolean marks the fact that the current @ref function_type
1894 /// (and its sub-types graph) is being walked for the purpose of
1895 /// printing its flat representation. This is useful to detect
1896 /// cycles in the graph and avoid endless loops.
1897 bool
1899 {return is_pretty_printing_;}
1900};// end struc function_type::priv
1901
1902// </function_type::priv definitions>
1903
1904size_t
1906
1907bool
1908type_originates_from_corpus(type_base_sptr t, corpus_sptr& c);
1909} // end namespace ir
1910
1911} // end namespace abigail
1912
1913#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
unordered_map< string, method_decl_sptr > string_mem_fn_sptr_map_type
Convenience typedef.
Definition abg-ir.h:3963
vector< method_decl_sptr > member_functions
Convenience typedef.
Definition abg-ir.h:3960
vector< var_decl_sptr > data_members
Convenience typedef.
Definition abg-ir.h:3959
unordered_map< string, method_decl * > string_mem_fn_ptr_map_type
Convenience typedef.
Definition abg-ir.h:3962
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:1556
const interned_string & get_cached_pretty_representation(bool internal=false) const
Get the pretty representation of the current decl.
Definition abg-ir.cc:4749
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:5430
virtual const interned_string & get_name() const
Getter for the name of the current decl.
Definition abg-ir.cc:4666
bool get_is_anonymous() const
Test if the current declaration is anonymous.
Definition abg-ir.cc:4523
This is an abstraction of the set of resources necessary to manage several aspects of the internal re...
Definition abg-ir.h:148
bool canonicalization_is_done() const
Test if the canonicalization of types created out of the current environment is done.
Definition abg-ir.cc:3386
bool canonicalization_started() const
Getter of a flag saying if the canonicalization process has started or not.
Definition abg-ir.cc:3413
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
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:16445
string to_string(bool internal=false) const
Return the string representation of the current instance of real_type.
Definition abg-ir.cc:16468
base_type get_base_type() const
Getter of the base type of the real_type.
Definition abg-ir.cc:16431
bool operator==(const real_type &) const
Equality operator for the real_type.
Definition abg-ir.cc:16455
real_type()
Default constructor of the real_type.
Definition abg-ir.cc:16401
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:16438
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
shared_ptr< scope_decl > global_scope_sptr
Convenience typedef for a shared pointer on a global_scope.
Definition abg-ir.h:704
language
The language of the translation unit.
Definition abg-ir.h:708
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:16031
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:4125
enum type_or_decl_kind kind() const
Getter for the "kind" property of type_or_decl_base type.
Definition abg-ir.cc:3969
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:4057
const translation_unit * get_translation_unit() const
Get the translation_unit this ABI artifact belongs to.
Definition abg-ir.cc:4150
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:16193
bool is_non_canonicalized_type(const type_base *t)
Test if a given type is allowed to be non canonicalized.
Definition abg-ir.cc:28076
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:28049
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:15451
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:10465
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:16386
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: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:7264
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:10669
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:7366
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:10405
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:9920
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:15869
bool compare_using_locations(const decl_base *f, const decl_base *s)
Compare decls using their locations.
Definition abg-ir.cc:3268
bool is_unique_type(const type_base_sptr &t)
Test if a type is unique in the entire environment.
Definition abg-ir.cc:28112
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:11514
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:11464
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:3251
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.
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.