• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
29 using abg_compat::optional;
30 
31 /// The result of structural comparison of type ABI artifacts.
32 enum 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.
45 class integral_type
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.
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 
94 private:
95   base_type	base_;
96   modifiers_type modifiers_;
97 
98 public:
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 
122 integral_type::modifiers_type
123 operator|(integral_type::modifiers_type l, integral_type::modifiers_type r);
124 
125 integral_type::modifiers_type
126 operator&(integral_type::modifiers_type l, integral_type::modifiers_type r);
127 
128 integral_type::modifiers_type
129 operator~(integral_type::modifiers_type l);
130 
131 integral_type::modifiers_type&
132 operator|=(integral_type::modifiers_type& l, integral_type::modifiers_type r);
133 
134 integral_type::modifiers_type&
135 operator &=(integral_type::modifiers_type& l, integral_type::modifiers_type r);
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
142 struct 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 
privpriv159   priv(const environment& env)
160     : env_(env),
161       corp(),
162       is_constructed_(),
163       address_size_(),
164       language_(LANG_UNKNOWN)
165   {}
166 
~privpriv167   ~priv()
168   {}
169 
170   type_maps&
get_typespriv171   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.
178 struct 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 
privpriv205   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())
size_in_bitspriv216     : 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
depends_on_recursive_typepriv234   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
depends_on_recursive_typepriv251   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
set_depends_on_recursive_typepriv269   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
set_does_not_depend_on_recursive_typepriv284   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
set_does_not_depend_on_recursive_typepriv289   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
canonical_type_propagatedpriv299   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
set_canonical_type_propagatedpriv309   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
propagated_canonical_type_confirmedpriv322   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
set_propagated_canonical_type_confirmedpriv335   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   bool
clear_propagated_canonical_typepriv341   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 	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.
357 struct uint64_t_pair_hash
358 {
359   /// Hashing function for a pair of uint64_t.
360   ///
361   /// @param p the pair to hash.
362   uint64_t
operatoruint64_t_pair_hash363   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,
373 		      uint64_t_pair_hash> uint64_t_pairs_set_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,
385 		      uint64_t_pair_hash> type_comparison_result_type;
386 
387 /// The private data of the @ref environment type.
388 struct environment::priv
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 
privpriv519   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
allow_type_comparison_results_cachingpriv544   allow_type_comparison_results_caching(bool f)
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
allow_type_comparison_results_cachingpriv555   allow_type_comparison_results_caching() const
556   {return allow_type_comparison_results_caching_;}
557 
558   void
do_logpriv559   do_log(bool f)
560   {do_log_ = f;}
561 
562   bool
do_logpriv563   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
cache_type_comparison_resultpriv579   cache_type_comparison_result(T& first, T& second, bool r)
580   {
581     if (allow_type_comparison_results_caching()
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
is_type_comparison_cachedpriv617   is_type_comparison_cached(T& first, T& second, bool& r)
618   {
619     if (!allow_type_comparison_results_caching())
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
clear_type_comparison_results_cachepriv635   clear_type_comparison_results_cache()
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
push_composite_type_comparison_operandspriv648   push_composite_type_comparison_operands(const type_base* left,
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
pop_composite_type_comparison_operandspriv671   pop_composite_type_comparison_operands(const type_base* left,
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
mark_dependant_typespriv696   mark_dependant_types(const type_base* type,
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
mark_dependant_types_compared_untilpriv771   mark_dependant_types_compared_until(const type_base* right)
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
is_recursive_typepriv788   is_recursive_type(const type_base* t)
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
set_is_not_recursivepriv799   set_is_not_recursive(const type_base* t)
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
propagate_ctpriv811   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
confirm_ct_propagation_for_types_dependant_onpriv835   confirm_ct_propagation_for_types_dependant_on(const type_base* dependant_type)
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);
845 	    t->priv_->set_propagated_canonical_type_confirmed(true);
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
confirm_ct_propagationpriv868   confirm_ct_propagation(const type_base*t)
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);
876     t->priv_->set_does_not_depend_on_recursive_type();
877     env.priv_->remove_from_types_with_non_confirmed_propagated_ct(t);
878     env.priv_->set_is_not_recursive(t);
879     t->priv_->set_propagated_canonical_type_confirmed(true);
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
confirm_ct_propagationpriv894   confirm_ct_propagation()
895   {
896     for (auto i : types_with_non_confirmed_propagated_ct_)
897       {
898 	type_base *t = reinterpret_cast<type_base*>(i);
899 	t->priv_->set_does_not_depend_on_recursive_type();
900 	t->priv_->set_propagated_canonical_type_confirmed(true);
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&
types_with_cleared_propagated_ctpriv918   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&
types_with_cleared_propagated_ctpriv930   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
record_type_with_cleared_propagated_canonical_typepriv938   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
erase_type_with_cleared_propagated_canonical_typepriv951   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
collect_types_that_depends_onpriv971   collect_types_that_depends_on(const type_base *target,
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
cancel_ct_propagation_for_types_dependant_onpriv1010   cancel_ct_propagation_for_types_dependant_on(const type_base* target)
1011   {
1012     pointer_set to_remove;
1013     collect_types_that_depends_on(target,
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 	  {
1025 	    clear_propagated_canonical_type(t);
1026 	    t->priv_->set_does_not_depend_on_recursive_type();
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
cancel_ct_propagationpriv1052   cancel_ct_propagation(const type_base* t)
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.
1061     clear_propagated_canonical_type(t);
1062     // Reset the marking of the type as it no longer carries a
1063     // tentative canonical type that might be later canceled.
1064     t->priv_->set_does_not_depend_on_recursive_type();
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
clear_propagated_canonical_typepriv1080   clear_propagated_canonical_type(const type_base *t)
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
add_to_types_with_non_confirmed_propagated_ctpriv1099   add_to_types_with_non_confirmed_propagated_ct(const type_base *t)
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
remove_from_types_with_non_confirmed_propagated_ctpriv1111   remove_from_types_with_non_confirmed_propagated_ct(const type_base* dependant)
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
cancel_all_non_confirmed_propagated_canonical_typespriv1120   cancel_all_non_confirmed_propagated_canonical_types()
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);
1129 	cancel_ct_propagation(t);
1130       }
1131   }
1132 
1133 #ifdef WITH_DEBUG_SELF_COMPARISON
1134 
1135   const unordered_map<string, uintptr_t>&
get_type_id_canonical_type_mappriv1136   get_type_id_canonical_type_map() const
1137   {return type_id_canonical_type_map_;}
1138 
1139   unordered_map<string, uintptr_t>&
get_type_id_canonical_type_mappriv1140   get_type_id_canonical_type_map()
1141   {return type_id_canonical_type_map_;}
1142 
1143   const unordered_map<uintptr_t, string>&
get_pointer_type_id_mappriv1144   get_pointer_type_id_map() const
1145   {return pointer_type_id_map_;}
1146 
1147   unordered_map<uintptr_t, string>&
get_pointer_type_id_mappriv1148   get_pointer_type_id_map()
1149   {return pointer_type_id_map_;}
1150 
1151   string
get_type_id_from_pointerpriv1152   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
get_type_id_from_typepriv1161   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
get_canonical_type_from_type_idpriv1165   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
check_canonical_type_from_abixml_during_self_comppriv1188   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
check_abixml_canonical_type_propagation_during_self_comppriv1243   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
check_canonical_type_from_abixml_during_self_comppriv1284   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
canonicalize_types(const input_iterator & begin,const input_iterator & end,deref_lambda deref)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>
1358 struct class_or_union::priv
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 
privpriv1372   priv()
1373   {}
1374 
privpriv1375   priv(class_or_union::data_members& data_mbrs,
1376        class_or_union::member_functions& mbr_fns)
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
mark_as_being_comparedpriv1402   mark_as_being_compared(const class_or_union& first,
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
mark_as_being_comparedpriv1426   mark_as_being_compared(const class_or_union* first,
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
mark_as_being_comparedpriv1445   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
unmark_as_being_comparedpriv1464   unmark_as_being_compared(const class_or_union& first,
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
unmark_as_being_comparedpriv1488   unmark_as_being_compared(const class_or_union* first,
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
comparison_startedpriv1505   comparison_started(const class_or_union& first,
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
comparison_startedpriv1525   comparison_started(const class_or_union* first,
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.
1537 struct function_type::priv
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 
privpriv1545   priv()
1546   {}
1547 
privpriv1548   priv(const parameters&	parms,
1549        type_base_sptr		return_type)
1550     : parms_(parms),
1551       return_type_(return_type)
1552   {}
1553 
privpriv1554   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
mark_as_being_comparedpriv1566   mark_as_being_compared(const function_type& first,
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
unmark_as_being_comparedpriv1583   unmark_as_being_compared(const function_type& first,
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
comparison_startedpriv1598   comparison_started(const function_type& first,
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__
1616