xref: /third_party/libabigail/src/abg-ir-priv.h (revision e01aa904)
1// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2// -*- Mode: C++ -*-
3//
4// Copyright (C) 2016-2022 Red Hat, Inc.
5//
6// Author: Dodji Seketeli
7
8/// @file
9///
10/// This contains the private implementation of the suppression engine
11/// of libabigail.
12
13#ifndef __ABG_IR_PRIV_H__
14#define __ABG_IR_PRIV_H__
15
16#include <string>
17#include <iostream>
18
19#include "abg-ir.h"
20#include "abg-corpus.h"
21
22namespace abigail
23{
24
25namespace ir
26{
27
28using std::string;
29using abg_compat::optional;
30
31/// The result of structural comparison of type ABI artifacts.
32enum comparison_result
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.
45class integral_type
46{
47public:
48  /// The possible base types of integral types.  We might have
49  /// forgotten many of these, so do not hesitate to add new ones.
50  ///
51  /// If you do add new ones, please also consider updating functions
52  /// parse_base_integral_type and integral_type::to_string.
53  enum base_type
54  {
55    /// The "int" base type.
56    INT_BASE_TYPE,
57    /// The "char" base type.
58    CHAR_BASE_TYPE,
59    /// The "bool" base type in C++ or "_Bool" in C11.
60    BOOL_BASE_TYPE,
61    /// The "double" base type.
62    DOUBLE_BASE_TYPE,
63    /// The "float" base type.
64    FLOAT_BASE_TYPE,
65    /// The "char16_t base type.
66    CHAR16_T_BASE_TYPE,
67    /// The "char32_t" base type.
68    CHAR32_T_BASE_TYPE,
69    /// The "wchar_t" base type.
70    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.
79  enum modifiers_type
80  {
81    NO_MODIFIER = 0,
82    /// The "signed" modifier.
83    SIGNED_MODIFIER = 1,
84    /// The "unsigned" modier.
85    UNSIGNED_MODIFIER = 1 << 1,
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
94private:
95  base_type	base_;
96  modifiers_type modifiers_;
97
98public:
99
100  integral_type();
101  integral_type(const string& name);
102  integral_type(base_type, modifiers_type);
103
104  base_type
105  get_base_type() const;
106
107  modifiers_type
108  get_modifiers() const;
109
110  void
111  set_modifiers(modifiers_type);
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
122integral_type::modifiers_type
123operator|(integral_type::modifiers_type l, integral_type::modifiers_type r);
124
125integral_type::modifiers_type
126operator&(integral_type::modifiers_type l, integral_type::modifiers_type r);
127
128integral_type::modifiers_type
129operator~(integral_type::modifiers_type l);
130
131integral_type::modifiers_type&
132operator|=(integral_type::modifiers_type& l, integral_type::modifiers_type r);
133
134integral_type::modifiers_type&
135operator &=(integral_type::modifiers_type& l, integral_type::modifiers_type r);
136
137bool
138parse_integral_type(const string& type_name,
139		    integral_type& type);
140
141/// Private type to hold private members of @ref translation_unit
142struct translation_unit::priv
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.
178struct type_base::priv
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
234  depends_on_recursive_type() const
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
269  set_depends_on_recursive_type(const type_base * t)
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
284  set_does_not_depend_on_recursive_type(const type_base *t)
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
289  set_does_not_depend_on_recursive_type()
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
299  canonical_type_propagated()
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
309  set_canonical_type_propagated(bool f)
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
322  propagated_canonical_type_confirmed() const
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
335  set_propagated_canonical_type_confirmed(bool f)
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  void
341  clear_propagated_canonical_type()
342  {
343    if (canonical_type_propagated_ && !propagated_canonical_type_confirmed_)
344      {
345	canonical_type.reset();
346	naked_canonical_type = nullptr;
347	set_canonical_type_propagated(false);
348      }
349  }
350}; // end struct type_base::priv
351
352// <environment definitions>
353
354/// The hashing functor for a pair of uint64_t.
355struct uint64_t_pair_hash
356{
357  /// Hashing function for a pair of uint64_t.
358  ///
359  /// @param p the pair to hash.
360  uint64_t
361  operator()(const std::pair<uint64_t, uint64_t>& p) const
362  {return abigail::hashing::combine_hashes(p.first, p.second);}
363};
364
365/// A convenience typedef for a pair of uint64_t which is initially
366/// intended to store a pair of pointer values.
367typedef std::pair<uint64_t, uint64_t> uint64_t_pair_type;
368
369/// A convenience typedef for a set of @ref uint64_t_pair
370typedef unordered_set<uint64_t_pair_type,
371		      uint64_t_pair_hash> uint64_t_pairs_set_type;
372/// A convenience typedef for a map which key is a pair of uint64_t
373/// and which value is a boolean.  This is initially intended to cache
374/// the result of comparing two (sub-)types.
375typedef unordered_map<uint64_t_pair_type, bool,
376		      uint64_t_pair_hash> type_comparison_result_type;
377
378/// The private data of the @ref environment type.
379struct environment::priv
380{
381  config				config_;
382  canonical_types_map_type		canonical_types_;
383  mutable vector<type_base_sptr>	sorted_canonical_types_;
384  type_base_sptr			void_type_;
385  type_base_sptr			variadic_marker_type_;
386  // The set of pairs of class types being currently compared.  It's
387  // used to avoid endless loops while recursively comparing types.
388  // This should be empty when none of the 'equal' overloads are
389  // currently being invoked.
390  uint64_t_pairs_set_type		classes_being_compared_;
391  // The set of pairs of function types being currently compared.  It's used
392  // to avoid endless loops while recursively comparing types.  This
393  // should be empty when none of the 'equal' overloads are currently
394  // being invoked.
395  uint64_t_pairs_set_type		fn_types_being_compared_;
396  // This is a cache for the result of comparing two sub-types (of
397  // either class or function types) that are designated by their
398  // memory address in the IR.
399  type_comparison_result_type		type_comparison_results_cache_;
400  vector<type_base_sptr>		extra_live_types_;
401  interned_string_pool			string_pool_;
402  // The two vectors below represent the stack of left and right
403  // operands of the current type comparison operation that is
404  // happening during type canonicalization.
405  //
406  // Basically, that stack of operand looks like below.
407  //
408  // First, suppose we have a type T_L that has two sub-types as this:
409  //
410  //  T_L
411  //   |
412  //   +-- L_OP0
413  //   |
414  //   +-- L_OP1
415  //
416  // Now suppose that we have another type T_R that has two sub-types
417  // as this:
418  //
419  //  T_R
420  //   |
421  //   +-- R_OP0
422  //   |
423  //   +-- R_OP1
424  //
425  //   Now suppose that we compare T_L against T_R.  We are going to
426  //   have a stack of pair of types. Each pair of types represents
427  //   two (sub) types being compared against each other.
428  //
429  //   On the stack, we will thus first have the pair (T_L, T_R)
430  //   being compared.  Then, we will have the pair (L_OP0, R_OP0)
431  //   being compared, and then the pair (L_OP1, R_OP1) being
432  //   compared.  Like this:
433  //
434  // | T_L | L_OP0 | L_OP1 | <-- this goes into left_type_comp_operands_;
435  //  -------- -------------
436  // | T_R | R_OP0 | R_OP1 | <-- this goes into right_type_comp_operands_;
437  //
438  // This "stack of operands of the current type comparison, during
439  // type canonicalization" is used in the context of the @ref
440  // OnTheFlyCanonicalization optimization.  It's used to detect if a
441  // sub-type of the type being canonicalized depends on a recursive
442  // type.
443  vector<const type_base*>		left_type_comp_operands_;
444  vector<const type_base*>		right_type_comp_operands_;
445  // Vector of types that protentially received propagated canonical types.
446  // If the canonical type propagation is confirmed, the potential
447  // canonical types must be promoted as canonical types. Otherwise if
448  // the canonical type propagation is cancelled, the canonical types
449  // must be cleared.
450  pointer_set		types_with_non_confirmed_propagated_ct_;
451  pointer_set		recursive_types_;
452#ifdef WITH_DEBUG_SELF_COMPARISON
453  // This is used for debugging purposes.
454  // When abidw is used with the option --debug-abidiff, some
455  // libabigail internals need to get a hold on the initial binary
456  // input of abidw, as well as as the abixml file that represents the
457  // ABI of that binary.
458  //
459  // So this one is the corpus for the input binary.
460  corpus_wptr				first_self_comparison_corpus_;
461  // This one is the corpus for the ABIXML file representing the
462  // serialization of the input binary.
463  corpus_wptr				second_self_comparison_corpus_;
464  // This is also used for debugging purposes, when using
465  //   'abidw --debug-abidiff <binary>'.  It holds the set of mapping of
466  // an abixml (canonical) type and its type-id.
467  unordered_map<string, uintptr_t>	type_id_canonical_type_map_;
468  // Likewise.  It holds a map that associates the pointer to a type
469  // read from abixml and the type-id string it corresponds to.
470  unordered_map<uintptr_t, string>	pointer_type_id_map_;
471#endif
472  bool					canonicalization_is_done_;
473  bool					do_on_the_fly_canonicalization_;
474  bool					decl_only_class_equals_definition_;
475  bool					use_enum_binary_only_equality_;
476  bool					allow_type_comparison_results_caching_;
477  optional<bool>			analyze_exported_interfaces_only_;
478#ifdef WITH_DEBUG_SELF_COMPARISON
479  bool					self_comparison_debug_on_;
480#endif
481#ifdef WITH_DEBUG_TYPE_CANONICALIZATION
482  // This controls whether to use canonical type comparison during
483  // type comparison or not.  This is only used for debugging, when we
484  // want to ensure that comparing types using canonical or structural
485  // comparison yields the same result.
486  bool					use_canonical_type_comparison_;
487  // Whether we are debugging type canonicalization or not.  When
488  // debugging type canonicalization, a type is compared to its
489  // potential canonical type twice: The first time with canonical
490  // comparison activated, and the second time with structural
491  // comparison activated.  The two comparison should yield the same
492  // result, otherwise, canonicalization is "broken" for that
493  // particular type.
494  bool					debug_type_canonicalization_;
495  bool					debug_die_canonicalization_;
496#endif
497
498  priv()
499    : canonicalization_is_done_(),
500      do_on_the_fly_canonicalization_(true),
501      decl_only_class_equals_definition_(false),
502      use_enum_binary_only_equality_(true),
503      allow_type_comparison_results_caching_(false)
504#ifdef WITH_DEBUG_SELF_COMPARISON
505    ,
506      self_comparison_debug_on_(false)
507#endif
508#ifdef WITH_DEBUG_TYPE_CANONICALIZATION
509    ,
510      use_canonical_type_comparison_(true),
511      debug_type_canonicalization_(false),
512      debug_die_canonicalization_(false)
513#endif
514  {}
515
516  /// Allow caching of the sub-types comparison results during the
517  /// invocation of the @ref equal overloads for class and function
518  /// types.
519  ///
520  /// @param f if true, allow type comparison result caching.
521  void
522  allow_type_comparison_results_caching(bool f)
523  {allow_type_comparison_results_caching_ = f;}
524
525  /// Check whether if caching of the sub-types comparison results during the
526  /// invocation of the @ref equal overloads for class and function
527  /// types is in effect.
528  ///
529  /// @return true iff caching of the sub-types comparison results
530  /// during the invocation of the @ref equal overloads for class and
531  /// function types is in effect.
532  bool
533  allow_type_comparison_results_caching() const
534  {return allow_type_comparison_results_caching_;}
535
536  /// Cache the result of comparing two sub-types.
537  ///
538  /// @param first the first sub-type that has been compared. Its
539  /// address is going to be stored in the cache.
540  ///
541  /// @param second the second sub-type that has been compared. Its
542  /// address is going to be stored in the cache.
543  ///
544  /// @param r the result of comparing @p first and @p second.  This
545  /// is going to be stored in the cache, as well as the addresses of
546  /// @p first and @p second.
547  template<typename T>
548  void
549  cache_type_comparison_result(T& first, T& second, bool r)
550  {
551    if (allow_type_comparison_results_caching()
552	&& (r == false
553	    ||
554	    (!is_recursive_type(&first)
555	     && !is_recursive_type(&second)
556	     && !is_type(&first)->priv_->depends_on_recursive_type()
557	     && !is_type(&second)->priv_->depends_on_recursive_type())))
558      {
559	type_comparison_results_cache_.emplace
560	  (std::make_pair(reinterpret_cast<uint64_t>(&first),
561			  reinterpret_cast<uint64_t>(&second)),
562	   r);
563      }
564  }
565
566  /// Retrieve the result of comparing two sub-types from the cache,
567  /// if it was previously stored.
568  ///
569  /// @param first the first sub-type to consider.
570  ///
571  /// @param second the second sub-type to consider.  The pair of
572  /// addresses of {@p first, @p second} is going to be looked up in
573  /// the cache.  If it's present, then the associated result of the
574  /// comparison of @p first against @p second is present as well, and
575  /// is returned.
576  ///
577  /// @param r this is an out parameter which is set to the result of
578  /// the comparison of @p first against @p second if the pair of
579  /// addresses of {@p first, @p second} is present in the cache.
580  ///
581  /// @return true iff the pair of addresses of {@p first, @p second}
582  /// is present in the cache.  In that case, the associated result of
583  /// the comparison of @p first against @p second is returned in the
584  /// argument of @p r.
585  template<typename T>
586  bool
587  is_type_comparison_cached(T& first, T& second, bool& r)
588  {
589    if (!allow_type_comparison_results_caching())
590      return false;
591
592    type_comparison_result_type::const_iterator it =
593      type_comparison_results_cache_.find
594	 (std::make_pair(reinterpret_cast<uint64_t>(&first),
595			 reinterpret_cast<uint64_t>(&second)));
596    if (it == type_comparison_results_cache_.end())
597      return false;
598
599    r = it->second;
600    return true;
601  }
602
603  /// Clear the cache type comparison results.
604  void
605  clear_type_comparison_results_cache()
606  {type_comparison_results_cache_.clear();}
607
608  /// Dumps a textual representation (to the standard error output) of
609  /// the content of the set of classes being currently compared using
610  /// the @ref equal overloads.
611  ///
612  /// This function is for debugging purposes.
613  void
614  dump_classes_being_compared()
615  {
616    std::cerr << "classes being compared: " << classes_being_compared_.size()
617	      << "\n"
618	      << "=====================================\n";
619    for (auto& p : classes_being_compared_)
620      {
621	class_or_union* c = reinterpret_cast<class_or_union*>(p.first);
622	std::cerr << "'" << c->get_pretty_representation()
623		  << " / (" << std::hex << p.first << "," << p.second << ")"
624		  << "'\n";
625      }
626    std::cerr << "=====================================\n";
627  }
628
629  /// Dumps a textual representation (to the standard error output) of
630  /// the content of the set of classes being currently compared using
631  /// the @ref equal overloads.
632  ///
633  /// This function is for debugging purposes.
634  void
635  dump_fn_types_being_compared()
636  {
637    std::cerr << "fn_types being compared: " << fn_types_being_compared_.size()
638	      << "\n"
639	      << "=====================================\n";
640    for (auto& p : fn_types_being_compared_)
641      {
642	function_type* c = reinterpret_cast<function_type*>(p.first);
643	std::cerr << "'" << c->get_pretty_representation()
644		  << " / (" << std::hex << p.first << "," << p.second << ")"
645		  << "'\n";
646      }
647    std::cerr << "=====================================\n";
648  }
649
650  /// Push a pair of operands on the stack of operands of the current
651  /// type comparison, during type canonicalization.
652  ///
653  /// For more information on this, please look at the description of
654  /// the right_type_comp_operands_ data member.
655  ///
656  /// @param left the left-hand-side comparison operand to push.
657  ///
658  /// @param right the right-hand-side comparison operand to push.
659  void
660  push_composite_type_comparison_operands(const type_base* left,
661					  const type_base* right)
662  {
663    ABG_ASSERT(left && right);
664
665    left_type_comp_operands_.push_back(left);
666    right_type_comp_operands_.push_back(right);
667  }
668
669  /// Pop a pair of operands from the stack of operands to the current
670  /// type comparison.
671  ///
672  /// For more information on this, please look at the description of
673  /// the right_type_comp_operands_ data member.
674  ///
675  /// @param left the left-hand-side comparison operand we expect to
676  /// pop from the top of the stack.  If this doesn't match the
677  /// operand found on the top of the stack, the function aborts.
678  ///
679  /// @param right the right-hand-side comparison operand we expect to
680  /// pop from the bottom of the stack. If this doesn't match the
681  /// operand found on the top of the stack, the function aborts.
682  void
683  pop_composite_type_comparison_operands(const type_base* left,
684					 const type_base* right)
685  {
686    const type_base *t = left_type_comp_operands_.back();
687    ABG_ASSERT(t == left);
688    t = right_type_comp_operands_.back();
689    ABG_ASSERT(t == right);
690
691    left_type_comp_operands_.pop_back();
692    right_type_comp_operands_.pop_back();
693  }
694
695  /// Mark all the types that comes after a certain one as NOT being
696  /// eligible for the canonical type propagation optimization.
697  ///
698  /// @param type the type that represents the "marker type".  All
699  /// types after this one will be marked as being NON-eligible to
700  /// the canonical type propagation optimization.
701  ///
702  /// @param types the set of types to consider.  In that vector, all
703  /// types that come after @p type are going to be marked as being
704  /// non-eligible to the canonical type propagation optimization.
705  ///
706  /// @return true iff the operation was successful.
707  bool
708  mark_dependant_types(const type_base* type,
709		       vector<const type_base*>& types)
710  {
711    bool found = false;
712    for (auto t : types)
713      {
714	if (!found
715	    && (reinterpret_cast<uintptr_t>(t)
716		== reinterpret_cast<uintptr_t>(type)))
717	  {
718	    found = true;
719	    continue;
720	  }
721	else if (found)
722	  t->priv_->set_depends_on_recursive_type(type);
723      }
724    return found;
725  }
726
727  /// In the stack of the current types being compared (as part of
728  /// type canonicalization), mark all the types that comes after a
729  /// certain one as NOT being eligible to the canonical type
730  /// propagation optimization.
731  ///
732  /// For a starter, please read about the @ref
733  /// OnTheFlyCanonicalization, aka, "canonical type propagation
734  /// optimization".
735  ///
736  /// To implement that optimization, we need, among other things to
737  /// maintain stack of the types (and their sub-types) being
738  /// currently compared as part of type canonicalization.
739  ///
740  /// Note that we only consider the type that is the right-hand-side
741  /// operand of the comparison because it's that one that is being
742  /// canonicalized and thus, that is not yet canonicalized.
743  ///
744  /// The reason why a type is deemed NON-eligible to the canonical
745  /// type propagation optimization is that it "depends" on
746  /// recursively present type.  Let me explain.
747  ///
748  /// Suppose we have a type T that has sub-types named ST0 and ST1.
749  /// Suppose ST1 itself has a sub-type that is T itself.  In this
750  /// case, we say that T is a recursive type, because it has T
751  /// (itself) as one of its sub-types:
752  ///
753  ///   T
754  ///   +-- ST0
755  ///   |
756  ///   +-- ST1
757  ///        +
758  ///        |
759  ///        +-- T
760  ///
761  /// ST1 is said to "depend" on T because it has T as a sub-type.
762  /// But because T is recursive, then ST1 is said to depend on a
763  /// recursive type.  Notice however that ST0 does not depend on any
764  /// recursive type.
765  ///
766  /// When we are at the point of comparing the sub-type T of ST1
767  /// against its counterpart, the stack of the right-hand-side
768  /// operands of the type canonicalization is going to look like
769  /// this:
770  ///
771  ///    | T | ST1 |
772  ///
773  /// We don't add the type T to the stack as we detect that T was
774  /// already in there (recursive cycle).
775  ///
776  /// So, this function will basically mark ST1 as being NON-eligible
777  /// to being the target of canonical type propagation.
778  ///
779  /// @param right the right-hand-side operand of the type comparison.
780  ///
781  /// @return true iff the operation was successful.
782  bool
783  mark_dependant_types_compared_until(const type_base* right)
784  {
785    bool result = false;
786
787    result |=
788      mark_dependant_types(right,
789			   right_type_comp_operands_);
790    recursive_types_.insert(reinterpret_cast<uintptr_t>(right));
791    return result;
792  }
793
794  /// Test if a type is a recursive one.
795  ///
796  /// @param t the type to consider.
797  ///
798  /// @return true iff @p t is recursive.
799  bool
800  is_recursive_type(const type_base* t)
801  {
802    return (recursive_types_.find(reinterpret_cast<uintptr_t>(t))
803	    != recursive_types_.end());
804  }
805
806
807  /// Unflag a type as being recursive
808  ///
809  /// @param t the type to unflag
810  void
811  set_is_not_recursive(const type_base* t)
812  {recursive_types_.erase(reinterpret_cast<uintptr_t>(t));}
813
814  /// Propagate the canonical type of a type to another one.
815  ///
816  /// @param src the type to propagate the canonical type from.
817  ///
818  /// @param dest the type to propagate the canonical type of @p src
819  /// to.
820  ///
821  /// @return bool iff the canonical was propagated.
822  bool
823  propagate_ct(const type_base& src, const type_base& dest)
824  {
825    type_base_sptr canonical = src.get_canonical_type();
826    ABG_ASSERT(canonical);
827    dest.priv_->canonical_type = canonical;
828    dest.priv_->naked_canonical_type = canonical.get();
829    dest.priv_->set_canonical_type_propagated(true);
830    return true;
831  }
832
833  /// Mark a set of types that have been the target of canonical type
834  /// propagation and that depend on a recursive type as being
835  /// permanently canonicalized.
836  ///
837  /// To understand the sentence above, please read the description of
838  /// type canonicalization and especially about the "canonical type
839  /// propagation optimization" at @ref OnTheFlyCanonicalization, in
840  /// the src/abg-ir.cc file.
841  void
842  confirm_ct_propagation_for_types_dependant_on(const type_base* dependant_type)
843  {
844    pointer_set to_remove;
845    for (auto i : types_with_non_confirmed_propagated_ct_)
846      {
847	type_base *t = reinterpret_cast<type_base*>(i);
848	ABG_ASSERT(t->get_environment().priv_->is_recursive_type(t)
849		   || t->priv_->depends_on_recursive_type());
850	t->priv_->set_does_not_depend_on_recursive_type(dependant_type);
851	if (!t->priv_->depends_on_recursive_type())
852	  {
853	    to_remove.insert(i);
854	    t->priv_->set_propagated_canonical_type_confirmed(true);
855	  }
856      }
857
858    for (auto i : to_remove)
859      types_with_non_confirmed_propagated_ct_.erase(i);
860  }
861
862  /// Mark a type that has been the target of canonical type
863  /// propagation as being permanently canonicalized.
864  ///
865  /// This function also marks the set of types that have been the
866  /// target of canonical type propagation and that depend on a
867  /// recursive type as being permanently canonicalized.
868  ///
869  /// To understand the sentence above, please read the description of
870  /// type canonicalization and especially about the "canonical type
871  /// propagation optimization" at @ref OnTheFlyCanonicalization, in
872  /// the src/abg-ir.cc file.
873  void
874  confirm_ct_propagation(const type_base*t)
875  {
876    if (!t || t->priv_->propagated_canonical_type_confirmed())
877      return;
878
879    const environment& env = t->get_environment();
880
881    env.priv_->confirm_ct_propagation_for_types_dependant_on(t);
882    t->priv_->set_does_not_depend_on_recursive_type();
883    env.priv_->remove_from_types_with_non_confirmed_propagated_ct(t);
884    env.priv_->set_is_not_recursive(t);
885    t->priv_->set_propagated_canonical_type_confirmed(true);
886  }
887
888  /// Mark all the types that have been the target of canonical type
889  /// propagation and that are not yet confirmed as being permanently
890  /// canonicalized (aka confirmed).
891  ///
892  /// To understand the sentence above, please read the description of
893  /// type canonicalization and especially about the "canonical type
894  /// propagation optimization" at @ref OnTheFlyCanonicalization, in
895  /// the src/abg-ir.cc file.
896  void
897  confirm_ct_propagation()
898  {
899    for (auto i : types_with_non_confirmed_propagated_ct_)
900      {
901	type_base *t = reinterpret_cast<type_base*>(i);
902	ABG_ASSERT(t->get_environment().priv_->is_recursive_type(t)
903		   || t->priv_->depends_on_recursive_type());
904	t->priv_->set_does_not_depend_on_recursive_type();
905	t->priv_->set_propagated_canonical_type_confirmed(true);
906      }
907    types_with_non_confirmed_propagated_ct_.clear();
908  }
909
910  /// Collect the types that depends on a given "target" type.
911  ///
912  /// Walk a set of types and if they depend directly or indirectly on
913  /// a "target" type, then collect them into a set.
914  ///
915  /// @param target the target type to consider.
916  ///
917  /// @param types the types to walk to detect those who depend on @p
918  /// target.
919  ///
920  /// @return true iff one or more type from @p types is found to
921  /// depend on @p target.
922  bool
923  collect_types_that_depends_on(const type_base *target,
924				const pointer_set& types,
925				pointer_set& collected)
926  {
927    bool result = false;
928    for (const auto i : types)
929      {
930	// First avoid infinite loop if we've already collected the
931	// current type.
932	if (collected.find(i) != collected.end())
933	  continue;
934
935	type_base *t = reinterpret_cast<type_base*>(i);
936	if (t->priv_->depends_on_recursive_type(target))
937	  {
938	    collected.insert(i);
939	    collect_types_that_depends_on(t, types, collected);
940	    result = true;
941	  }
942      }
943    return result;
944  }
945
946  /// Reset the canonical type (set it nullptr) of a set of types that
947  /// have been the target of canonical type propagation and that
948  /// depend on a given recursive type.
949  ///
950  /// Once the canonical type of a type in that set is reset, the type
951  /// is marked as being non-dependant on a recursive type anymore.
952  ///
953  /// To understand the sentences above, please read the description
954  /// of type canonicalization and especially about the "canonical
955  /// type propagation optimization" at @ref OnTheFlyCanonicalization,
956  /// in the src/abg-ir.cc file.
957  ///
958  /// @param target if a type which has been subject to the canonical
959  /// type propagation optimizationdepends on a this target type, then
960  /// cancel its canonical type.
961  void
962  cancel_ct_propagation_for_types_dependant_on(const type_base* target)
963  {
964    pointer_set to_remove;
965    collect_types_that_depends_on(target,
966				  types_with_non_confirmed_propagated_ct_,
967				  to_remove);
968
969    for (auto i : to_remove)
970      {
971	type_base *t = reinterpret_cast<type_base*>(i);
972	ABG_ASSERT(t->get_environment().priv_->is_recursive_type(t)
973		   || t->priv_->depends_on_recursive_type());
974	type_base_sptr canonical = t->priv_->canonical_type.lock();
975	if (canonical)
976	  {
977	    t->priv_->clear_propagated_canonical_type();
978	    t->priv_->set_does_not_depend_on_recursive_type();
979	  }
980      }
981
982    for (auto i : to_remove)
983      types_with_non_confirmed_propagated_ct_.erase(i);
984  }
985
986  /// Reset the canonical type (set it nullptr) of a type that has
987  /// been the target of canonical type propagation.
988  ///
989  /// This also resets the propagated canonical type of the set of
990  /// types that depends on a given recursive type.
991  ///
992  /// Once the canonical type of a type in that set is reset, the type
993  /// is marked as being non-dependant on a recursive type anymore.
994  ///
995  /// To understand the sentences above, please read the description
996  /// of type canonicalization and especially about the "canonical
997  /// type propagation optimization" at @ref OnTheFlyCanonicalization,
998  /// in the src/abg-ir.cc file.
999  ///
1000  /// @param target if a type which has been subject to the canonical
1001  /// type propagation optimizationdepends on a this target type, then
1002  /// cancel its canonical type.
1003  void
1004  cancel_ct_propagation(const type_base* t)
1005  {
1006    if (!t)
1007      return;
1008
1009    const environment& env = t->get_environment();
1010    env.priv_->cancel_ct_propagation_for_types_dependant_on(t);
1011    if (t->priv_->depends_on_recursive_type()
1012	|| env.priv_->is_recursive_type(t))
1013      {
1014	// This cannot carry any tentative canonical type at this
1015	// point.
1016	if (t->priv_->canonical_type_propagated()
1017	    && !t->priv_->propagated_canonical_type_confirmed())
1018	  t->priv_->clear_propagated_canonical_type();
1019	// Reset the marking of the type as it no longer carries a
1020	// tentative canonical type that might be later cancelled.
1021	t->priv_->set_does_not_depend_on_recursive_type();
1022	env.priv_->remove_from_types_with_non_confirmed_propagated_ct(t);
1023      }
1024  }
1025
1026  /// Add a given type to the set of types that have been
1027  /// non-confirmed subjects of the canonical type propagation
1028  /// optimization.
1029  ///
1030  /// @param t the dependant type to consider.
1031  void
1032  add_to_types_with_non_confirmed_propagated_ct(const type_base *t)
1033  {
1034    uintptr_t v = reinterpret_cast<uintptr_t>(t);
1035    types_with_non_confirmed_propagated_ct_.insert(v);
1036  }
1037
1038  /// Remove a given type from the set of types that have been
1039  /// non-confirmed subjects of the canonical type propagation
1040  /// optimization.
1041  ///
1042  /// @param dependant the dependant type to consider.
1043  void
1044  remove_from_types_with_non_confirmed_propagated_ct(const type_base* dependant)
1045  {
1046    uintptr_t i = reinterpret_cast<uintptr_t>(dependant);
1047    types_with_non_confirmed_propagated_ct_.erase(i);
1048  }
1049
1050#ifdef WITH_DEBUG_SELF_COMPARISON
1051  /// When debugging self comparison, verify that a type T
1052  /// de-serialized from abixml has the same canonical type as the
1053  /// initial type built from DWARF that was serialized into T in the
1054  /// first place.
1055  ///
1056  /// @param t deserialized type (from abixml) to consider.
1057  ///
1058  /// @param c the canonical type @p t should have.
1059  ///
1060  /// @return true iff @p c is the canonical type that @p t should
1061  /// have.
1062  bool
1063  check_canonical_type_from_abixml_during_self_comp(const type_base* t,
1064						    const type_base* c)
1065  {
1066    if (!t || !t->get_corpus() || !c)
1067      return false;
1068
1069    if (!(t->get_corpus()->get_origin() == ir::corpus::NATIVE_XML_ORIGIN))
1070      return false;
1071
1072    // Get the abixml type-id that this type was constructed from.
1073    string type_id;
1074    {
1075      unordered_map<uintptr_t, string>::const_iterator it =
1076	pointer_type_id_map_.find(reinterpret_cast<uintptr_t>(t));
1077      if (it == pointer_type_id_map_.end())
1078	// This type didn't have a type-id in the abixml file.  Maybe
1079	// it's a function or method type.  So let's just keep going.
1080	return true;
1081      type_id = it->second;
1082    }
1083
1084    // Get the canonical type the original in-memory type (constructed
1085    // from DWARF) had when it was serialized into abixml in the first place.
1086    type_base *original_canonical_type = nullptr;
1087    if (!type_id.empty())
1088      {
1089	unordered_map<string, uintptr_t>::const_iterator it =
1090	  type_id_canonical_type_map_.find(type_id);
1091	if (it == type_id_canonical_type_map_.end())
1092	  return false;
1093	original_canonical_type = reinterpret_cast<type_base*>(it->second);
1094      }
1095
1096    // Now perform the real check.
1097    //
1098    // We want to ensure that the canonical type 'c' of 't' is the
1099    // same as the canonical type of initial in-memory type (built
1100    // from DWARF) that was serialized into 't' (in abixml) in the
1101    // first place.
1102    if (original_canonical_type == c)
1103      return true;
1104
1105    return false;
1106  }
1107
1108  /// When debugging self comparison, verify that a type T
1109  /// de-serialized from abixml has the same canonical type as the
1110  /// initial type built from DWARF that was serialized into T in the
1111  /// first place.
1112  ///
1113  /// @param t deserialized type (from abixml) to consider.
1114  ///
1115  /// @param c the canonical type @p t should have.
1116  ///
1117  /// @return true iff @p c is the canonical type that @p t should
1118  /// have.
1119  bool
1120  check_canonical_type_from_abixml_during_self_comp(const type_base_sptr& t,
1121						    const type_base_sptr& c)
1122  {
1123    return check_canonical_type_from_abixml_during_self_comp(t.get(), c.get());
1124  }
1125#endif
1126};// end struct environment::priv
1127
1128// <class_or_union::priv definitions>
1129struct class_or_union::priv
1130{
1131  typedef_decl_wptr		naming_typedef_;
1132  data_members			data_members_;
1133  data_members			non_static_data_members_;
1134  member_functions		member_functions_;
1135  // A map that associates a linkage name to a member function.
1136  string_mem_fn_sptr_map_type	mem_fns_map_;
1137  // A map that associates function signature strings to member
1138  // function.
1139  string_mem_fn_ptr_map_type	signature_2_mem_fn_map_;
1140  member_function_templates	member_function_templates_;
1141  member_class_templates	member_class_templates_;
1142
1143  priv()
1144  {}
1145
1146  priv(class_or_union::data_members& data_mbrs,
1147       class_or_union::member_functions& mbr_fns)
1148    : data_members_(data_mbrs),
1149      member_functions_(mbr_fns)
1150  {
1151    for (data_members::const_iterator i = data_members_.begin();
1152	 i != data_members_.end();
1153	 ++i)
1154      if (!get_member_is_static(*i))
1155	non_static_data_members_.push_back(*i);
1156  }
1157
1158  /// Mark a pair of classes or unions as being currently compared
1159  /// using the class_or_union== operator.
1160  ///
1161  /// Note that this marking business is to avoid infinite loop when
1162  /// comparing a pair of classes or unions. If via the comparison of
1163  /// a data member or a member function a recursive re-comparison of
1164  /// the class or union is attempted, the marking process helps to
1165  /// detect that infinite loop possibility and avoid it.
1166  ///
1167  /// @param first the class or union (of the pair) to mark as being
1168  /// currently compared.
1169  ///
1170  /// @param second the second class or union (of the pair) to mark as
1171  /// being currently compared.
1172  void
1173  mark_as_being_compared(const class_or_union& first,
1174			 const class_or_union& second) const
1175  {
1176    const environment& env = first.get_environment();
1177    env.priv_->classes_being_compared_.insert
1178      (std::make_pair(reinterpret_cast<uint64_t>(&first),
1179		      reinterpret_cast<uint64_t>(&second)));
1180  }
1181
1182  /// Mark a pair of classes or unions as being currently compared
1183  /// using the class_or_union== operator.
1184  ///
1185  /// Note that this marking business is to avoid infinite loop when
1186  /// comparing a pair of classes or unions. If via the comparison of
1187  /// a data member or a member function a recursive re-comparison of
1188  /// the class or union is attempted, the marking process helps to
1189  /// detect that infinite loop possibility and avoid it.
1190  ///
1191  /// @param first the class or union (of the pair) to mark as being
1192  /// currently compared.
1193  ///
1194  /// @param second the second class or union (of the pair) to mark as
1195  /// being currently compared.
1196  void
1197  mark_as_being_compared(const class_or_union* first,
1198			 const class_or_union* second) const
1199  {mark_as_being_compared(*first, *second);}
1200
1201  /// Mark a pair of classes or unions as being currently compared
1202  /// using the class_or_union== operator.
1203  ///
1204  /// Note that this marking business is to avoid infinite loop when
1205  /// comparing a pair of classes or unions. If via the comparison of
1206  /// a data member or a member function a recursive re-comparison of
1207  /// the class or union is attempted, the marking process helps to
1208  /// detect that infinite loop possibility and avoid it.
1209  ///
1210  /// @param first the class or union (of the pair) to mark as being
1211  /// currently compared.
1212  ///
1213  /// @param second the second class or union (of the pair) to mark as
1214  /// being currently compared.
1215  void
1216  mark_as_being_compared(const class_or_union_sptr& first,
1217			 const class_or_union_sptr& second) const
1218  {mark_as_being_compared(*first, *second);}
1219
1220  /// If a pair of class_or_union has been previously marked as
1221  /// being compared -- via an invocation of mark_as_being_compared()
1222  /// this method unmarks it.  Otherwise is has no effect.
1223  ///
1224  /// This method is not thread safe because it uses the static data
1225  /// member classes_being_compared_.  If you wish to use it in a
1226  /// multi-threaded environment you should probably protect the
1227  /// access to that static data member with a mutex or somesuch.
1228  ///
1229  /// @param first the first instance of class_or_union (of the pair)
1230  /// to unmark.
1231  ///
1232  /// @param second the second instance of class_or_union (of the
1233  /// pair) to unmark.
1234  void
1235  unmark_as_being_compared(const class_or_union& first,
1236			   const class_or_union& second) const
1237  {
1238    const environment& env = first.get_environment();
1239    env.priv_->classes_being_compared_.erase
1240      (std::make_pair(reinterpret_cast<uint64_t>(&first),
1241		      reinterpret_cast<uint64_t>(&second)));
1242  }
1243
1244  /// If a pair of class_or_union has been previously marked as
1245  /// being compared -- via an invocation of mark_as_being_compared()
1246  /// this method unmarks it.  Otherwise is has no effect.
1247  ///
1248  /// This method is not thread safe because it uses the static data
1249  /// member classes_being_compared_.  If you wish to use it in a
1250  /// multi-threaded environment you should probably protect the
1251  /// access to that static data member with a mutex or somesuch.
1252  ///
1253  /// @param first the first instance of class_or_union (of the pair)
1254  /// to unmark.
1255  ///
1256  /// @param second the second instance of class_or_union (of the
1257  /// pair) to unmark.
1258  void
1259  unmark_as_being_compared(const class_or_union* first,
1260			   const class_or_union* second) const
1261  {
1262    if (!first || !second)
1263      return;
1264    unmark_as_being_compared(*first, *second);
1265  }
1266
1267  /// Test if a pair of class_or_union is being currently compared.
1268  ///
1269  ///@param first the first class or union (of the pair) to test for.
1270  ///
1271  ///@param second the second class or union (of the pair) to test for.
1272  ///
1273  /// @return true if the pair {@p first, @p second} is being
1274  /// compared, false otherwise.
1275  bool
1276  comparison_started(const class_or_union& first,
1277		     const class_or_union& second) const
1278  {
1279    const environment& env = first.get_environment();
1280    return env.priv_->
1281      classes_being_compared_.count
1282      (std::make_pair(reinterpret_cast<uint64_t>(&first),
1283		      reinterpret_cast<uint64_t>((&second))));
1284  }
1285
1286  /// Test if a pair of class_or_union is being currently compared.
1287  ///
1288  ///@param first the first class or union (of the pair) to test for.
1289  ///
1290  ///@param second the second class or union (of the pair) to test for.
1291  ///
1292  /// @return true if the pair {@p first, @p second} is being
1293  /// compared, false otherwise.
1294  bool
1295  comparison_started(const class_or_union* first,
1296		     const class_or_union* second) const
1297  {
1298    if (first && second)
1299      return comparison_started(*first, *second);
1300    return false;
1301  }
1302}; // end struct class_or_union::priv
1303
1304// <function_type::priv definitions>
1305
1306/// The type of the private data of the @ref function_type type.
1307struct function_type::priv
1308{
1309  parameters parms_;
1310  type_base_wptr return_type_;
1311  interned_string cached_name_;
1312  interned_string internal_cached_name_;
1313  interned_string temp_internal_cached_name_;
1314
1315  priv()
1316  {}
1317
1318  priv(const parameters&	parms,
1319       type_base_sptr		return_type)
1320    : parms_(parms),
1321      return_type_(return_type)
1322  {}
1323
1324  priv(type_base_sptr return_type)
1325    : return_type_(return_type)
1326  {}
1327
1328  /// Mark a given pair of @ref function_type as being compared.
1329  ///
1330  /// @param first the first @ref function_type of the pair being
1331  /// compared, to mark.
1332  ///
1333  /// @param second the second @ref function_type of the pair being
1334  /// compared, to mark.
1335  void
1336  mark_as_being_compared(const function_type& first,
1337			 const function_type& second) const
1338  {
1339    const environment& env = first.get_environment();
1340    env.priv_->fn_types_being_compared_.insert
1341      (std::make_pair(reinterpret_cast<uint64_t>(&first),
1342		      reinterpret_cast<uint64_t>(&second)));
1343  }
1344
1345  /// Mark a given pair of @ref function_type as being compared.
1346  ///
1347  /// @param first the first @ref function_type of the pair being
1348  /// compared, to mark.
1349  ///
1350  /// @param second the second @ref function_type of the pair being
1351  /// compared, to mark.
1352  void
1353  unmark_as_being_compared(const function_type& first,
1354			   const function_type& second) const
1355  {
1356    const environment& env = first.get_environment();
1357    env.priv_->fn_types_being_compared_.erase
1358      (std::make_pair(reinterpret_cast<uint64_t>(&first),
1359		      reinterpret_cast<uint64_t>(&second)));
1360  }
1361
1362  /// Tests if a @ref function_type is currently being compared.
1363  ///
1364  /// @param type the function type to take into account.
1365  ///
1366  /// @return true if @p type is being compared.
1367  bool
1368  comparison_started(const function_type& first,
1369		     const function_type& second) const
1370  {
1371    const environment& env = first.get_environment();
1372    return env.priv_->fn_types_being_compared_.count
1373      (std::make_pair(reinterpret_cast<uint64_t>(&first),
1374		      reinterpret_cast<uint64_t>(&second)));
1375  }
1376};// end struc function_type::priv
1377
1378// </function_type::priv definitions>
1379
1380} // end namespace ir
1381
1382} // end namespace abigail
1383
1384#endif // __ABG_IR_PRIV_H__
1385