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