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 bool do_log_;
498 optional<bool> analyze_exported_interfaces_only_;
499#ifdef WITH_DEBUG_SELF_COMPARISON
500 bool self_comparison_debug_on_;
501#endif
502#ifdef WITH_DEBUG_TYPE_CANONICALIZATION
503 // This controls whether to use canonical type comparison during
504 // type comparison or not. This is only used for debugging, when we
505 // want to ensure that comparing types using canonical or structural
506 // comparison yields the same result.
507 bool use_canonical_type_comparison_;
508 // Whether we are debugging type canonicalization or not. When
509 // debugging type canonicalization, a type is compared to its
510 // potential canonical type twice: The first time with canonical
511 // comparison activated, and the second time with structural
512 // comparison activated. The two comparison should yield the same
513 // result, otherwise, canonicalization is "broken" for that
514 // particular type.
515 bool debug_type_canonicalization_;
516 bool debug_die_canonicalization_;
517#endif
518
519 priv()
520 : canonicalization_is_done_(),
521 do_on_the_fly_canonicalization_(true),
522 decl_only_class_equals_definition_(false),
523 use_enum_binary_only_equality_(true),
524 allow_type_comparison_results_caching_(false),
525 do_log_(false)
526#ifdef WITH_DEBUG_SELF_COMPARISON
527 ,
528 self_comparison_debug_on_(false)
529#endif
530#ifdef WITH_DEBUG_TYPE_CANONICALIZATION
531 ,
532 use_canonical_type_comparison_(true),
533 debug_type_canonicalization_(false),
534 debug_die_canonicalization_(false)
535#endif
536 {}
537
538 /// Allow caching of the sub-types comparison results during the
539 /// invocation of the @ref equal overloads for class and function
540 /// types.
541 ///
542 /// @param f if true, allow type comparison result caching.
543 void
545 {allow_type_comparison_results_caching_ = f;}
546
547 /// Check whether if caching of the sub-types comparison results during the
548 /// invocation of the @ref equal overloads for class and function
549 /// types is in effect.
550 ///
551 /// @return true iff caching of the sub-types comparison results
552 /// during the invocation of the @ref equal overloads for class and
553 /// function types is in effect.
554 bool
556 {return allow_type_comparison_results_caching_;}
557
558 void
559 do_log(bool f)
560 {do_log_ = f;}
561
562 bool
563 do_log() const
564 {return do_log_;}
565
566 /// Cache the result of comparing two sub-types.
567 ///
568 /// @param first the first sub-type that has been compared. Its
569 /// address is going to be stored in the cache.
570 ///
571 /// @param second the second sub-type that has been compared. Its
572 /// address is going to be stored in the cache.
573 ///
574 /// @param r the result of comparing @p first and @p second. This
575 /// is going to be stored in the cache, as well as the addresses of
576 /// @p first and @p second.
577 template<typename T>
578 void
579 cache_type_comparison_result(T& first, T& second, bool r)
580 {
582 && (r == false
583 ||
584 (!is_recursive_type(&first)
585 && !is_recursive_type(&second)
586 && !is_type(&first)->priv_->depends_on_recursive_type()
587 && !is_type(&second)->priv_->depends_on_recursive_type())))
588 {
589 type_comparison_results_cache_.emplace
590 (std::make_pair(reinterpret_cast<uint64_t>(&first),
591 reinterpret_cast<uint64_t>(&second)),
592 r);
593 }
594 }
595
596 /// Retrieve the result of comparing two sub-types from the cache,
597 /// if it was previously stored.
598 ///
599 /// @param first the first sub-type to consider.
600 ///
601 /// @param second the second sub-type to consider. The pair of
602 /// addresses of {@p first, @p second} is going to be looked up in
603 /// the cache. If it's present, then the associated result of the
604 /// comparison of @p first against @p second is present as well, and
605 /// is returned.
606 ///
607 /// @param r this is an out parameter which is set to the result of
608 /// the comparison of @p first against @p second if the pair of
609 /// addresses of {@p first, @p second} is present in the cache.
610 ///
611 /// @return true iff the pair of addresses of {@p first, @p second}
612 /// is present in the cache. In that case, the associated result of
613 /// the comparison of @p first against @p second is returned in the
614 /// argument of @p r.
615 template<typename T>
616 bool
617 is_type_comparison_cached(T& first, T& second, bool& r)
618 {
620 return false;
621
622 type_comparison_result_type::const_iterator it =
623 type_comparison_results_cache_.find
624 (std::make_pair(reinterpret_cast<uint64_t>(&first),
625 reinterpret_cast<uint64_t>(&second)));
626 if (it == type_comparison_results_cache_.end())
627 return false;
628
629 r = it->second;
630 return true;
631 }
632
633 /// Clear the cache type comparison results.
634 void
636 {type_comparison_results_cache_.clear();}
637
638 /// Push a pair of operands on the stack of operands of the current
639 /// type comparison, during type canonicalization.
640 ///
641 /// For more information on this, please look at the description of
642 /// the right_type_comp_operands_ data member.
643 ///
644 /// @param left the left-hand-side comparison operand to push.
645 ///
646 /// @param right the right-hand-side comparison operand to push.
647 void
649 const type_base* right)
650 {
651 ABG_ASSERT(left && right);
652
653 left_type_comp_operands_.push_back(left);
654 right_type_comp_operands_.push_back(right);
655 }
656
657 /// Pop a pair of operands from the stack of operands to the current
658 /// type comparison.
659 ///
660 /// For more information on this, please look at the description of
661 /// the right_type_comp_operands_ data member.
662 ///
663 /// @param left the left-hand-side comparison operand we expect to
664 /// pop from the top of the stack. If this doesn't match the
665 /// operand found on the top of the stack, the function aborts.
666 ///
667 /// @param right the right-hand-side comparison operand we expect to
668 /// pop from the bottom of the stack. If this doesn't match the
669 /// operand found on the top of the stack, the function aborts.
670 void
672 const type_base* right)
673 {
674 const type_base *t = left_type_comp_operands_.back();
675 ABG_ASSERT(t == left);
676 t = right_type_comp_operands_.back();
677 ABG_ASSERT(t == right);
678
679 left_type_comp_operands_.pop_back();
680 right_type_comp_operands_.pop_back();
681 }
682
683 /// Mark all the types that comes after a certain one as NOT being
684 /// eligible for the canonical type propagation optimization.
685 ///
686 /// @param type the type that represents the "marker type". All
687 /// types after this one will be marked as being NON-eligible to
688 /// the canonical type propagation optimization.
689 ///
690 /// @param types the set of types to consider. In that vector, all
691 /// types that come after @p type are going to be marked as being
692 /// non-eligible to the canonical type propagation optimization.
693 ///
694 /// @return true iff the operation was successful.
695 bool
697 vector<const type_base*>& types)
698 {
699 bool found = false;
700 for (auto t : types)
701 {
702 if (!found
703 && (reinterpret_cast<uintptr_t>(t)
704 == reinterpret_cast<uintptr_t>(type)))
705 {
706 found = true;
707 continue;
708 }
709 else if (found)
710 t->priv_->set_depends_on_recursive_type(type);
711 }
712 return found;
713 }
714
715 /// In the stack of the current types being compared (as part of
716 /// type canonicalization), mark all the types that comes after a
717 /// certain one as NOT being eligible to the canonical type
718 /// propagation optimization.
719 ///
720 /// For a starter, please read about the @ref
721 /// OnTheFlyCanonicalization, aka, "canonical type propagation
722 /// optimization".
723 ///
724 /// To implement that optimization, we need, among other things to
725 /// maintain stack of the types (and their sub-types) being
726 /// currently compared as part of type canonicalization.
727 ///
728 /// Note that we only consider the type that is the right-hand-side
729 /// operand of the comparison because it's that one that is being
730 /// canonicalized and thus, that is not yet canonicalized.
731 ///
732 /// The reason why a type is deemed NON-eligible to the canonical
733 /// type propagation optimization is that it "depends" on
734 /// recursively present type. Let me explain.
735 ///
736 /// Suppose we have a type T that has sub-types named ST0 and ST1.
737 /// Suppose ST1 itself has a sub-type that is T itself. In this
738 /// case, we say that T is a recursive type, because it has T
739 /// (itself) as one of its sub-types:
740 ///
741 /// T
742 /// +-- ST0
743 /// |
744 /// +-- ST1
745 /// +
746 /// |
747 /// +-- T
748 ///
749 /// ST1 is said to "depend" on T because it has T as a sub-type.
750 /// But because T is recursive, then ST1 is said to depend on a
751 /// recursive type. Notice however that ST0 does not depend on any
752 /// recursive type.
753 ///
754 /// When we are at the point of comparing the sub-type T of ST1
755 /// against its counterpart, the stack of the right-hand-side
756 /// operands of the type canonicalization is going to look like
757 /// this:
758 ///
759 /// | T | ST1 |
760 ///
761 /// We don't add the type T to the stack as we detect that T was
762 /// already in there (recursive cycle).
763 ///
764 /// So, this function will basically mark ST1 as being NON-eligible
765 /// to being the target of canonical type propagation.
766 ///
767 /// @param right the right-hand-side operand of the type comparison.
768 ///
769 /// @return true iff the operation was successful.
770 bool
772 {
773 bool result = false;
774
775 result |=
777 right_type_comp_operands_);
778 recursive_types_.insert(reinterpret_cast<uintptr_t>(right));
779 return result;
780 }
781
782 /// Test if a type is a recursive one.
783 ///
784 /// @param t the type to consider.
785 ///
786 /// @return true iff @p t is recursive.
787 bool
789 {
790 return (recursive_types_.find(reinterpret_cast<uintptr_t>(t))
791 != recursive_types_.end());
792 }
793
794
795 /// Unflag a type as being recursive
796 ///
797 /// @param t the type to unflag
798 void
800 {recursive_types_.erase(reinterpret_cast<uintptr_t>(t));}
801
802 /// Propagate the canonical type of a type to another one.
803 ///
804 /// @param src the type to propagate the canonical type from.
805 ///
806 /// @param dest the type to propagate the canonical type of @p src
807 /// to.
808 ///
809 /// @return bool iff the canonical was propagated.
810 bool
811 propagate_ct(const type_base& src, const type_base& dest)
812 {
813 type_base_sptr canonical = src.get_canonical_type();
814 ABG_ASSERT(canonical);
815 dest.priv_->canonical_type = canonical;
816 dest.priv_->naked_canonical_type = canonical.get();
817 dest.priv_->set_canonical_type_propagated(true);
818#ifdef WITH_DEBUG_CT_PROPAGATION
819 // If dest was previously a type which propagated canonical type
820 // has been cleared, let the book-keeping system know.
821 erase_type_with_cleared_propagated_canonical_type(&dest);
822#endif
823 return true;
824 }
825
826 /// Mark a set of types that have been the target of canonical type
827 /// propagation and that depend on a recursive type as being
828 /// permanently canonicalized.
829 ///
830 /// To understand the sentence above, please read the description of
831 /// type canonicalization and especially about the "canonical type
832 /// propagation optimization" at @ref OnTheFlyCanonicalization, in
833 /// the src/abg-ir.cc file.
834 void
836 {
837 pointer_set to_remove;
838 for (auto i : types_with_non_confirmed_propagated_ct_)
839 {
840 type_base *t = reinterpret_cast<type_base*>(i);
841 t->priv_->set_does_not_depend_on_recursive_type(dependant_type);
842 if (!t->priv_->depends_on_recursive_type())
843 {
844 to_remove.insert(i);
846#ifdef WITH_DEBUG_SELF_COMPARISON
847 check_abixml_canonical_type_propagation_during_self_comp(t);
848#endif
849 }
850 }
851
852 for (auto i : to_remove)
853 types_with_non_confirmed_propagated_ct_.erase(i);
854 }
855
856 /// Mark a type that has been the target of canonical type
857 /// propagation as being permanently canonicalized.
858 ///
859 /// This function also marks the set of types that have been the
860 /// target of canonical type propagation and that depend on a
861 /// recursive type as being permanently canonicalized.
862 ///
863 /// To understand the sentence above, please read the description of
864 /// type canonicalization and especially about the "canonical type
865 /// propagation optimization" at @ref OnTheFlyCanonicalization, in
866 /// the src/abg-ir.cc file.
867 void
869 {
870 if (!t || t->priv_->propagated_canonical_type_confirmed())
871 return;
872
873 const environment& env = t->get_environment();
874
875 env.priv_->confirm_ct_propagation_for_types_dependant_on(t);
877 env.priv_->remove_from_types_with_non_confirmed_propagated_ct(t);
878 env.priv_->set_is_not_recursive(t);
880#ifdef WITH_DEBUG_SELF_COMPARISON
881 check_abixml_canonical_type_propagation_during_self_comp(t);
882#endif
883 }
884
885 /// Mark all the types that have been the target of canonical type
886 /// propagation and that are not yet confirmed as being permanently
887 /// canonicalized (aka confirmed).
888 ///
889 /// To understand the sentence above, please read the description of
890 /// type canonicalization and especially about the "canonical type
891 /// propagation optimization" at @ref OnTheFlyCanonicalization, in
892 /// the src/abg-ir.cc file.
893 void
895 {
896 for (auto i : types_with_non_confirmed_propagated_ct_)
897 {
898 type_base *t = reinterpret_cast<type_base*>(i);
901#ifdef WITH_DEBUG_SELF_COMPARISON
902 check_abixml_canonical_type_propagation_during_self_comp(t);
903#endif
904 }
905 types_with_non_confirmed_propagated_ct_.clear();
906 }
907
908#ifdef WITH_DEBUG_CT_PROPAGATION
909 /// Getter for the set of types which propagated canonical type has
910 /// been cleared during the "canonical type propagation
911 /// optimization" phase. Those types are tracked in this set to
912 /// ensure that they are later canonicalized. This means that at
913 /// the end of the canonicalization process, this set must be empty.
914 ///
915 /// @return the set of types which propagated canonical type has
916 /// been cleared.
917 const pointer_set&
918 types_with_cleared_propagated_ct() const
919 {return types_with_cleared_propagated_ct_;}
920
921 /// Getter for the set of types which propagated canonical type has
922 /// been cleared during the "canonical type propagation
923 /// optimization" phase. Those types are tracked in this set to
924 /// ensure that they are later canonicalized. This means that at
925 /// the end of the canonicalization process, this set must be empty.
926 ///
927 /// @return the set of types which propagated canonical type has
928 /// been cleared.
930 types_with_cleared_propagated_ct()
931 {return types_with_cleared_propagated_ct_;}
932
933 /// Record a type which propagated canonical type has been cleared
934 /// during the "canonical type propagation optimization phase".
935 ///
936 /// @param t the type to record.
937 void
938 record_type_with_cleared_propagated_canonical_type(const type_base* t)
939 {
940 uintptr_t ptr = reinterpret_cast<uintptr_t>(t);
941 types_with_cleared_propagated_ct_.insert(ptr);
942 }
943
944 /// Erase a type (which propagated canonical type has been cleared
945 /// during the "canonical type propagation optimization phase") from
946 /// the set of types that have been recorded by the invocation of
947 /// record_type_with_cleared_propagated_canonical_type()
948 ///
949 /// @param t the type to erase from the set.
950 void
951 erase_type_with_cleared_propagated_canonical_type(const type_base* t)
952 {
953 uintptr_t ptr = reinterpret_cast<uintptr_t>(t);
954 types_with_cleared_propagated_ct_.erase(ptr);
955 }
956#endif //WITH_DEBUG_CT_PROPAGATION
957
958 /// Collect the types that depends on a given "target" type.
959 ///
960 /// Walk a set of types and if they depend directly or indirectly on
961 /// a "target" type, then collect them into a set.
962 ///
963 /// @param target the target type to consider.
964 ///
965 /// @param types the types to walk to detect those who depend on @p
966 /// target.
967 ///
968 /// @return true iff one or more type from @p types is found to
969 /// depend on @p target.
970 bool
972 const pointer_set& types,
973 pointer_set& collected)
974 {
975 bool result = false;
976 for (const auto i : types)
977 {
978 // First avoid infinite loop if we've already collected the
979 // current type.
980 if (collected.find(i) != collected.end())
981 continue;
982
983 type_base *t = reinterpret_cast<type_base*>(i);
984 if (t->priv_->depends_on_recursive_type(target))
985 {
986 collected.insert(i);
987 collect_types_that_depends_on(t, types, collected);
988 result = true;
989 }
990 }
991 return result;
992 }
993
994 /// Reset the canonical type (set it nullptr) of a set of types that
995 /// have been the target of canonical type propagation and that
996 /// depend on a given recursive type.
997 ///
998 /// Once the canonical type of a type in that set is reset, the type
999 /// is marked as being non-dependant on a recursive type anymore.
1000 ///
1001 /// To understand the sentences above, please read the description
1002 /// of type canonicalization and especially about the "canonical
1003 /// type propagation optimization" at @ref OnTheFlyCanonicalization,
1004 /// in the src/abg-ir.cc file.
1005 ///
1006 /// @param target if a type which has been subject to the canonical
1007 /// type propagation optimizationdepends on a this target type, then
1008 /// cancel its canonical type.
1009 void
1011 {
1012 pointer_set to_remove;
1014 types_with_non_confirmed_propagated_ct_,
1015 to_remove);
1016
1017 for (auto i : to_remove)
1018 {
1019 type_base *t = reinterpret_cast<type_base*>(i);
1020 ABG_ASSERT(t->get_environment().priv_->is_recursive_type(t)
1021 || t->priv_->depends_on_recursive_type());
1022 type_base_sptr canonical = t->priv_->canonical_type.lock();
1023 if (canonical)
1024 {
1027 }
1028 }
1029
1030 for (auto i : to_remove)
1031 types_with_non_confirmed_propagated_ct_.erase(i);
1032 }
1033
1034 /// Reset the canonical type (set it nullptr) of a type that has
1035 /// been the target of canonical type propagation.
1036 ///
1037 /// This also resets the propagated canonical type of the set of
1038 /// types that depends on a given recursive type.
1039 ///
1040 /// Once the canonical type of a type in that set is reset, the type
1041 /// is marked as being non-dependant on a recursive type anymore.
1042 ///
1043 /// To understand the sentences above, please read the description
1044 /// of type canonicalization and especially about the "canonical
1045 /// type propagation optimization" at @ref OnTheFlyCanonicalization,
1046 /// in the src/abg-ir.cc file.
1047 ///
1048 /// @param target if a type which has been subject to the canonical
1049 /// type propagation optimizationdepends on a this target type, then
1050 /// cancel its canonical type.
1051 void
1053 {
1054 if (!t)
1055 return;
1056
1057 const environment& env = t->get_environment();
1058 env.priv_->cancel_ct_propagation_for_types_dependant_on(t);
1059 // This cannot carry any tentative canonical type at this
1060 // point.
1062 // Reset the marking of the type as it no longer carries a
1063 // tentative canonical type that might be later canceled.
1065 env.priv_->remove_from_types_with_non_confirmed_propagated_ct(t);
1066 env.priv_->clear_type_comparison_results_cache();
1067 }
1068
1069 /// Clear the propagated canonical type of a given type.
1070 ///
1071 /// This function also updates the book-keeping of the set of types
1072 /// which propagated canonical types have been cleared.
1073 ///
1074 /// Please note that at the end of the canonicalization of all the
1075 /// types in the system, all the types which propagated canonical
1076 /// type has been cleared must be canonicalized.
1077 ///
1078 /// @param t the type to
1079 void
1081 {
1082 if (t->priv_->clear_propagated_canonical_type())
1083 {
1084#ifdef WITH_DEBUG_CT_PROPAGATION
1085 // let the book-keeping system know that t has its propagated
1086 // canonical type cleared.
1087 record_type_with_cleared_propagated_canonical_type(t)
1088#endif
1089 ;
1090 }
1091 }
1092
1093 /// Add a given type to the set of types that have been
1094 /// non-confirmed subjects of the canonical type propagation
1095 /// optimization.
1096 ///
1097 /// @param t the dependant type to consider.
1098 void
1100 {
1101 uintptr_t v = reinterpret_cast<uintptr_t>(t);
1102 types_with_non_confirmed_propagated_ct_.insert(v);
1103 }
1104
1105 /// Remove a given type from the set of types that have been
1106 /// non-confirmed subjects of the canonical type propagation
1107 /// optimization.
1108 ///
1109 /// @param dependant the dependant type to consider.
1110 void
1112 {
1113 uintptr_t i = reinterpret_cast<uintptr_t>(dependant);
1114 types_with_non_confirmed_propagated_ct_.erase(i);
1115 }
1116
1117 /// Cancel the propagated canonical types of all the types which
1118 /// propagated canonical type have not yet been confirmed.
1119 void
1121 {
1122 vector<uintptr_t> to_erase;
1123 for (auto i : types_with_non_confirmed_propagated_ct_)
1124 to_erase.push_back(i);
1125
1126 for (auto i : to_erase)
1127 {
1128 type_base *t = reinterpret_cast<type_base*>(i);
1130 }
1131 }
1132
1133#ifdef WITH_DEBUG_SELF_COMPARISON
1134
1135 const unordered_map<string, uintptr_t>&
1136 get_type_id_canonical_type_map() const
1137 {return type_id_canonical_type_map_;}
1138
1139 unordered_map<string, uintptr_t>&
1140 get_type_id_canonical_type_map()
1141 {return type_id_canonical_type_map_;}
1142
1143 const unordered_map<uintptr_t, string>&
1144 get_pointer_type_id_map() const
1145 {return pointer_type_id_map_;}
1146
1147 unordered_map<uintptr_t, string>&
1148 get_pointer_type_id_map()
1149 {return pointer_type_id_map_;}
1150
1151 string
1152 get_type_id_from_pointer(uintptr_t ptr) const
1153 {
1154 auto it = get_pointer_type_id_map().find(ptr);
1155 if (it != get_pointer_type_id_map().end())
1156 return it->second;
1157 return "";
1158 }
1159
1160 string
1161 get_type_id_from_type(const type_base *t) const
1162 {return get_type_id_from_pointer(reinterpret_cast<uintptr_t>(t));}
1163
1164 uintptr_t
1165 get_canonical_type_from_type_id(const char* type_id) const
1166 {
1167 if (!type_id)
1168 return 0;
1169 auto it = get_type_id_canonical_type_map().find(type_id);
1170 if (it != get_type_id_canonical_type_map().end())
1171 return it->second;
1172 return 0;
1173 }
1174
1175 /// When debugging self comparison, verify that a type T
1176 /// de-serialized from abixml has the same canonical type as the
1177 /// initial type built from DWARF that was serialized into T in the
1178 /// first place.
1179 ///
1180 /// @param t deserialized type (from abixml) to consider.
1181 ///
1182 /// @param c the canonical type that @p t has, as computed freshly
1183 /// from the abixml file.
1184 ///
1185 /// @return true iff @p c has the same value as the canonical type
1186 /// that @p t had before being serialized into abixml.
1187 bool
1188 check_canonical_type_from_abixml_during_self_comp(const type_base* t,
1189 const type_base* c)
1190 {
1191 if (!t || !t->get_corpus() || !c)
1192 return false;
1193
1194 if (!(t->get_corpus()->get_origin() == ir::corpus::NATIVE_XML_ORIGIN))
1195 return false;
1196
1197 // Get the abixml type-id that this type was constructed from.
1198 string type_id;
1199 {
1200 unordered_map<uintptr_t, string>::const_iterator it =
1201 pointer_type_id_map_.find(reinterpret_cast<uintptr_t>(t));
1202 if (it == pointer_type_id_map_.end())
1203 // This type didn't have a type-id in the abixml file. Maybe
1204 // it's a function or method type. So let's just keep going.
1205 return true;
1206 type_id = it->second;
1207 }
1208
1209 // Get the canonical type the original in-memory type (constructed
1210 // from DWARF) had when it was serialized into abixml in the first place.
1211 type_base *original_canonical_type = nullptr;
1212 if (!type_id.empty())
1213 {
1214 unordered_map<string, uintptr_t>::const_iterator it =
1215 type_id_canonical_type_map_.find(type_id);
1216 if (it == type_id_canonical_type_map_.end())
1217 return false;
1218 original_canonical_type = reinterpret_cast<type_base*>(it->second);
1219 }
1220
1221 // Now perform the real check.
1222 //
1223 // We want to ensure that the canonical type 'c' of 't' is the
1224 // same as the canonical type of initial in-memory type (built
1225 // from DWARF) that was serialized into 't' (in abixml) in the
1226 // first place.
1227 if (original_canonical_type == c)
1228 return true;
1229
1230 return false;
1231 }
1232
1233 /// When debugging self comparison, verify that a type T
1234 /// de-serialized from abixml has the same canonical type as the
1235 /// initial type built from DWARF that was serialized into T in the
1236 /// first place.
1237 ///
1238 /// @param t deserialized type (from abixml) to consider.
1239 ///
1240 /// @return true iff @p c is the canonical type that @p t should
1241 /// have.
1242 bool
1243 check_abixml_canonical_type_propagation_during_self_comp(const type_base* t)
1244 {
1245 if (t->get_corpus()
1246 && t->get_corpus()->get_origin() == ir::corpus::NATIVE_XML_ORIGIN)
1247 {
1248 type_base* c = t->get_naked_canonical_type();
1249 if (c && !check_canonical_type_from_abixml_during_self_comp(t, c))
1250 {
1251 string repr = t->get_pretty_representation(true, true);
1252 string type_id = get_type_id_from_type(t);
1253 std::cerr << "error: canonical type propagation error for '"
1254 << repr
1255 << "' of type-id: '"
1256 << type_id
1257 << "' / type: @"
1258 << std::hex
1259 << t
1260 << "/ canon: @"
1261 << c
1262 << ", should have had canonical type: "
1263 << std::hex
1264 << get_canonical_type_from_type_id(type_id.c_str())
1265 << "\n";
1266 return false;
1267 }
1268 }
1269 return true;
1270 }
1271
1272 /// When debugging self comparison, verify that a type T
1273 /// de-serialized from abixml has the same canonical type as the
1274 /// initial type built from DWARF that was serialized into T in the
1275 /// first place.
1276 ///
1277 /// @param t deserialized type (from abixml) to consider.
1278 ///
1279 /// @param c the canonical type @p t should have.
1280 ///
1281 /// @return true iff @p c is the canonical type that @p t should
1282 /// have.
1283 bool
1284 check_canonical_type_from_abixml_during_self_comp(const type_base_sptr& t,
1285 const type_base_sptr& c)
1286 {
1287 return check_canonical_type_from_abixml_during_self_comp(t.get(), c.get());
1288 }
1289#endif
1290};// end struct environment::priv
1291
1292/// Compute the canonical type for all the IR types of the system.
1293///
1294/// After invoking this function, the time it takes to compare two
1295/// types of the IR is equivalent to the time it takes to compare
1296/// their pointer value. That is faster than performing a structural
1297/// (A.K.A. member-wise) comparison.
1298///
1299/// Note that this function performs some sanity checks after* the
1300/// canonicalization process. It ensures that at the end of the
1301/// canonicalization process, all types have been canonicalized. This
1302/// is important because the canonicalization algorithm sometimes
1303/// clears some canonical types after having speculatively set them
1304/// for performance purposes. At the end of the process however, all
1305/// types must be canonicalized, and this function detects violations
1306/// of that assertion.
1307///
1308/// @tparam input_iterator the type of the input iterator of the @p
1309/// beging and @p end.
1310///
1311/// @tparam deref_lambda a lambda function which takes in parameter
1312/// the input iterator of type @p input_iterator and dereferences it
1313/// to return the type to canonicalize.
1314///
1315/// @param begin an iterator pointing to the first type of the set of types
1316/// to canonicalize.
1317///
1318/// @param end an iterator pointing to the end (after the last type) of
1319/// the set of types to canonicalize.
1320///
1321/// @param deref a lambda function that knows how to dereference the
1322/// iterator @p begin to return the type to canonicalize.
1323template<typename input_iterator,
1324 typename deref_lambda>
1325void
1326canonicalize_types(const input_iterator& begin,
1327 const input_iterator& end,
1328 deref_lambda deref)
1329{
1330 if (begin == end)
1331 return;
1332
1333 int i;
1334 input_iterator t;
1335 // First, let's compute the canonical type of this type.
1336 for (t = begin,i = 0; t != end; ++t, ++i)
1337 {
1338 if (deref(t)->get_environment().priv_->do_log())
1339 std::cerr << "#" << std::dec << i << " ";
1340
1341 canonicalize(deref(t));
1342 }
1343
1344#ifdef WITH_DEBUG_CT_PROPAGATION
1345 // Then now, make sure that all types -- which propagated canonical
1346 // type has been cleared -- have been canonicalized. In other
1347 // words, the set of types which have been recorded because their
1348 // propagated canonical type has been cleared must be empty.
1349 const environment& env = deref(begin)->get_environment();
1350 pointer_set to_canonicalize =
1351 env.priv_->types_with_cleared_propagated_ct();
1352
1353 ABG_ASSERT(to_canonicalize.empty());
1354#endif // WITH_DEBUG_CT_PROPAGATION
1355}
1356
1357// <class_or_union::priv definitions>
1359{
1360 typedef_decl_wptr naming_typedef_;
1361 data_members data_members_;
1362 data_members non_static_data_members_;
1363 member_functions member_functions_;
1364 // A map that associates a linkage name to a member function.
1365 string_mem_fn_sptr_map_type mem_fns_map_;
1366 // A map that associates function signature strings to member
1367 // function.
1368 string_mem_fn_ptr_map_type signature_2_mem_fn_map_;
1369 member_function_templates member_function_templates_;
1370 member_class_templates member_class_templates_;
1371
1372 priv()
1373 {}
1374
1377 : data_members_(data_mbrs),
1378 member_functions_(mbr_fns)
1379 {
1380 for (data_members::const_iterator i = data_members_.begin();
1381 i != data_members_.end();
1382 ++i)
1383 if (!get_member_is_static(*i))
1384 non_static_data_members_.push_back(*i);
1385 }
1386
1387 /// Mark a pair of classes or unions as being currently compared
1388 /// using the class_or_union== operator.
1389 ///
1390 /// Note that this marking business is to avoid infinite loop when
1391 /// comparing a pair of classes or unions. If via the comparison of
1392 /// a data member or a member function a recursive re-comparison of
1393 /// the class or union is attempted, the marking process helps to
1394 /// detect that infinite loop possibility and avoid it.
1395 ///
1396 /// @param first the class or union (of the pair) to mark as being
1397 /// currently compared.
1398 ///
1399 /// @param second the second class or union (of the pair) to mark as
1400 /// being currently compared.
1401 void
1403 const class_or_union& second) const
1404 {
1405 const environment& env = first.get_environment();
1406
1407 env.priv_->left_classes_being_compared_.insert(&first);
1408 env.priv_->right_classes_being_compared_.insert(&second);
1409 }
1410
1411 /// Mark a pair of classes or unions as being currently compared
1412 /// using the class_or_union== operator.
1413 ///
1414 /// Note that this marking business is to avoid infinite loop when
1415 /// comparing a pair of classes or unions. If via the comparison of
1416 /// a data member or a member function a recursive re-comparison of
1417 /// the class or union is attempted, the marking process helps to
1418 /// detect that infinite loop possibility and avoid it.
1419 ///
1420 /// @param first the class or union (of the pair) to mark as being
1421 /// currently compared.
1422 ///
1423 /// @param second the second class or union (of the pair) to mark as
1424 /// being currently compared.
1425 void
1427 const class_or_union* second) const
1428 {mark_as_being_compared(*first, *second);}
1429
1430 /// Mark a pair of classes or unions as being currently compared
1431 /// using the class_or_union== operator.
1432 ///
1433 /// Note that this marking business is to avoid infinite loop when
1434 /// comparing a pair of classes or unions. If via the comparison of
1435 /// a data member or a member function a recursive re-comparison of
1436 /// the class or union is attempted, the marking process helps to
1437 /// detect that infinite loop possibility and avoid it.
1438 ///
1439 /// @param first the class or union (of the pair) to mark as being
1440 /// currently compared.
1441 ///
1442 /// @param second the second class or union (of the pair) to mark as
1443 /// being currently compared.
1444 void
1445 mark_as_being_compared(const class_or_union_sptr& first,
1446 const class_or_union_sptr& second) const
1447 {mark_as_being_compared(*first, *second);}
1448
1449 /// If a pair of class_or_union has been previously marked as
1450 /// being compared -- via an invocation of mark_as_being_compared()
1451 /// this method unmarks it. Otherwise is has no effect.
1452 ///
1453 /// This method is not thread safe because it uses the static data
1454 /// member classes_being_compared_. If you wish to use it in a
1455 /// multi-threaded environment you should probably protect the
1456 /// access to that static data member with a mutex or somesuch.
1457 ///
1458 /// @param first the first instance of class_or_union (of the pair)
1459 /// to unmark.
1460 ///
1461 /// @param second the second instance of class_or_union (of the
1462 /// pair) to unmark.
1463 void
1465 const class_or_union& second) const
1466 {
1467 const environment& env = first.get_environment();
1468
1469 env.priv_->left_classes_being_compared_.erase(&first);
1470 env.priv_->right_classes_being_compared_.erase(&second);
1471 }
1472
1473 /// If a pair of class_or_union has been previously marked as
1474 /// being compared -- via an invocation of mark_as_being_compared()
1475 /// this method unmarks it. Otherwise is has no effect.
1476 ///
1477 /// This method is not thread safe because it uses the static data
1478 /// member classes_being_compared_. If you wish to use it in a
1479 /// multi-threaded environment you should probably protect the
1480 /// access to that static data member with a mutex or somesuch.
1481 ///
1482 /// @param first the first instance of class_or_union (of the pair)
1483 /// to unmark.
1484 ///
1485 /// @param second the second instance of class_or_union (of the
1486 /// pair) to unmark.
1487 void
1489 const class_or_union* second) const
1490 {
1491 if (!first || !second)
1492 return;
1493 unmark_as_being_compared(*first, *second);
1494 }
1495
1496 /// Test if a pair of class_or_union is being currently compared.
1497 ///
1498 ///@param first the first class or union (of the pair) to test for.
1499 ///
1500 ///@param second the second class or union (of the pair) to test for.
1501 ///
1502 /// @return true if the pair {@p first, @p second} is being
1503 /// compared, false otherwise.
1504 bool
1506 const class_or_union& second) const
1507 {
1508 const environment& env = first.get_environment();
1509
1510 return (env.priv_->left_classes_being_compared_.count(&first)
1511 || env.priv_->right_classes_being_compared_.count(&second)
1512 || env.priv_->right_classes_being_compared_.count(&first)
1513 || env.priv_->left_classes_being_compared_.count(&second));
1514 }
1515
1516 /// Test if a pair of class_or_union is being currently compared.
1517 ///
1518 ///@param first the first class or union (of the pair) to test for.
1519 ///
1520 ///@param second the second class or union (of the pair) to test for.
1521 ///
1522 /// @return true if the pair {@p first, @p second} is being
1523 /// compared, false otherwise.
1524 bool
1526 const class_or_union* second) const
1527 {
1528 if (first && second)
1529 return comparison_started(*first, *second);
1530 return false;
1531 }
1532}; // end struct class_or_union::priv
1533
1534// <function_type::priv definitions>
1535
1536/// The type of the private data of the @ref function_type type.
1538{
1539 parameters parms_;
1540 type_base_wptr return_type_;
1541 interned_string cached_name_;
1542 interned_string internal_cached_name_;
1543 interned_string temp_internal_cached_name_;
1544
1545 priv()
1546 {}
1547
1548 priv(const parameters& parms,
1549 type_base_sptr return_type)
1550 : parms_(parms),
1551 return_type_(return_type)
1552 {}
1553
1554 priv(type_base_sptr return_type)
1555 : return_type_(return_type)
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_.insert(&first);
1572 env.priv_->right_fn_types_being_compared_.insert(&second);
1573 }
1574
1575 /// Mark a given pair of @ref function_type as being compared.
1576 ///
1577 /// @param first the first @ref function_type of the pair being
1578 /// compared, to mark.
1579 ///
1580 /// @param second the second @ref function_type of the pair being
1581 /// compared, to mark.
1582 void
1584 const function_type& second) const
1585 {
1586 const environment& env = first.get_environment();
1587
1588 env.priv_->left_fn_types_being_compared_.erase(&first);
1589 env.priv_->right_fn_types_being_compared_.erase(&second);
1590 }
1591
1592 /// Tests if a @ref function_type is currently being compared.
1593 ///
1594 /// @param type the function type to take into account.
1595 ///
1596 /// @return true if @p type is being compared.
1597 bool
1599 const function_type& second) const
1600 {
1601 const environment& env = first.get_environment();
1602
1603 return (env.priv_->left_fn_types_being_compared_.count(&first)
1604 ||
1605 env.priv_->right_fn_types_being_compared_.count(&second));
1606 }
1607};// end struc function_type::priv
1608
1609// </function_type::priv definitions>
1610
1611} // end namespace ir
1612
1613} // end namespace abigail
1614
1615#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:1695
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:4026
vector< method_decl_sptr > member_functions
Convenience typedef.
Definition: abg-ir.h:4057
unordered_map< string, method_decl * > string_mem_fn_ptr_map_type
Convenience typedef.
Definition: abg-ir.h:4059
vector< var_decl_sptr > data_members
Convenience typedef.
Definition: abg-ir.h:4056
unordered_map< string, method_decl_sptr > string_mem_fn_sptr_map_type
Convenience typedef.
Definition: abg-ir.h:4060
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:5809
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:3387
std::vector< parameter_sptr > parameters
Convenience typedef for a vector of parameter_sptr.
Definition: abg-ir.h:3399
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:16320
string to_string(bool internal=false) const
Return the string representation of the current instance of integral_type.
Definition: abg-ir.cc:16343
base_type get_base_type() const
Getter of the base type of the integral_type.
Definition: abg-ir.cc:16306
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:16330
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:16313
integral_type()
Default constructor of the integral_type.
Definition: abg-ir.cc:16276
The entry point to manage locations.
Definition: abg-ir.h:441
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:15883
This is a type that aggregates maps of all the kinds of types that are supported by libabigail.
Definition: abg-ir.h:593
const environment & get_environment() const
Getter of the environment of the current ABI artifact.
Definition: abg-ir.cc:4415
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:1645
bool is_type(const type_or_decl_base &tod)
Test whether a declaration is a type.
Definition: abg-ir.cc:10541
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:16078
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:1326
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:1631
bool parse_integral_type(const string &type_name, integral_type &type)
Parse an integral type from a string.
Definition: abg-ir.cc:16261
corpus::origin operator&(corpus::origin l, corpus::origin r)
Bitwise & operator for the corpus::origin type.
Definition: abg-corpus.cc:1659
type_base_sptr canonicalize(type_base_sptr t)
Compute the canonical type of a given type.
Definition: abg-ir.cc:15752
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:1673
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:1505
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:1525
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:1445
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:1402
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:1426
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:1488
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:1464
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:894
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:617
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:971
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:835
void set_is_not_recursive(const type_base *t)
Unflag a type as being recursive.
Definition: abg-ir-priv.h:799
void clear_type_comparison_results_cache()
Clear the cache type comparison results.
Definition: abg-ir-priv.h:635
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:648
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:1111
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:868
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:1099
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:771
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:1120
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:1010
void clear_propagated_canonical_type(const type_base *t)
Clear the propagated canonical type of a given type.
Definition: abg-ir-priv.h:1080
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:671
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:544
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:555
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:696
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:811
void cache_type_comparison_result(T &first, T &second, bool r)
Cache the result of comparing two sub-types.
Definition: abg-ir-priv.h:579
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:1052
bool is_recursive_type(const type_base *t)
Test if a type is a recursive one.
Definition: abg-ir-priv.h:788
The type of the private data of the function_type type.
Definition: abg-ir-priv.h:1538
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:1566
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:1598
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:1583
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