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.
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 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 |=
776  mark_dependant_types(right,
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.
929  pointer_set&
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.
1323 template<typename input_iterator,
1324  typename deref_lambda>
1325 void
1326 canonicalize_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__
bool is_recursive_type(const type_base *t)
Test if a type is a recursive one.
Definition: abg-ir-priv.h:788
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
string to_string(bool internal=false) const
Return the string representation of the current instance of integral_type.
Definition: abg-ir.cc:16471
The type of the private data of the function_type type.
Definition: abg-ir-priv.h:1537
bool is_type(const type_or_decl_base &tod)
Test whether a declaration is a type.
Definition: abg-ir.cc:10665
void set_is_not_recursive(const type_base *t)
Unflag a type as being recursive.
Definition: abg-ir-priv.h:799
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
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:5816
integral_type()
Default constructor of the integral_type.
Definition: abg-ir.cc:16404
bool propagated_canonical_type_confirmed() const
Getter of the property propagated-canonical-type-confirmed.
Definition: abg-ir-priv.h:322
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 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
The internal representation of an integral type.
Definition: abg-ir-priv.h:45
comparison_result
The result of structural comparison of type ABI artifacts.
Definition: abg-ir-priv.h:32
An abstraction helper for type declarations.
Definition: abg-ir.h:1972
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
This is the abstraction of a set of translation units (themselves seen as bundles of unitary abi arte...
Definition: abg-corpus.h:24
Definition of the private data of type_base.
Definition: abg-ir-priv.h:178
weak_ptr< typedef_decl > typedef_decl_wptr
Convenience typedef for a weak pointer on a typedef_decl.
Definition: abg-fwd.h:171
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
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:53
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
shared_ptr< scope_decl > global_scope_sptr
Convenience typedef for a shared pointer on a global_scope.
Definition: abg-ir.h:695
base_type get_base_type() const
Getter of the base type of the integral_type.
Definition: abg-ir.cc:16434
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
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 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
unordered_set< uintptr_t > pointer_set
A convenience typedef for an unordered set of pointer values.
Definition: abg-ir.h:100
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
unordered_map< string, method_decl_sptr > string_mem_fn_sptr_map_type
Convenience typedef.
Definition: abg-ir.h:4063
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_modifiers(modifiers_type)
Setter of the modifiers bitmap of the integral_type.
Definition: abg-ir.cc:16448
The private data of the environment type.
Definition: abg-ir-priv.h:388
corpus::origin operator&=(corpus::origin &l, corpus::origin r)
Bitwise &= operator for the corpus::origin type.
Definition: abg-corpus.cc:1798
type_base_sptr canonicalize(type_base_sptr t)
Compute the canonical type of a given type.
Definition: abg-ir.cc:15880
Simplified implementation of std::optional just enough to be used as a replacement for our purposes a...
weak_ptr< type_base > type_base_wptr
Convenience typedef for a weak pointer on a type_base.
Definition: abg-fwd.h:129
const environment & get_environment() const
Getter of the environment of the current ABI artifact.
Definition: abg-ir.cc:4422
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
Private type to hold private members of translation_unit.
Definition: abg-ir-priv.h:142
Toplevel namespace for libabigail.
std::vector< parameter_sptr > parameters
Convenience typedef for a vector of parameter_sptr.
Definition: abg-ir.h:3402
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 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
Types of the main internal representation of libabigail.
modifiers_type
The modifiers of the base types above. Several modifiers can be combined for a given base type...
Definition: abg-ir-priv.h:79
The base type of class_decl and union_decl.
Definition: abg-ir.h:4028
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
This is a type that aggregates maps of all the kinds of types that are supported by libabigail...
Definition: abg-ir.h:592
This is an abstraction of the set of resources necessary to manage several aspects of the internal re...
Definition: abg-ir.h:139
vector< method_decl_sptr > member_functions
Convenience typedef.
Definition: abg-ir.h:4060
weak_ptr< corpus > corpus_wptr
Convenience typedef for a weak pointer to a corpus.
Definition: abg-fwd.h:132
The "bool" base type in C++ or "_Bool" in C11.
Definition: abg-ir-priv.h:60
#define ABG_ASSERT(cond)
This is a wrapper around the 'assert' glibc call. It allows for its argument to have side effects...
Definition: abg-fwd.h:1714
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
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
bool canonical_type_propagated()
Test if the type carries a canonical type that is the result of maybe_propagate_canonical_type(), aka, "canonical type propagation optimization".
Definition: abg-ir-priv.h:299
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
corpus::origin operator|(corpus::origin l, corpus::origin r)
Bitwise | operator for the corpus::origin type.
Definition: abg-corpus.cc:1756
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
type_base_sptr get_canonical_type() const
Getter of the canonical type of the current instance of type_base.
Definition: abg-ir.cc:16011
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
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
modifiers_type get_modifiers() const
Getter of the modifiers bitmap of the integral_type.
Definition: abg-ir.cc:16441
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
language
The language of the translation unit.
Definition: abg-ir.h:698
bool mark_dependant_types_compared_until(const type_base *right)
In the stack of the current types being compared (as part of type canonicalization), mark all the types that comes after a certain one as NOT being eligible to the canonical type propagation optimization.
Definition: abg-ir-priv.h:771
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
corpus::origin operator|=(corpus::origin &l, corpus::origin r)
Bitwise |= operator for the corpus::origin type.
Definition: abg-corpus.cc:1770
integral_type::modifiers_type operator~(integral_type::modifiers_type l)
Bitwise one's complement operator for integral_type::modifiers_type.
Definition: abg-ir.cc:16206
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
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
unordered_map< string, method_decl * > string_mem_fn_ptr_map_type
Convenience typedef.
Definition: abg-ir.h:4062
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
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
The abstraction of an interned string.
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
void clear_type_comparison_results_cache()
Clear the cache type comparison results.
Definition: abg-ir-priv.h:635
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
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
The interned string pool.
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
This type abstracts the configuration information of the library.
Definition: abg-config.h:17
vector< var_decl_sptr > data_members
Convenience typedef.
Definition: abg-ir.h:4059
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
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 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
corpus::origin operator&(corpus::origin l, corpus::origin r)
Bitwise & operator for the corpus::origin type.
Definition: abg-corpus.cc:1784
The hashing functor for a pair of uint64_t.
Definition: abg-ir-priv.h:357
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
bool parse_integral_type(const string &type_name, integral_type &type)
Parse an integral type from a string.
Definition: abg-ir.cc:16389
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
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
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 depends_on_recursive_type() const
Test if the current type depends on recursive type comparison.
Definition: abg-ir-priv.h:234
void set_propagated_canonical_type_confirmed(bool f)
Setter of the property propagated-canonical-type-confirmed.
Definition: abg-ir-priv.h:335
bool operator==(const integral_type &) const
Equality operator for the integral_type.
Definition: abg-ir.cc:16458
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
Abstraction of a function type.
Definition: abg-ir.h:3389
The entry point to manage locations.
Definition: abg-ir.h:440
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