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-2023 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 <string>
17#include <iostream>
18
19#include "abg-ir.h"
20#include "abg-corpus.h"
21
22namespace abigail
23{
24
25namespace ir
26{
27
28using std::string;
30
31/// The result of structural comparison of type ABI artifacts.
33{
34 COMPARISON_RESULT_DIFFERENT = 0,
35 COMPARISON_RESULT_EQUAL = 1,
36 COMPARISON_RESULT_CYCLE_DETECTED = 2,
37 COMPARISON_RESULT_UNKNOWN = 3,
38}; //end enum comparison_result
39
40/// The internal representation of an integral type.
41///
42/// This is a "utility type" used internally to canonicalize the name
43/// of fundamental integral types, so that "unsignd long" and "long
44/// unsined int" end-up having the same name.
46{
47public:
48 /// The possible base types of integral types. We might have
49 /// forgotten many of these, so do not hesitate to add new ones.
50 ///
51 /// If you do add new ones, please also consider updating functions
52 /// parse_base_integral_type and integral_type::to_string.
54 {
55 /// The "int" base type.
57 /// The "char" base type.
59 /// The "bool" base type in C++ or "_Bool" in C11.
61 /// The "double" base type.
63 /// The "float" base type.
65 /// The "char16_t base type.
67 /// The "char32_t" base type.
69 /// The "wchar_t" base type.
71 };
72
73 /// The modifiers of the base types above. Several modifiers can be
74 /// combined for a given base type. The presence of modifiers is
75 /// usually modelled by a bitmap of modifiers.
76 ///
77 /// If you add a new modifier, please consider updating functions
78 /// parse_integral_type_modifier and integral_type::to_string.
80 {
81 NO_MODIFIER = 0,
82 /// The "signed" modifier.
84 /// The "unsigned" modier.
86 /// The "short" modifier.
88 /// The "long" modifier.
89 LONG_MODIFIER = 1 << 3,
90 /// The "long long" modifier.
91 LONG_LONG_MODIFIER = 1 << 4
92 };
93
94private:
95 base_type base_;
96 modifiers_type modifiers_;
97
98public:
99
101 integral_type(const string& name);
103
105 get_base_type() const;
106
108 get_modifiers() const;
109
110 void
112
113 bool
114 operator==(const integral_type&) const;
115
116 string
117 to_string(bool internal=false) const;
118
119 operator string() const;
120}; // end class integral_type
121
124
127
130
133
136
137bool
138parse_integral_type(const string& type_name,
139 integral_type& type);
140
141/// Private type to hold private members of @ref translation_unit
143{
144 const environment& env_;
145 corpus* corp;
146 bool is_constructed_;
147 char address_size_;
148 language language_;
149 std::string path_;
150 std::string comp_dir_path_;
151 std::string abs_path_;
152 location_manager loc_mgr_;
153 mutable global_scope_sptr global_scope_;
154 mutable vector<type_base_sptr> synthesized_types_;
155 vector<function_type_sptr> live_fn_types_;
156 type_maps types_;
157
158
159 priv(const environment& env)
160 : env_(env),
161 corp(),
162 is_constructed_(),
163 address_size_(),
164 language_(LANG_UNKNOWN)
165 {}
166
167 ~priv()
168 {}
169
170 type_maps&
171 get_types()
172 {return types_;}
173}; // end translation_unit::priv
174
175// <type_base definitions>
176
177/// Definition of the private data of @ref type_base.
179{
180 size_t size_in_bits;
181 size_t alignment_in_bits;
182 type_base_wptr canonical_type;
183 // The data member below holds the canonical type that is managed by
184 // the smart pointer referenced by the canonical_type data member
185 // above. We are storing this underlying (naked) pointer here, so
186 // that users can access it *fast*. Otherwise, accessing
187 // canonical_type above implies creating a shared_ptr, and that has
188 // been measured to be slow for some performance hot spots.
189 type_base* naked_canonical_type;
190 // Computing the representation of a type again and again can be
191 // costly. So we cache the internal and non-internal type
192 // representation strings here.
193 interned_string internal_cached_repr_;
194 interned_string cached_repr_;
195 // The next two data members are used while comparing types during
196 // canonicalization. They are useful for the "canonical type
197 // propagation" (aka on-the-fly-canonicalization) optimization
198 // implementation.
199
200 // The set of canonical recursive types this type depends on.
201 unordered_set<uintptr_t> depends_on_recursive_type_;
202 bool canonical_type_propagated_;
203 bool propagated_canonical_type_confirmed_;
204
205 priv()
206 : size_in_bits(),
207 alignment_in_bits(),
208 naked_canonical_type(),
209 canonical_type_propagated_(false),
210 propagated_canonical_type_confirmed_(false)
211 {}
212
213 priv(size_t s,
214 size_t a,
215 type_base_sptr c = type_base_sptr())
216 : size_in_bits(s),
217 alignment_in_bits(a),
218 canonical_type(c),
219 naked_canonical_type(c.get()),
220 canonical_type_propagated_(false),
221 propagated_canonical_type_confirmed_(false)
222 {}
223
224 /// Test if the current type depends on recursive type comparison.
225 ///
226 /// A recursive type T is a type T which has a sub-type that is T
227 /// (recursively) itself.
228 ///
229 /// So this function tests if the current type has a recursive
230 /// sub-type or is a recursive type itself.
231 ///
232 /// @return true if the current type depends on a recursive type.
233 bool
235 {return !depends_on_recursive_type_.empty();}
236
237 /// Test if the current type depends on a given recursive type.
238 ///
239 /// A recursive type T is a type T which has a sub-type that is T
240 /// (recursively) itself.
241 ///
242 /// So this function tests if the current type depends on a given
243 /// recursive type.
244 ///
245 /// @param dependant the type we want to test if the current type
246 /// depends on.
247 ///
248 /// @return true if the current type depends on the recursive type
249 /// @dependant.
250 bool
251 depends_on_recursive_type(const type_base* dependant) const
252 {
253 return
254 (depends_on_recursive_type_.find(reinterpret_cast<uintptr_t>(dependant))
255 != depends_on_recursive_type_.end());
256 }
257
258 /// Set the flag that tells if the current type depends on a given
259 /// recursive type.
260 ///
261 /// A recursive type T is a type T which has asub-type that is T
262 /// (recursively) itself.
263 ///
264 /// So this function tests if the current type depends on a
265 /// recursive type.
266 ///
267 /// @param t the recursive type that current type depends on.
268 void
270 {depends_on_recursive_type_.insert(reinterpret_cast<uintptr_t>(t));}
271
272 /// Unset the flag that tells if the current type depends on a given
273 /// recursive type.
274 ///
275 /// A recursive type T is a type T which has asub-type that is T
276 /// (recursively) itself.
277 ///
278 /// So this function flags the current type as not being dependant
279 /// on a given recursive type.
280 ///
281 ///
282 /// @param t the recursive type to consider.
283 void
285 {depends_on_recursive_type_.erase(reinterpret_cast<uintptr_t>(t));}
286
287 /// Flag the current type as not being dependant on any recursive type.
288 void
290 {depends_on_recursive_type_.clear();}
291
292 /// Test if the type carries a canonical type that is the result of
293 /// maybe_propagate_canonical_type(), aka, "canonical type
294 /// propagation optimization".
295 ///
296 /// @return true iff the current type carries a canonical type that
297 /// is the result of canonical type propagation.
298 bool
300 {return canonical_type_propagated_;}
301
302 /// Set the flag that says if the type carries a canonical type that
303 /// is the result of maybe_propagate_canonical_type(), aka,
304 /// "canonical type propagation optimization".
305 ///
306 /// @param f true iff the current type carries a canonical type that
307 /// is the result of canonical type propagation.
308 void
310 {canonical_type_propagated_ = f;}
311
312 /// Getter of the property propagated-canonical-type-confirmed.
313 ///
314 /// If canonical_type_propagated() returns true, then this property
315 /// says if the propagated canonical type has been confirmed or not.
316 /// If it hasn't been confirmed, then it means it can still
317 /// cancelled.
318 ///
319 /// @return true iff the propagated canonical type has been
320 /// confirmed.
321 bool
323 {return propagated_canonical_type_confirmed_;}
324
325 /// Setter of the property propagated-canonical-type-confirmed.
326 ///
327 /// If canonical_type_propagated() returns true, then this property
328 /// says if the propagated canonical type has been confirmed or not.
329 /// If it hasn't been confirmed, then it means it can still
330 /// cancelled.
331 ///
332 /// @param f If this is true then the propagated canonical type has
333 /// been confirmed.
334 void
336 {propagated_canonical_type_confirmed_ = f;}
337
338 /// If the current canonical type was set as the result of the
339 /// "canonical type propagation optimization", then clear it.
340 bool
342 {
343 if (canonical_type_propagated_ && !propagated_canonical_type_confirmed_)
344 {
345 canonical_type.reset();
346 naked_canonical_type = nullptr;
348 return true;
349 }
350 return false;
351 }
352}; // end struct type_base::priv
353
354// <environment definitions>
355
356/// The hashing functor for a pair of uint64_t.
358{
359 /// Hashing function for a pair of uint64_t.
360 ///
361 /// @param p the pair to hash.
362 uint64_t
363 operator()(const std::pair<uint64_t, uint64_t>& p) const
364 {return abigail::hashing::combine_hashes(p.first, p.second);}
365};
366
367/// A convenience typedef for a pair of uint64_t which is initially
368/// intended to store a pair of pointer values.
369typedef std::pair<uint64_t, uint64_t> uint64_t_pair_type;
370
371/// A convenience typedef for a set of @ref uint64_t_pair
372typedef unordered_set<uint64_t_pair_type,
374
375/// A convenience typedef for a set of pointer to @ref class_or_union
376typedef unordered_set<const class_or_union*> class_set_type;
377
378/// A convenience typedef for a set of pointer to @ref function_type.
379typedef unordered_set<const function_type*> fn_set_type;
380
381/// A convenience typedef for a map which key is a pair of uint64_t
382/// and which value is a boolean. This is initially intended to cache
383/// the result of comparing two (sub-)types.
384typedef unordered_map<uint64_t_pair_type, bool,
386
387/// The private data of the @ref environment type.
389{
390 config config_;
391 canonical_types_map_type canonical_types_;
392 mutable vector<type_base_sptr> sorted_canonical_types_;
393 type_base_sptr void_type_;
394 type_base_sptr void_pointer_type_;
395 type_base_sptr variadic_marker_type_;
396 // The set of pairs of class types being currently compared. It's
397 // used to avoid endless loops while recursively comparing types.
398 // This should be empty when none of the 'equal' overloads are
399 // currently being invoked.
400 class_set_type left_classes_being_compared_;
401 class_set_type right_classes_being_compared_;
402 // The set of pairs of function types being currently compared. It's used
403 // to avoid endless loops while recursively comparing types. This
404 // should be empty when none of the 'equal' overloads are currently
405 // being invoked.
406 fn_set_type left_fn_types_being_compared_;
407 fn_set_type right_fn_types_being_compared_;
408 // This is a cache for the result of comparing two sub-types (of
409 // either class or function types) that are designated by their
410 // memory address in the IR.
411 type_comparison_result_type type_comparison_results_cache_;
412 vector<type_base_sptr> extra_live_types_;
413 interned_string_pool string_pool_;
414 // The two vectors below represent the stack of left and right
415 // operands of the current type comparison operation that is
416 // happening during type canonicalization.
417 //
418 // Basically, that stack of operand looks like below.
419 //
420 // First, suppose we have a type T_L that has two sub-types as this:
421 //
422 // T_L
423 // |
424 // +-- L_OP0
425 // |
426 // +-- L_OP1
427 //
428 // Now suppose that we have another type T_R that has two sub-types
429 // as this:
430 //
431 // T_R
432 // |
433 // +-- R_OP0
434 // |
435 // +-- R_OP1
436 //
437 // Now suppose that we compare T_L against T_R. We are going to
438 // have a stack of pair of types. Each pair of types represents
439 // two (sub) types being compared against each other.
440 //
441 // On the stack, we will thus first have the pair (T_L, T_R)
442 // being compared. Then, we will have the pair (L_OP0, R_OP0)
443 // being compared, and then the pair (L_OP1, R_OP1) being
444 // compared. Like this:
445 //
446 // | T_L | L_OP0 | L_OP1 | <-- this goes into left_type_comp_operands_;
447 // -------- -------------
448 // | T_R | R_OP0 | R_OP1 | <-- this goes into right_type_comp_operands_;
449 //
450 // This "stack of operands of the current type comparison, during
451 // type canonicalization" is used in the context of the @ref
452 // OnTheFlyCanonicalization optimization. It's used to detect if a
453 // sub-type of the type being canonicalized depends on a recursive
454 // type.
455 vector<const type_base*> left_type_comp_operands_;
456 vector<const type_base*> right_type_comp_operands_;
457 // Vector of types that protentially received propagated canonical types.
458 // If the canonical type propagation is confirmed, the potential
459 // canonical types must be promoted as canonical types. Otherwise if
460 // the canonical type propagation is cancelled, the canonical types
461 // must be cleared.
462 pointer_set types_with_non_confirmed_propagated_ct_;
463 pointer_set recursive_types_;
464#ifdef WITH_DEBUG_CT_PROPAGATION
465 // Set of types which propagated canonical type has been cleared
466 // during the "canonical type propagation optimization" phase. Those
467 // types are tracked in this set to ensure that they are later
468 // canonicalized. This means that at the end of the
469 // canonicalization process, this set must be empty.
470 mutable pointer_set types_with_cleared_propagated_ct_;
471#endif
472#ifdef WITH_DEBUG_SELF_COMPARISON
473 // This is used for debugging purposes.
474 // When abidw is used with the option --debug-abidiff, some
475 // libabigail internals need to get a hold on the initial binary
476 // input of abidw, as well as as the abixml file that represents the
477 // ABI of that binary.
478 //
479 // So this one is the corpus for the input binary.
480 corpus_wptr first_self_comparison_corpus_;
481 // This one is the corpus for the ABIXML file representing the
482 // serialization of the input binary.
483 corpus_wptr second_self_comparison_corpus_;
484 // This is also used for debugging purposes, when using
485 // 'abidw --debug-abidiff <binary>'. It holds the set of mapping of
486 // an abixml (canonical) type and its type-id.
487 unordered_map<string, uintptr_t> type_id_canonical_type_map_;
488 // Likewise. It holds a map that associates the pointer to a type
489 // read from abixml and the type-id string it corresponds to.
490 unordered_map<uintptr_t, string> pointer_type_id_map_;
491#endif
492 bool canonicalization_is_done_;
493 bool do_on_the_fly_canonicalization_;
494 bool decl_only_class_equals_definition_;
495 bool use_enum_binary_only_equality_;
496 bool allow_type_comparison_results_caching_;
497 optional<bool> analyze_exported_interfaces_only_;
498#ifdef WITH_DEBUG_SELF_COMPARISON
499 bool self_comparison_debug_on_;
500#endif
501#ifdef WITH_DEBUG_TYPE_CANONICALIZATION
502 // This controls whether to use canonical type comparison during
503 // type comparison or not. This is only used for debugging, when we
504 // want to ensure that comparing types using canonical or structural
505 // comparison yields the same result.
506 bool use_canonical_type_comparison_;
507 // Whether we are debugging type canonicalization or not. When
508 // debugging type canonicalization, a type is compared to its
509 // potential canonical type twice: The first time with canonical
510 // comparison activated, and the second time with structural
511 // comparison activated. The two comparison should yield the same
512 // result, otherwise, canonicalization is "broken" for that
513 // particular type.
514 bool debug_type_canonicalization_;
515 bool debug_die_canonicalization_;
516#endif
517
518 priv()
519 : canonicalization_is_done_(),
520 do_on_the_fly_canonicalization_(true),
521 decl_only_class_equals_definition_(false),
522 use_enum_binary_only_equality_(true),
523 allow_type_comparison_results_caching_(false)
524#ifdef WITH_DEBUG_SELF_COMPARISON
525 ,
526 self_comparison_debug_on_(false)
527#endif
528#ifdef WITH_DEBUG_TYPE_CANONICALIZATION
529 ,
530 use_canonical_type_comparison_(true),
531 debug_type_canonicalization_(false),
532 debug_die_canonicalization_(false)
533#endif
534 {}
535
536 /// Allow caching of the sub-types comparison results during the
537 /// invocation of the @ref equal overloads for class and function
538 /// types.
539 ///
540 /// @param f if true, allow type comparison result caching.
541 void
543 {allow_type_comparison_results_caching_ = f;}
544
545 /// Check whether if caching of the sub-types comparison results during the
546 /// invocation of the @ref equal overloads for class and function
547 /// types is in effect.
548 ///
549 /// @return true iff caching of the sub-types comparison results
550 /// during the invocation of the @ref equal overloads for class and
551 /// function types is in effect.
552 bool
554 {return allow_type_comparison_results_caching_;}
555
556 /// Cache the result of comparing two sub-types.
557 ///
558 /// @param first the first sub-type that has been compared. Its
559 /// address is going to be stored in the cache.
560 ///
561 /// @param second the second sub-type that has been compared. Its
562 /// address is going to be stored in the cache.
563 ///
564 /// @param r the result of comparing @p first and @p second. This
565 /// is going to be stored in the cache, as well as the addresses of
566 /// @p first and @p second.
567 template<typename T>
568 void
569 cache_type_comparison_result(T& first, T& second, bool r)
570 {
572 && (r == false
573 ||
574 (!is_recursive_type(&first)
575 && !is_recursive_type(&second)
576 && !is_type(&first)->priv_->depends_on_recursive_type()
577 && !is_type(&second)->priv_->depends_on_recursive_type())))
578 {
579 type_comparison_results_cache_.emplace
580 (std::make_pair(reinterpret_cast<uint64_t>(&first),
581 reinterpret_cast<uint64_t>(&second)),
582 r);
583 }
584 }
585
586 /// Retrieve the result of comparing two sub-types from the cache,
587 /// if it was previously stored.
588 ///
589 /// @param first the first sub-type to consider.
590 ///
591 /// @param second the second sub-type to consider. The pair of
592 /// addresses of {@p first, @p second} is going to be looked up in
593 /// the cache. If it's present, then the associated result of the
594 /// comparison of @p first against @p second is present as well, and
595 /// is returned.
596 ///
597 /// @param r this is an out parameter which is set to the result of
598 /// the comparison of @p first against @p second if the pair of
599 /// addresses of {@p first, @p second} is present in the cache.
600 ///
601 /// @return true iff the pair of addresses of {@p first, @p second}
602 /// is present in the cache. In that case, the associated result of
603 /// the comparison of @p first against @p second is returned in the
604 /// argument of @p r.
605 template<typename T>
606 bool
607 is_type_comparison_cached(T& first, T& second, bool& r)
608 {
610 return false;
611
612 type_comparison_result_type::const_iterator it =
613 type_comparison_results_cache_.find
614 (std::make_pair(reinterpret_cast<uint64_t>(&first),
615 reinterpret_cast<uint64_t>(&second)));
616 if (it == type_comparison_results_cache_.end())
617 return false;
618
619 r = it->second;
620 return true;
621 }
622
623 /// Clear the cache type comparison results.
624 void
626 {type_comparison_results_cache_.clear();}
627
628 /// Push a pair of operands on the stack of operands of the current
629 /// type comparison, during type canonicalization.
630 ///
631 /// For more information on this, please look at the description of
632 /// the right_type_comp_operands_ data member.
633 ///
634 /// @param left the left-hand-side comparison operand to push.
635 ///
636 /// @param right the right-hand-side comparison operand to push.
637 void
639 const type_base* right)
640 {
641 ABG_ASSERT(left && right);
642
643 left_type_comp_operands_.push_back(left);
644 right_type_comp_operands_.push_back(right);
645 }
646
647 /// Pop a pair of operands from the stack of operands to the current
648 /// type comparison.
649 ///
650 /// For more information on this, please look at the description of
651 /// the right_type_comp_operands_ data member.
652 ///
653 /// @param left the left-hand-side comparison operand we expect to
654 /// pop from the top of the stack. If this doesn't match the
655 /// operand found on the top of the stack, the function aborts.
656 ///
657 /// @param right the right-hand-side comparison operand we expect to
658 /// pop from the bottom of the stack. If this doesn't match the
659 /// operand found on the top of the stack, the function aborts.
660 void
662 const type_base* right)
663 {
664 const type_base *t = left_type_comp_operands_.back();
665 ABG_ASSERT(t == left);
666 t = right_type_comp_operands_.back();
667 ABG_ASSERT(t == right);
668
669 left_type_comp_operands_.pop_back();
670 right_type_comp_operands_.pop_back();
671 }
672
673 /// Mark all the types that comes after a certain one as NOT being
674 /// eligible for the canonical type propagation optimization.
675 ///
676 /// @param type the type that represents the "marker type". All
677 /// types after this one will be marked as being NON-eligible to
678 /// the canonical type propagation optimization.
679 ///
680 /// @param types the set of types to consider. In that vector, all
681 /// types that come after @p type are going to be marked as being
682 /// non-eligible to the canonical type propagation optimization.
683 ///
684 /// @return true iff the operation was successful.
685 bool
687 vector<const type_base*>& types)
688 {
689 bool found = false;
690 for (auto t : types)
691 {
692 if (!found
693 && (reinterpret_cast<uintptr_t>(t)
694 == reinterpret_cast<uintptr_t>(type)))
695 {
696 found = true;
697 continue;
698 }
699 else if (found)
700 t->priv_->set_depends_on_recursive_type(type);
701 }
702 return found;
703 }
704
705 /// In the stack of the current types being compared (as part of
706 /// type canonicalization), mark all the types that comes after a
707 /// certain one as NOT being eligible to the canonical type
708 /// propagation optimization.
709 ///
710 /// For a starter, please read about the @ref
711 /// OnTheFlyCanonicalization, aka, "canonical type propagation
712 /// optimization".
713 ///
714 /// To implement that optimization, we need, among other things to
715 /// maintain stack of the types (and their sub-types) being
716 /// currently compared as part of type canonicalization.
717 ///
718 /// Note that we only consider the type that is the right-hand-side
719 /// operand of the comparison because it's that one that is being
720 /// canonicalized and thus, that is not yet canonicalized.
721 ///
722 /// The reason why a type is deemed NON-eligible to the canonical
723 /// type propagation optimization is that it "depends" on
724 /// recursively present type. Let me explain.
725 ///
726 /// Suppose we have a type T that has sub-types named ST0 and ST1.
727 /// Suppose ST1 itself has a sub-type that is T itself. In this
728 /// case, we say that T is a recursive type, because it has T
729 /// (itself) as one of its sub-types:
730 ///
731 /// T
732 /// +-- ST0
733 /// |
734 /// +-- ST1
735 /// +
736 /// |
737 /// +-- T
738 ///
739 /// ST1 is said to "depend" on T because it has T as a sub-type.
740 /// But because T is recursive, then ST1 is said to depend on a
741 /// recursive type. Notice however that ST0 does not depend on any
742 /// recursive type.
743 ///
744 /// When we are at the point of comparing the sub-type T of ST1
745 /// against its counterpart, the stack of the right-hand-side
746 /// operands of the type canonicalization is going to look like
747 /// this:
748 ///
749 /// | T | ST1 |
750 ///
751 /// We don't add the type T to the stack as we detect that T was
752 /// already in there (recursive cycle).
753 ///
754 /// So, this function will basically mark ST1 as being NON-eligible
755 /// to being the target of canonical type propagation.
756 ///
757 /// @param right the right-hand-side operand of the type comparison.
758 ///
759 /// @return true iff the operation was successful.
760 bool
762 {
763 bool result = false;
764
765 result |=
767 right_type_comp_operands_);
768 recursive_types_.insert(reinterpret_cast<uintptr_t>(right));
769 return result;
770 }
771
772 /// Test if a type is a recursive one.
773 ///
774 /// @param t the type to consider.
775 ///
776 /// @return true iff @p t is recursive.
777 bool
779 {
780 return (recursive_types_.find(reinterpret_cast<uintptr_t>(t))
781 != recursive_types_.end());
782 }
783
784
785 /// Unflag a type as being recursive
786 ///
787 /// @param t the type to unflag
788 void
790 {recursive_types_.erase(reinterpret_cast<uintptr_t>(t));}
791
792 /// Propagate the canonical type of a type to another one.
793 ///
794 /// @param src the type to propagate the canonical type from.
795 ///
796 /// @param dest the type to propagate the canonical type of @p src
797 /// to.
798 ///
799 /// @return bool iff the canonical was propagated.
800 bool
801 propagate_ct(const type_base& src, const type_base& dest)
802 {
803 type_base_sptr canonical = src.get_canonical_type();
804 ABG_ASSERT(canonical);
805 dest.priv_->canonical_type = canonical;
806 dest.priv_->naked_canonical_type = canonical.get();
807 dest.priv_->set_canonical_type_propagated(true);
808#ifdef WITH_DEBUG_CT_PROPAGATION
809 // If dest was previously a type which propagated canonical type
810 // has been cleared, let the book-keeping system know.
811 erase_type_with_cleared_propagated_canonical_type(&dest);
812#endif
813 return true;
814 }
815
816 /// Mark a set of types that have been the target of canonical type
817 /// propagation and that depend on a recursive type as being
818 /// permanently canonicalized.
819 ///
820 /// To understand the sentence above, please read the description of
821 /// type canonicalization and especially about the "canonical type
822 /// propagation optimization" at @ref OnTheFlyCanonicalization, in
823 /// the src/abg-ir.cc file.
824 void
826 {
827 pointer_set to_remove;
828 for (auto i : types_with_non_confirmed_propagated_ct_)
829 {
830 type_base *t = reinterpret_cast<type_base*>(i);
831 t->priv_->set_does_not_depend_on_recursive_type(dependant_type);
832 if (!t->priv_->depends_on_recursive_type())
833 {
834 to_remove.insert(i);
836#ifdef WITH_DEBUG_SELF_COMPARISON
837 check_abixml_canonical_type_propagation_during_self_comp(t);
838#endif
839 }
840 }
841
842 for (auto i : to_remove)
843 types_with_non_confirmed_propagated_ct_.erase(i);
844 }
845
846 /// Mark a type that has been the target of canonical type
847 /// propagation as being permanently canonicalized.
848 ///
849 /// This function also marks the set of types that have been the
850 /// target of canonical type propagation and that depend on a
851 /// recursive type as being permanently canonicalized.
852 ///
853 /// To understand the sentence above, please read the description of
854 /// type canonicalization and especially about the "canonical type
855 /// propagation optimization" at @ref OnTheFlyCanonicalization, in
856 /// the src/abg-ir.cc file.
857 void
859 {
860 if (!t || t->priv_->propagated_canonical_type_confirmed())
861 return;
862
863 const environment& env = t->get_environment();
864
865 env.priv_->confirm_ct_propagation_for_types_dependant_on(t);
867 env.priv_->remove_from_types_with_non_confirmed_propagated_ct(t);
868 env.priv_->set_is_not_recursive(t);
870#ifdef WITH_DEBUG_SELF_COMPARISON
871 check_abixml_canonical_type_propagation_during_self_comp(t);
872#endif
873 }
874
875 /// Mark all the types that have been the target of canonical type
876 /// propagation and that are not yet confirmed as being permanently
877 /// canonicalized (aka confirmed).
878 ///
879 /// To understand the sentence above, please read the description of
880 /// type canonicalization and especially about the "canonical type
881 /// propagation optimization" at @ref OnTheFlyCanonicalization, in
882 /// the src/abg-ir.cc file.
883 void
885 {
886 for (auto i : types_with_non_confirmed_propagated_ct_)
887 {
888 type_base *t = reinterpret_cast<type_base*>(i);
891#ifdef WITH_DEBUG_SELF_COMPARISON
892 check_abixml_canonical_type_propagation_during_self_comp(t);
893#endif
894 }
895 types_with_non_confirmed_propagated_ct_.clear();
896 }
897
898#ifdef WITH_DEBUG_CT_PROPAGATION
899 /// Getter for the set of types which propagated canonical type has
900 /// been cleared during the "canonical type propagation
901 /// optimization" phase. Those types are tracked in this set to
902 /// ensure that they are later canonicalized. This means that at
903 /// the end of the canonicalization process, this set must be empty.
904 ///
905 /// @return the set of types which propagated canonical type has
906 /// been cleared.
907 const pointer_set&
908 types_with_cleared_propagated_ct() const
909 {return types_with_cleared_propagated_ct_;}
910
911 /// Getter for the set of types which propagated canonical type has
912 /// been cleared during the "canonical type propagation
913 /// optimization" phase. Those types are tracked in this set to
914 /// ensure that they are later canonicalized. This means that at
915 /// the end of the canonicalization process, this set must be empty.
916 ///
917 /// @return the set of types which propagated canonical type has
918 /// been cleared.
920 types_with_cleared_propagated_ct()
921 {return types_with_cleared_propagated_ct_;}
922
923 /// Record a type which propagated canonical type has been cleared
924 /// during the "canonical type propagation optimization phase".
925 ///
926 /// @param t the type to record.
927 void
928 record_type_with_cleared_propagated_canonical_type(const type_base* t)
929 {
930 uintptr_t ptr = reinterpret_cast<uintptr_t>(t);
931 types_with_cleared_propagated_ct_.insert(ptr);
932 }
933
934 /// Erase a type (which propagated canonical type has been cleared
935 /// during the "canonical type propagation optimization phase") from
936 /// the set of types that have been recorded by the invocation of
937 /// record_type_with_cleared_propagated_canonical_type()
938 ///
939 /// @param t the type to erase from the set.
940 void
941 erase_type_with_cleared_propagated_canonical_type(const type_base* t)
942 {
943 uintptr_t ptr = reinterpret_cast<uintptr_t>(t);
944 types_with_cleared_propagated_ct_.erase(ptr);
945 }
946#endif //WITH_DEBUG_CT_PROPAGATION
947
948 /// Collect the types that depends on a given "target" type.
949 ///
950 /// Walk a set of types and if they depend directly or indirectly on
951 /// a "target" type, then collect them into a set.
952 ///
953 /// @param target the target type to consider.
954 ///
955 /// @param types the types to walk to detect those who depend on @p
956 /// target.
957 ///
958 /// @return true iff one or more type from @p types is found to
959 /// depend on @p target.
960 bool
962 const pointer_set& types,
963 pointer_set& collected)
964 {
965 bool result = false;
966 for (const auto i : types)
967 {
968 // First avoid infinite loop if we've already collected the
969 // current type.
970 if (collected.find(i) != collected.end())
971 continue;
972
973 type_base *t = reinterpret_cast<type_base*>(i);
974 if (t->priv_->depends_on_recursive_type(target))
975 {
976 collected.insert(i);
977 collect_types_that_depends_on(t, types, collected);
978 result = true;
979 }
980 }
981 return result;
982 }
983
984 /// Reset the canonical type (set it nullptr) of a set of types that
985 /// have been the target of canonical type propagation and that
986 /// depend on a given recursive type.
987 ///
988 /// Once the canonical type of a type in that set is reset, the type
989 /// is marked as being non-dependant on a recursive type anymore.
990 ///
991 /// To understand the sentences above, please read the description
992 /// of type canonicalization and especially about the "canonical
993 /// type propagation optimization" at @ref OnTheFlyCanonicalization,
994 /// in the src/abg-ir.cc file.
995 ///
996 /// @param target if a type which has been subject to the canonical
997 /// type propagation optimizationdepends on a this target type, then
998 /// cancel its canonical type.
999 void
1001 {
1002 pointer_set to_remove;
1004 types_with_non_confirmed_propagated_ct_,
1005 to_remove);
1006
1007 for (auto i : to_remove)
1008 {
1009 type_base *t = reinterpret_cast<type_base*>(i);
1010 ABG_ASSERT(t->get_environment().priv_->is_recursive_type(t)
1011 || t->priv_->depends_on_recursive_type());
1012 type_base_sptr canonical = t->priv_->canonical_type.lock();
1013 if (canonical)
1014 {
1017 }
1018 }
1019
1020 for (auto i : to_remove)
1021 types_with_non_confirmed_propagated_ct_.erase(i);
1022 }
1023
1024 /// Reset the canonical type (set it nullptr) of a type that has
1025 /// been the target of canonical type propagation.
1026 ///
1027 /// This also resets the propagated canonical type of the set of
1028 /// types that depends on a given recursive type.
1029 ///
1030 /// Once the canonical type of a type in that set is reset, the type
1031 /// is marked as being non-dependant on a recursive type anymore.
1032 ///
1033 /// To understand the sentences above, please read the description
1034 /// of type canonicalization and especially about the "canonical
1035 /// type propagation optimization" at @ref OnTheFlyCanonicalization,
1036 /// in the src/abg-ir.cc file.
1037 ///
1038 /// @param target if a type which has been subject to the canonical
1039 /// type propagation optimizationdepends on a this target type, then
1040 /// cancel its canonical type.
1041 void
1043 {
1044 if (!t)
1045 return;
1046
1047 const environment& env = t->get_environment();
1048 env.priv_->cancel_ct_propagation_for_types_dependant_on(t);
1049 // This cannot carry any tentative canonical type at this
1050 // point.
1052 // Reset the marking of the type as it no longer carries a
1053 // tentative canonical type that might be later canceled.
1055 env.priv_->remove_from_types_with_non_confirmed_propagated_ct(t);
1056 env.priv_->clear_type_comparison_results_cache();
1057 }
1058
1059 /// Clear the propagated canonical type of a given type.
1060 ///
1061 /// This function also updates the book-keeping of the set of types
1062 /// which propagated canonical types have been cleared.
1063 ///
1064 /// Please note that at the end of the canonicalization of all the
1065 /// types in the system, all the types which propagated canonical
1066 /// type has been cleared must be canonicalized.
1067 ///
1068 /// @param t the type to
1069 void
1071 {
1072 if (t->priv_->clear_propagated_canonical_type())
1073 {
1074#ifdef WITH_DEBUG_CT_PROPAGATION
1075 // let the book-keeping system know that t has its propagated
1076 // canonical type cleared.
1077 record_type_with_cleared_propagated_canonical_type(t)
1078#endif
1079 ;
1080 }
1081 }
1082
1083 /// Add a given type to the set of types that have been
1084 /// non-confirmed subjects of the canonical type propagation
1085 /// optimization.
1086 ///
1087 /// @param t the dependant type to consider.
1088 void
1090 {
1091 uintptr_t v = reinterpret_cast<uintptr_t>(t);
1092 types_with_non_confirmed_propagated_ct_.insert(v);
1093 }
1094
1095 /// Remove a given type from the set of types that have been
1096 /// non-confirmed subjects of the canonical type propagation
1097 /// optimization.
1098 ///
1099 /// @param dependant the dependant type to consider.
1100 void
1102 {
1103 uintptr_t i = reinterpret_cast<uintptr_t>(dependant);
1104 types_with_non_confirmed_propagated_ct_.erase(i);
1105 }
1106
1107 /// Cancel the propagated canonical types of all the types which
1108 /// propagated canonical type have not yet been confirmed.
1109 void
1111 {
1112 vector<uintptr_t> to_erase;
1113 for (auto i : types_with_non_confirmed_propagated_ct_)
1114 to_erase.push_back(i);
1115
1116 for (auto i : to_erase)
1117 {
1118 type_base *t = reinterpret_cast<type_base*>(i);
1120 }
1121 }
1122
1123#ifdef WITH_DEBUG_SELF_COMPARISON
1124
1125 const unordered_map<string, uintptr_t>&
1126 get_type_id_canonical_type_map() const
1127 {return type_id_canonical_type_map_;}
1128
1129 unordered_map<string, uintptr_t>&
1130 get_type_id_canonical_type_map()
1131 {return type_id_canonical_type_map_;}
1132
1133 const unordered_map<uintptr_t, string>&
1134 get_pointer_type_id_map() const
1135 {return pointer_type_id_map_;}
1136
1137 unordered_map<uintptr_t, string>&
1138 get_pointer_type_id_map()
1139 {return pointer_type_id_map_;}
1140
1141 string
1142 get_type_id_from_pointer(uintptr_t ptr) const
1143 {
1144 auto it = get_pointer_type_id_map().find(ptr);
1145 if (it != get_pointer_type_id_map().end())
1146 return it->second;
1147 return "";
1148 }
1149
1150 string
1151 get_type_id_from_type(const type_base *t) const
1152 {return get_type_id_from_pointer(reinterpret_cast<uintptr_t>(t));}
1153
1154 uintptr_t
1155 get_canonical_type_from_type_id(const char* type_id) const
1156 {
1157 if (!type_id)
1158 return 0;
1159 auto it = get_type_id_canonical_type_map().find(type_id);
1160 if (it != get_type_id_canonical_type_map().end())
1161 return it->second;
1162 return 0;
1163 }
1164
1165 /// When debugging self comparison, verify that a type T
1166 /// de-serialized from abixml has the same canonical type as the
1167 /// initial type built from DWARF that was serialized into T in the
1168 /// first place.
1169 ///
1170 /// @param t deserialized type (from abixml) to consider.
1171 ///
1172 /// @param c the canonical type that @p t has, as computed freshly
1173 /// from the abixml file.
1174 ///
1175 /// @return true iff @p c has the same value as the canonical type
1176 /// that @p t had before being serialized into abixml.
1177 bool
1178 check_canonical_type_from_abixml_during_self_comp(const type_base* t,
1179 const type_base* c)
1180 {
1181 if (!t || !t->get_corpus() || !c)
1182 return false;
1183
1184 if (!(t->get_corpus()->get_origin() == ir::corpus::NATIVE_XML_ORIGIN))
1185 return false;
1186
1187 // Get the abixml type-id that this type was constructed from.
1188 string type_id;
1189 {
1190 unordered_map<uintptr_t, string>::const_iterator it =
1191 pointer_type_id_map_.find(reinterpret_cast<uintptr_t>(t));
1192 if (it == pointer_type_id_map_.end())
1193 // This type didn't have a type-id in the abixml file. Maybe
1194 // it's a function or method type. So let's just keep going.
1195 return true;
1196 type_id = it->second;
1197 }
1198
1199 // Get the canonical type the original in-memory type (constructed
1200 // from DWARF) had when it was serialized into abixml in the first place.
1201 type_base *original_canonical_type = nullptr;
1202 if (!type_id.empty())
1203 {
1204 unordered_map<string, uintptr_t>::const_iterator it =
1205 type_id_canonical_type_map_.find(type_id);
1206 if (it == type_id_canonical_type_map_.end())
1207 return false;
1208 original_canonical_type = reinterpret_cast<type_base*>(it->second);
1209 }
1210
1211 // Now perform the real check.
1212 //
1213 // We want to ensure that the canonical type 'c' of 't' is the
1214 // same as the canonical type of initial in-memory type (built
1215 // from DWARF) that was serialized into 't' (in abixml) in the
1216 // first place.
1217 if (original_canonical_type == c)
1218 return true;
1219
1220 return false;
1221 }
1222
1223 /// When debugging self comparison, verify that a type T
1224 /// de-serialized from abixml has the same canonical type as the
1225 /// initial type built from DWARF that was serialized into T in the
1226 /// first place.
1227 ///
1228 /// @param t deserialized type (from abixml) to consider.
1229 ///
1230 /// @return true iff @p c is the canonical type that @p t should
1231 /// have.
1232 bool
1233 check_abixml_canonical_type_propagation_during_self_comp(const type_base* t)
1234 {
1235 if (t->get_corpus()
1236 && t->get_corpus()->get_origin() == ir::corpus::NATIVE_XML_ORIGIN)
1237 {
1238 type_base* c = t->get_naked_canonical_type();
1239 if (c && !check_canonical_type_from_abixml_during_self_comp(t, c))
1240 {
1241 string repr = t->get_pretty_representation(true, true);
1242 string type_id = get_type_id_from_type(t);
1243 std::cerr << "error: canonical type propagation error for '"
1244 << repr
1245 << "' of type-id: '"
1246 << type_id
1247 << "' / type: @"
1248 << std::hex
1249 << t
1250 << "/ canon: @"
1251 << c
1252 << ", should have had canonical type: "
1253 << std::hex
1254 << get_canonical_type_from_type_id(type_id.c_str())
1255 << "\n";
1256 return false;
1257 }
1258 }
1259 return true;
1260 }
1261
1262 /// When debugging self comparison, verify that a type T
1263 /// de-serialized from abixml has the same canonical type as the
1264 /// initial type built from DWARF that was serialized into T in the
1265 /// first place.
1266 ///
1267 /// @param t deserialized type (from abixml) to consider.
1268 ///
1269 /// @param c the canonical type @p t should have.
1270 ///
1271 /// @return true iff @p c is the canonical type that @p t should
1272 /// have.
1273 bool
1274 check_canonical_type_from_abixml_during_self_comp(const type_base_sptr& t,
1275 const type_base_sptr& c)
1276 {
1277 return check_canonical_type_from_abixml_during_self_comp(t.get(), c.get());
1278 }
1279#endif
1280};// end struct environment::priv
1281
1282/// Compute the canonical type for all the IR types of the system.
1283///
1284/// After invoking this function, the time it takes to compare two
1285/// types of the IR is equivalent to the time it takes to compare
1286/// their pointer value. That is faster than performing a structural
1287/// (A.K.A. member-wise) comparison.
1288///
1289/// Note that this function performs some sanity checks after* the
1290/// canonicalization process. It ensures that at the end of the
1291/// canonicalization process, all types have been canonicalized. This
1292/// is important because the canonicalization algorithm sometimes
1293/// clears some canonical types after having speculatively set them
1294/// for performance purposes. At the end of the process however, all
1295/// types must be canonicalized, and this function detects violations
1296/// of that assertion.
1297///
1298/// @tparam input_iterator the type of the input iterator of the @p
1299/// beging and @p end.
1300///
1301/// @tparam deref_lambda a lambda function which takes in parameter
1302/// the input iterator of type @p input_iterator and dereferences it
1303/// to return the type to canonicalize.
1304///
1305/// @param begin an iterator pointing to the first type of the set of types
1306/// to canonicalize.
1307///
1308/// @param end an iterator pointing to the end (after the last type) of
1309/// the set of types to canonicalize.
1310///
1311/// @param deref a lambda function that knows how to dereference the
1312/// iterator @p begin to return the type to canonicalize.
1313template<typename input_iterator,
1314 typename deref_lambda>
1315void
1316canonicalize_types(const input_iterator& begin,
1317 const input_iterator& end,
1318 deref_lambda deref)
1319{
1320 if (begin == end)
1321 return;
1322
1323 // First, let's compute the canonical type of this type.
1324 for (auto t = begin; t != end; ++t)
1325 canonicalize(deref(t));
1326
1327#ifdef WITH_DEBUG_CT_PROPAGATION
1328 // Then now, make sure that all types -- which propagated canonical
1329 // type has been cleared -- have been canonicalized. In other
1330 // words, the set of types which have been recorded because their
1331 // propagated canonical type has been cleared must be empty.
1332 const environment& env = deref(begin)->get_environment();
1333 pointer_set to_canonicalize =
1334 env.priv_->types_with_cleared_propagated_ct();
1335
1336 ABG_ASSERT(to_canonicalize.empty());
1337#endif // WITH_DEBUG_CT_PROPAGATION
1338}
1339
1340// <class_or_union::priv definitions>
1342{
1343 typedef_decl_wptr naming_typedef_;
1344 data_members data_members_;
1345 data_members non_static_data_members_;
1346 member_functions member_functions_;
1347 // A map that associates a linkage name to a member function.
1348 string_mem_fn_sptr_map_type mem_fns_map_;
1349 // A map that associates function signature strings to member
1350 // function.
1351 string_mem_fn_ptr_map_type signature_2_mem_fn_map_;
1352 member_function_templates member_function_templates_;
1353 member_class_templates member_class_templates_;
1354
1355 priv()
1356 {}
1357
1360 : data_members_(data_mbrs),
1361 member_functions_(mbr_fns)
1362 {
1363 for (data_members::const_iterator i = data_members_.begin();
1364 i != data_members_.end();
1365 ++i)
1366 if (!get_member_is_static(*i))
1367 non_static_data_members_.push_back(*i);
1368 }
1369
1370 /// Mark a pair of classes or unions as being currently compared
1371 /// using the class_or_union== operator.
1372 ///
1373 /// Note that this marking business is to avoid infinite loop when
1374 /// comparing a pair of classes or unions. If via the comparison of
1375 /// a data member or a member function a recursive re-comparison of
1376 /// the class or union is attempted, the marking process helps to
1377 /// detect that infinite loop possibility and avoid it.
1378 ///
1379 /// @param first the class or union (of the pair) to mark as being
1380 /// currently compared.
1381 ///
1382 /// @param second the second class or union (of the pair) to mark as
1383 /// being currently compared.
1384 void
1386 const class_or_union& second) const
1387 {
1388 const environment& env = first.get_environment();
1389
1390 env.priv_->left_classes_being_compared_.insert(&first);
1391 env.priv_->right_classes_being_compared_.insert(&second);
1392 }
1393
1394 /// Mark a pair of classes or unions as being currently compared
1395 /// using the class_or_union== operator.
1396 ///
1397 /// Note that this marking business is to avoid infinite loop when
1398 /// comparing a pair of classes or unions. If via the comparison of
1399 /// a data member or a member function a recursive re-comparison of
1400 /// the class or union is attempted, the marking process helps to
1401 /// detect that infinite loop possibility and avoid it.
1402 ///
1403 /// @param first the class or union (of the pair) to mark as being
1404 /// currently compared.
1405 ///
1406 /// @param second the second class or union (of the pair) to mark as
1407 /// being currently compared.
1408 void
1410 const class_or_union* second) const
1411 {mark_as_being_compared(*first, *second);}
1412
1413 /// Mark a pair of classes or unions as being currently compared
1414 /// using the class_or_union== operator.
1415 ///
1416 /// Note that this marking business is to avoid infinite loop when
1417 /// comparing a pair of classes or unions. If via the comparison of
1418 /// a data member or a member function a recursive re-comparison of
1419 /// the class or union is attempted, the marking process helps to
1420 /// detect that infinite loop possibility and avoid it.
1421 ///
1422 /// @param first the class or union (of the pair) to mark as being
1423 /// currently compared.
1424 ///
1425 /// @param second the second class or union (of the pair) to mark as
1426 /// being currently compared.
1427 void
1428 mark_as_being_compared(const class_or_union_sptr& first,
1429 const class_or_union_sptr& second) const
1430 {mark_as_being_compared(*first, *second);}
1431
1432 /// If a pair of class_or_union has been previously marked as
1433 /// being compared -- via an invocation of mark_as_being_compared()
1434 /// this method unmarks it. Otherwise is has no effect.
1435 ///
1436 /// This method is not thread safe because it uses the static data
1437 /// member classes_being_compared_. If you wish to use it in a
1438 /// multi-threaded environment you should probably protect the
1439 /// access to that static data member with a mutex or somesuch.
1440 ///
1441 /// @param first the first instance of class_or_union (of the pair)
1442 /// to unmark.
1443 ///
1444 /// @param second the second instance of class_or_union (of the
1445 /// pair) to unmark.
1446 void
1448 const class_or_union& second) const
1449 {
1450 const environment& env = first.get_environment();
1451
1452 env.priv_->left_classes_being_compared_.erase(&first);
1453 env.priv_->right_classes_being_compared_.erase(&second);
1454 }
1455
1456 /// If a pair of class_or_union has been previously marked as
1457 /// being compared -- via an invocation of mark_as_being_compared()
1458 /// this method unmarks it. Otherwise is has no effect.
1459 ///
1460 /// This method is not thread safe because it uses the static data
1461 /// member classes_being_compared_. If you wish to use it in a
1462 /// multi-threaded environment you should probably protect the
1463 /// access to that static data member with a mutex or somesuch.
1464 ///
1465 /// @param first the first instance of class_or_union (of the pair)
1466 /// to unmark.
1467 ///
1468 /// @param second the second instance of class_or_union (of the
1469 /// pair) to unmark.
1470 void
1472 const class_or_union* second) const
1473 {
1474 if (!first || !second)
1475 return;
1476 unmark_as_being_compared(*first, *second);
1477 }
1478
1479 /// Test if a pair of class_or_union is being currently compared.
1480 ///
1481 ///@param first the first class or union (of the pair) to test for.
1482 ///
1483 ///@param second the second class or union (of the pair) to test for.
1484 ///
1485 /// @return true if the pair {@p first, @p second} is being
1486 /// compared, false otherwise.
1487 bool
1489 const class_or_union& second) const
1490 {
1491 const environment& env = first.get_environment();
1492
1493 return (env.priv_->left_classes_being_compared_.count(&first)
1494 || env.priv_->right_classes_being_compared_.count(&second)
1495 || env.priv_->right_classes_being_compared_.count(&first)
1496 || env.priv_->left_classes_being_compared_.count(&second));
1497 }
1498
1499 /// Test if a pair of class_or_union is being currently compared.
1500 ///
1501 ///@param first the first class or union (of the pair) to test for.
1502 ///
1503 ///@param second the second class or union (of the pair) to test for.
1504 ///
1505 /// @return true if the pair {@p first, @p second} is being
1506 /// compared, false otherwise.
1507 bool
1509 const class_or_union* second) const
1510 {
1511 if (first && second)
1512 return comparison_started(*first, *second);
1513 return false;
1514 }
1515}; // end struct class_or_union::priv
1516
1517// <function_type::priv definitions>
1518
1519/// The type of the private data of the @ref function_type type.
1521{
1522 parameters parms_;
1523 type_base_wptr return_type_;
1524 interned_string cached_name_;
1525 interned_string internal_cached_name_;
1526 interned_string temp_internal_cached_name_;
1527
1528 priv()
1529 {}
1530
1531 priv(const parameters& parms,
1532 type_base_sptr return_type)
1533 : parms_(parms),
1534 return_type_(return_type)
1535 {}
1536
1537 priv(type_base_sptr return_type)
1538 : return_type_(return_type)
1539 {}
1540
1541 /// Mark a given pair of @ref function_type as being compared.
1542 ///
1543 /// @param first the first @ref function_type of the pair being
1544 /// compared, to mark.
1545 ///
1546 /// @param second the second @ref function_type of the pair being
1547 /// compared, to mark.
1548 void
1550 const function_type& second) const
1551 {
1552 const environment& env = first.get_environment();
1553
1554 env.priv_->left_fn_types_being_compared_.insert(&first);
1555 env.priv_->right_fn_types_being_compared_.insert(&second);
1556 }
1557
1558 /// Mark a given pair of @ref function_type as being compared.
1559 ///
1560 /// @param first the first @ref function_type of the pair being
1561 /// compared, to mark.
1562 ///
1563 /// @param second the second @ref function_type of the pair being
1564 /// compared, to mark.
1565 void
1567 const function_type& second) const
1568 {
1569 const environment& env = first.get_environment();
1570
1571 env.priv_->left_fn_types_being_compared_.erase(&first);
1572 env.priv_->right_fn_types_being_compared_.erase(&second);
1573 }
1574
1575 /// Tests if a @ref function_type is currently being compared.
1576 ///
1577 /// @param type the function type to take into account.
1578 ///
1579 /// @return true if @p type is being compared.
1580 bool
1582 const function_type& second) const
1583 {
1584 const environment& env = first.get_environment();
1585
1586 return (env.priv_->left_fn_types_being_compared_.count(&first)
1587 ||
1588 env.priv_->right_fn_types_being_compared_.count(&second));
1589 }
1590};// end struc function_type::priv
1591
1592// </function_type::priv definitions>
1593
1594} // end namespace ir
1595
1596} // end namespace abigail
1597
1598#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:1612
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:3948
vector< method_decl_sptr > member_functions
Convenience typedef.
Definition: abg-ir.h:3979
unordered_map< string, method_decl * > string_mem_fn_ptr_map_type
Convenience typedef.
Definition: abg-ir.h:3981
vector< var_decl_sptr > data_members
Convenience typedef.
Definition: abg-ir.h:3978
unordered_map< string, method_decl_sptr > string_mem_fn_sptr_map_type
Convenience typedef.
Definition: abg-ir.h:3982
This is the abstraction of a set of translation units (themselves seen as bundles of unitary abi arte...
Definition: abg-corpus.h:25
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:5717
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:3309
std::vector< parameter_sptr > parameters
Convenience typedef for a vector of parameter_sptr.
Definition: abg-ir.h:3321
The internal representation of an integral type.
Definition: abg-ir-priv.h:46
void set_modifiers(modifiers_type)
Setter of the modifiers bitmap of the integral_type.
Definition: abg-ir.cc:15586
string to_string(bool internal=false) const
Return the string representation of the current instance of integral_type.
Definition: abg-ir.cc:15609
base_type get_base_type() const
Getter of the base type of the integral_type.
Definition: abg-ir.cc:15572
modifiers_type
The modifiers of the base types above. Several modifiers can be combined for a given base type....
Definition: abg-ir-priv.h:80
@ LONG_LONG_MODIFIER
The "long long" modifier.
Definition: abg-ir-priv.h:91
@ LONG_MODIFIER
The "long" modifier.
Definition: abg-ir-priv.h:89
@ SIGNED_MODIFIER
The "signed" modifier.
Definition: abg-ir-priv.h:83
@ UNSIGNED_MODIFIER
The "unsigned" modier.
Definition: abg-ir-priv.h:85
@ SHORT_MODIFIER
The "short" modifier.
Definition: abg-ir-priv.h:87
bool operator==(const integral_type &) const
Equality operator for the integral_type.
Definition: abg-ir.cc:15596
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:54
@ WCHAR_T_BASE_TYPE
The "wchar_t" base type.
Definition: abg-ir-priv.h:70
@ CHAR32_T_BASE_TYPE
The "char32_t" base type.
Definition: abg-ir-priv.h:68
@ FLOAT_BASE_TYPE
The "float" base type.
Definition: abg-ir-priv.h:64
@ BOOL_BASE_TYPE
The "bool" base type in C++ or "_Bool" in C11.
Definition: abg-ir-priv.h:60
@ CHAR_BASE_TYPE
The "char" base type.
Definition: abg-ir-priv.h:58
@ CHAR16_T_BASE_TYPE
The "char16_t base type.
Definition: abg-ir-priv.h:66
@ INT_BASE_TYPE
The "int" base type.
Definition: abg-ir-priv.h:56
@ DOUBLE_BASE_TYPE
The "double" base type.
Definition: abg-ir-priv.h:62
modifiers_type get_modifiers() const
Getter of the modifiers bitmap of the integral_type.
Definition: abg-ir.cc:15579
integral_type()
Default constructor of the integral_type.
Definition: abg-ir.cc:15542
The entry point to manage locations.
Definition: abg-ir.h:441
language
The language of the translation unit.
Definition: abg-ir.h:685
shared_ptr< scope_decl > global_scope_sptr
Convenience typedef for a shared pointer on a global_scope.
Definition: abg-ir.h:681
An abstraction helper for type declarations.
Definition: abg-ir.h:1960
type_base_sptr get_canonical_type() const
Getter of the canonical type of the current instance of type_base.
Definition: abg-ir.cc:15149
This is a type that aggregates maps of all the kinds of types that are supported by libabigail.
Definition: abg-ir.h:585
const environment & get_environment() const
Getter of the environment of the current ABI artifact.
Definition: abg-ir.cc:4324
weak_ptr< typedef_decl > typedef_decl_wptr
Convenience typedef for a weak pointer on a typedef_decl.
Definition: abg-fwd.h:167
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:385
corpus::origin operator|=(corpus::origin &l, corpus::origin r)
Bitwise |= operator for the corpus::origin type.
Definition: abg-corpus.cc:1617
bool is_type(const type_or_decl_base &tod)
Test whether a declaration is a type.
Definition: abg-ir.cc:10248
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:376
integral_type::modifiers_type operator~(integral_type::modifiers_type l)
Bitwise one's complement operator for integral_type::modifiers_type.
Definition: abg-ir.cc:15344
unordered_set< const function_type * > fn_set_type
A convenience typedef for a set of pointer to function_type.
Definition: abg-ir-priv.h:379
comparison_result
The result of structural comparison of type ABI artifacts.
Definition: abg-ir-priv.h:33
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:1316
weak_ptr< corpus > corpus_wptr
Convenience typedef for a weak pointer to a corpus.
Definition: abg-fwd.h:132
corpus::origin operator|(corpus::origin l, corpus::origin r)
Bitwise | operator for the corpus::origin type.
Definition: abg-corpus.cc:1603
bool parse_integral_type(const string &type_name, integral_type &type)
Parse an integral type from a string.
Definition: abg-ir.cc:15527
corpus::origin operator&(corpus::origin l, corpus::origin r)
Bitwise & operator for the corpus::origin type.
Definition: abg-corpus.cc:1631
type_base_sptr canonicalize(type_base_sptr t)
Compute the canonical type of a given type.
Definition: abg-ir.cc:15034
unordered_set< uintptr_t > pointer_set
A convenience typedef for an unordered set of pointer values.
Definition: abg-ir.h:100
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:373
corpus::origin operator&=(corpus::origin &l, corpus::origin r)
Bitwise &= operator for the corpus::origin type.
Definition: abg-corpus.cc:1645
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:369
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:1488
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:1508
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:1428
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:1385
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:1409
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:1471
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:1447
The private data of the environment type.
Definition: abg-ir-priv.h:389
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:884
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:607
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:961
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:825
void set_is_not_recursive(const type_base *t)
Unflag a type as being recursive.
Definition: abg-ir-priv.h:789
void clear_type_comparison_results_cache()
Clear the cache type comparison results.
Definition: abg-ir-priv.h:625
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:638
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:1101
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:858
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:1089
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:761
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:1110
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:1000
void clear_propagated_canonical_type(const type_base *t)
Clear the propagated canonical type of a given type.
Definition: abg-ir-priv.h:1070
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:661
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:542
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:553
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:686
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:801
void cache_type_comparison_result(T &first, T &second, bool r)
Cache the result of comparing two sub-types.
Definition: abg-ir-priv.h:569
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:1042
bool is_recursive_type(const type_base *t)
Test if a type is a recursive one.
Definition: abg-ir-priv.h:778
The type of the private data of the function_type type.
Definition: abg-ir-priv.h:1521
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:1549
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:1581
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:1566
Private type to hold private members of translation_unit.
Definition: abg-ir-priv.h:143
Definition of the private data of type_base.
Definition: abg-ir-priv.h:179
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:284
void set_propagated_canonical_type_confirmed(bool f)
Setter of the property propagated-canonical-type-confirmed.
Definition: abg-ir-priv.h:335
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:289
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:251
bool propagated_canonical_type_confirmed() const
Getter of the property propagated-canonical-type-confirmed.
Definition: abg-ir-priv.h:322
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:269
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:299
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:341
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:309
bool depends_on_recursive_type() const
Test if the current type depends on recursive type comparison.
Definition: abg-ir-priv.h:234
The hashing functor for a pair of uint64_t.
Definition: abg-ir-priv.h:358
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:363