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