• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2016-2020 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 
18 #include "abg-ir.h"
19 #include "abg-corpus.h"
20 
21 namespace abigail
22 {
23 
24 namespace ir
25 {
26 
27 using std::string;
28 
29 /// The internal representation of an integral type.
30 ///
31 /// This is a "utility type" used internally to canonicalize the name
32 /// of fundamental integral types, so that "unsignd long" and "long
33 /// unsined int" end-up having the same name.
34 class integral_type
35 {
36 public:
37   /// The possible base types of integral types.  We might have
38   /// forgotten many of these, so do not hesitate to add new ones.
39   ///
40   /// If you do add new ones, please also consider updating functions
41   /// parse_base_integral_type and integral_type::to_string.
42   enum base_type
43   {
44     /// The "int" base type.
45     INT_BASE_TYPE,
46     /// The "char" base type.
47     CHAR_BASE_TYPE,
48     /// The "bool" base type in C++ or "_Bool" in C11.
49     BOOL_BASE_TYPE,
50     /// The "double" base type.
51     DOUBLE_BASE_TYPE,
52     /// The "float" base type.
53     FLOAT_BASE_TYPE,
54     /// The "char16_t base type.
55     CHAR16_T_BASE_TYPE,
56     /// The "char32_t" base type.
57     CHAR32_T_BASE_TYPE,
58     /// The "wchar_t" base type.
59     WCHAR_T_BASE_TYPE
60   };
61 
62   /// The modifiers of the base types above.  Several modifiers can be
63   /// combined for a given base type.  The presence of modifiers is
64   /// usually modelled by a bitmap of modifiers.
65   ///
66   /// If you add a new modifier, please consider updating functions
67   /// parse_integral_type_modifier and integral_type::to_string.
68   enum modifiers_type
69   {
70     NO_MODIFIER = 0,
71     /// The "signed" modifier.
72     SIGNED_MODIFIER = 1,
73     /// The "unsigned" modier.
74     UNSIGNED_MODIFIER = 1 << 1,
75     /// The "short" modifier.
76     SHORT_MODIFIER = 1 << 2,
77     /// The "long" modifier.
78     LONG_MODIFIER = 1 << 3,
79     /// The "long long" modifier.
80     LONG_LONG_MODIFIER = 1 << 4
81   };
82 
83 private:
84   base_type	base_;
85   modifiers_type modifiers_;
86 
87 public:
88 
89   integral_type();
90   integral_type(const string& name);
91   integral_type(base_type, modifiers_type);
92 
93   base_type
94   get_base_type() const;
95 
96   modifiers_type
97   get_modifiers() const;
98 
99   bool
100   operator==(const integral_type&) const;
101 
102   string
103   to_string() const;
104 
105   operator string() const;
106 }; // end class integral_type
107 
108 integral_type::modifiers_type
109 operator|(integral_type::modifiers_type l, integral_type::modifiers_type r);
110 
111 integral_type::modifiers_type
112 operator&(integral_type::modifiers_type l, integral_type::modifiers_type r);
113 
114 integral_type::modifiers_type&
115 operator|=(integral_type::modifiers_type& l, integral_type::modifiers_type r);
116 
117 bool
118 parse_integral_type(const string& type_name,
119 		    integral_type& type);
120 
121 /// Private type to hold private members of @ref translation_unit
122 struct translation_unit::priv
123 {
124   const environment*				env_;
125   corpus*					corp;
126   bool						is_constructed_;
127   char						address_size_;
128   language					language_;
129   std::string					path_;
130   std::string					comp_dir_path_;
131   std::string					abs_path_;
132   location_manager				loc_mgr_;
133   mutable global_scope_sptr			global_scope_;
134   mutable vector<type_base_sptr>		synthesized_types_;
135   vector<function_type_sptr>			live_fn_types_;
136   type_maps					types_;
137 
138 
privpriv139   priv(const environment* env)
140     : env_(env),
141       corp(),
142       is_constructed_(),
143       address_size_(),
144       language_(LANG_UNKNOWN)
145   {}
146 
~privpriv147   ~priv()
148   {}
149 
150   type_maps&
get_typespriv151   get_types()
152   {return types_;}
153 }; // end translation_unit::priv
154 
155 // <type_base definitions>
156 
157 /// Definition of the private data of @ref type_base.
158 struct type_base::priv
159 {
160   size_t		size_in_bits;
161   size_t		alignment_in_bits;
162   type_base_wptr	canonical_type;
163   // The data member below holds the canonical type that is managed by
164   // the smart pointer referenced by the canonical_type data member
165   // above.  We are storing this underlying (naked) pointer here, so
166   // that users can access it *fast*.  Otherwise, accessing
167   // canonical_type above implies creating a shared_ptr, and that has
168   // been measured to be slow for some performance hot spots.
169   type_base*		naked_canonical_type;
170   // Computing the representation of a type again and again can be
171   // costly.  So we cache the internal and non-internal type
172   // representation strings here.
173   interned_string	internal_cached_repr_;
174   interned_string	cached_repr_;
175   // The next two data members are used while comparing types during
176   // canonicalization.  They are useful for the "canonical type
177   // propagation" (aka on-the-fly-canonicalization) optimization
178   // implementation.
179 
180   // The set of canonical recursive types this type depends on.
181   unordered_set<uintptr_t> depends_on_recursive_type_;
182   bool canonical_type_propagated_;
183 
privpriv184   priv()
185     : size_in_bits(),
186       alignment_in_bits(),
187       naked_canonical_type(),
188       canonical_type_propagated_(false)
189   {}
190 
191   priv(size_t s,
192        size_t a,
193        type_base_sptr c = type_base_sptr())
size_in_bitspriv194     : size_in_bits(s),
195       alignment_in_bits(a),
196       canonical_type(c),
197       naked_canonical_type(c.get()),
198       canonical_type_propagated_(false)
199   {}
200 
201   /// Test if the current type depends on recursive type comparison.
202   ///
203   /// A recursive type T is a type T which has a sub-type that is T
204   /// (recursively) itself.
205   ///
206   /// So this function tests if the current type has a recursive
207   /// sub-type or is a recursive type itself.
208   ///
209   /// @return true if the current type depends on a recursive type.
210   bool
depends_on_recursive_typepriv211   depends_on_recursive_type() const
212   {return !depends_on_recursive_type_.empty();}
213 
214   /// Test if the current type depends on a given recursive type.
215   ///
216   /// A recursive type T is a type T which has a sub-type that is T
217   /// (recursively) itself.
218   ///
219   /// So this function tests if the current type depends on a given
220   /// recursive type.
221   ///
222   /// @param dependant the type we want to test if the current type
223   /// depends on.
224   ///
225   /// @return true if the current type depends on the recursive type
226   /// @dependant.
227   bool
depends_on_recursive_typepriv228   depends_on_recursive_type(const type_base* dependant) const
229   {
230     return
231       (depends_on_recursive_type_.find(reinterpret_cast<uintptr_t>(dependant))
232        != depends_on_recursive_type_.end());
233   }
234 
235   /// Set the flag that tells if the current type depends on a given
236   /// recursive type.
237   ///
238   /// A recursive type T is a type T which has asub-type that is T
239   /// (recursively) itself.
240   ///
241   /// So this function tests if the current type depends on a
242   /// recursive type.
243   ///
244   /// @param t the recursive type that current type depends on.
245   void
set_depends_on_recursive_typepriv246   set_depends_on_recursive_type(const type_base * t)
247   {depends_on_recursive_type_.insert(reinterpret_cast<uintptr_t>(t));}
248 
249   /// Unset the flag that tells if the current type depends on a given
250   /// recursive type.
251   ///
252   /// A recursive type T is a type T which has asub-type that is T
253   /// (recursively) itself.
254   ///
255   /// So this function flags the current type as not being dependant
256   /// on a given recursive type.
257   ///
258   ///
259   /// @param t the recursive type to consider.
260   void
set_does_not_depend_on_recursive_typepriv261   set_does_not_depend_on_recursive_type(const type_base *t)
262   {depends_on_recursive_type_.erase(reinterpret_cast<uintptr_t>(t));}
263 
264   /// Flag the current type as not being dependant on any recursive type.
265   void
set_does_not_depend_on_recursive_typepriv266   set_does_not_depend_on_recursive_type()
267   {depends_on_recursive_type_.clear();}
268 
269   /// Test if the type carries a canonical type that is the result of
270   /// maybe_propagate_canonical_type(), aka, "canonical type
271   /// propagation optimization".
272   ///
273   /// @return true iff the current type carries a canonical type that
274   /// is the result of canonical type propagation.
275   bool
canonical_type_propagatedpriv276   canonical_type_propagated()
277   {return canonical_type_propagated_;}
278 
279   /// Set the flag that says if the type carries a canonical type that
280   /// is the result of maybe_propagate_canonical_type(), aka,
281   /// "canonical type propagation optimization".
282   ///
283   /// @param f true iff the current type carries a canonical type that
284   /// is the result of canonical type propagation.
285   void
set_canonical_type_propagatedpriv286   set_canonical_type_propagated(bool f)
287   {canonical_type_propagated_ = f;}
288 
289   /// If the current canonical type was set as the result of the
290   /// "canonical type propagation optimization", then clear it.
291   void
clear_propagated_canonical_typepriv292   clear_propagated_canonical_type()
293   {
294     if (canonical_type_propagated_)
295       {
296 	canonical_type.reset();
297 	naked_canonical_type = nullptr;
298 	set_canonical_type_propagated(false);
299       }
300   }
301 }; // end struct type_base::priv
302 
303 // <environment definitions>
304 /// The private data of the @ref environment type.
305 struct environment::priv
306 {
307   config				config_;
308   canonical_types_map_type		canonical_types_;
309   mutable vector<type_base_sptr>	sorted_canonical_types_;
310   type_base_sptr			void_type_;
311   type_base_sptr			variadic_marker_type_;
312   unordered_set<const class_or_union*>	classes_being_compared_;
313   unordered_set<const function_type*>	fn_types_being_compared_;
314   vector<type_base_sptr>		extra_live_types_;
315   interned_string_pool			string_pool_;
316   // The two vectors below represent the stack of left and right
317   // operands of the current type comparison operation that is
318   // happening during type canonicalization.
319   //
320   // Basically, that stack of operand looks like below.
321   //
322   // First, suppose we have a type T_L that has two sub-types as this:
323   //
324   //  T_L
325   //   |
326   //   +-- L_OP0
327   //   |
328   //   +-- L_OP1
329   //
330   // Now suppose that we have another type T_R that has two sub-types
331   // as this:
332   //
333   //  T_R
334   //   |
335   //   +-- R_OP0
336   //   |
337   //   +-- R_OP1
338   //
339   //   Now suppose that we compare T_L against T_R.  We are going to
340   //   have a stack of pair of types. Each pair of types represents
341   //   two (sub) types being compared against each other.
342   //
343   //   On the stack, we will thus first have the pair (T_L, T_R)
344   //   being compared.  Then, we will have the pair (L_OP0, R_OP0)
345   //   being compared, and then the pair (L_OP1, R_OP1) being
346   //   compared.  Like this:
347   //
348   // | T_L | L_OP0 | L_OP1 | <-- this goes into left_type_comp_operands_;
349   //  -------- -------------
350   // | T_R | R_OP0 | R_OP1 | <-- this goes into right_type_comp_operands_;
351   //
352   // This "stack of operands of the current type comparison, during
353   // type canonicalization" is used in the context of the @ref
354   // OnTheFlyCanonicalization optimization.  It's used to detect if a
355   // sub-type of the type being canonicalized depends on a recursive
356   // type.
357   vector<const type_base*>		left_type_comp_operands_;
358   vector<const type_base*>		right_type_comp_operands_;
359   // Vector of types that protentially received propagated canonical types.
360   // If the canonical type propagation is confirmed, the potential
361   // canonical types must be promoted as canonical types. Otherwise if
362   // the canonical type propagation is cancelled, the canonical types
363   // must be cleared.
364   pointer_set		types_with_non_confirmed_propagated_ct_;
365 #ifdef WITH_DEBUG_SELF_COMPARISON
366   // This is used for debugging purposes.
367   // When abidw is used with the option --debug-abidiff, some
368   // libabigail internals need to get a hold on the initial binary
369   // input of abidw, as well as as the abixml file that represents the
370   // ABI of that binary.
371   //
372   // So this one is the corpus for the input binary.
373   corpus_wptr				first_self_comparison_corpus_;
374   // This one is the corpus for the ABIXML file representing the
375   // serialization of the input binary.
376   corpus_wptr				second_self_comparison_corpus_;
377   // This is also used for debugging purposes, when using
378   //   'abidw --debug-abidiff <binary>'.  It holds the set of mapping of
379   // an abixml (canonical) type and its type-id.
380   unordered_map<string, uintptr_t>	type_id_canonical_type_map_;
381   // Likewise.  It holds a map that associates the pointer to a type
382   // read from abixml and the type-id string it corresponds to.
383   unordered_map<uintptr_t, string>	pointer_type_id_map_;
384 #endif
385   bool					canonicalization_is_done_;
386   bool					do_on_the_fly_canonicalization_;
387   bool					decl_only_class_equals_definition_;
388   bool					use_enum_binary_only_equality_;
389 #ifdef WITH_DEBUG_SELF_COMPARISON
390   bool					self_comparison_debug_on_;
391 #endif
392 #ifdef WITH_DEBUG_TYPE_CANONICALIZATION
393   // This controls whether to use canonical type comparison during
394   // type comparison or not.  This is only used for debugging, when we
395   // want to ensure that comparing types using canonical or structural
396   // comparison yields the same result.
397   bool					use_canonical_type_comparison_;
398   // Whether we are debugging type canonicalization or not.  When
399   // debugging type canonicalization, a type is compared to its
400   // potential canonical type twice: The first time with canonical
401   // comparison activated, and the second time with structural
402   // comparison activated.  The two comparison should yield the same
403   // result, otherwise, canonicalization is "broken" for that
404   // particular type.
405   bool					debug_type_canonicalization_;
406 #endif
407 
privpriv408   priv()
409     : canonicalization_is_done_(),
410       do_on_the_fly_canonicalization_(true),
411       decl_only_class_equals_definition_(false),
412       use_enum_binary_only_equality_(false)
413 #ifdef WITH_DEBUG_SELF_COMPARISON
414     ,
415       self_comparison_debug_on_(false)
416 #endif
417 #ifdef WITH_DEBUG_TYPE_CANONICALIZATION
418     ,
419       use_canonical_type_comparison_(true),
420       debug_type_canonicalization_(false)
421 #endif
422   {}
423 
424   /// Push a pair of operands on the stack of operands of the current
425   /// type comparison, during type canonicalization.
426   ///
427   /// For more information on this, please look at the description of
428   /// the right_type_comp_operands_ data member.
429   ///
430   /// @param left the left-hand-side comparison operand to push.
431   ///
432   /// @param right the right-hand-side comparison operand to push.
433   void
push_composite_type_comparison_operandspriv434   push_composite_type_comparison_operands(const type_base* left,
435 					  const type_base* right)
436   {
437     ABG_ASSERT(left && right);
438 
439     left_type_comp_operands_.push_back(left);
440     right_type_comp_operands_.push_back(right);
441   }
442 
443   /// Pop a pair of operands from the stack of operands to the current
444   /// type comparison.
445   ///
446   /// For more information on this, please look at the description of
447   /// the right_type_comp_operands_ data member.
448   ///
449   /// @param left the left-hand-side comparison operand we expect to
450   /// pop from the top of the stack.  If this doesn't match the
451   /// operand found on the top of the stack, the function aborts.
452   ///
453   /// @param right the right-hand-side comparison operand we expect to
454   /// pop from the bottom of the stack. If this doesn't match the
455   /// operand found on the top of the stack, the function aborts.
456   void
pop_composite_type_comparison_operandspriv457   pop_composite_type_comparison_operands(const type_base* left,
458 					 const type_base* right)
459   {
460     const type_base *t = left_type_comp_operands_.back();
461     ABG_ASSERT(t == left);
462     t = right_type_comp_operands_.back();
463     ABG_ASSERT(t == right);
464 
465     left_type_comp_operands_.pop_back();
466     right_type_comp_operands_.pop_back();
467   }
468 
469   /// Mark all the types that comes after a certain one as NOT being
470   /// eligible for the canonical type propagation optimization.
471   ///
472   /// @param type the type that represents the "marker type".  All
473   /// types after this one will be marked as being NON-eligible to
474   /// the canonical type propagation optimization.
475   ///
476   /// @param types the set of types to consider.  In that vector, all
477   /// types that come after @p type are going to be marked as being
478   /// non-eligible to the canonical type propagation optimization.
479   ///
480   /// @return true iff the operation was successful.
481   bool
mark_dependant_typespriv482   mark_dependant_types(const type_base* type,
483 		       vector<const type_base*>& types)
484   {
485     bool found = false;
486     for (auto t : types)
487       {
488 	if (!found
489 	    && (reinterpret_cast<uintptr_t>(t)
490 		== reinterpret_cast<uintptr_t>(type)))
491 	  {
492 	    found = true;
493 	    continue;
494 	  }
495 	else if (found)
496 	  t->priv_->set_depends_on_recursive_type(type);
497       }
498     return found;
499   }
500 
501   /// In the stack of the current types being compared (as part of
502   /// type canonicalization), mark all the types that comes after a
503   /// certain one as NOT being eligible to the canonical type
504   /// propagation optimization.
505   ///
506   /// For a starter, please read about the @ref
507   /// OnTheFlyCanonicalization, aka, "canonical type propagation
508   /// optimization".
509   ///
510   /// To implement that optimization, we need, among other things to
511   /// maintain stack of the types (and their sub-types) being
512   /// currently compared as part of type canonicalization.
513   ///
514   /// Note that we only consider the type that is the right-hand-side
515   /// operand of the comparison because it's that one that is being
516   /// canonicalized and thus, that is not yet canonicalized.
517   ///
518   /// The reason why a type is deemed NON-eligible to the canonical
519   /// type propagation optimization is that it "depends" on
520   /// recursively present type.  Let me explain.
521   ///
522   /// Suppose we have a type T that has sub-types named ST0 and ST1.
523   /// Suppose ST1 itself has a sub-type that is T itself.  In this
524   /// case, we say that T is a recursive type, because it has T
525   /// (itself) as one of its sub-types:
526   ///
527   ///   T
528   ///   +-- ST0
529   ///   |
530   ///   +-- ST1
531   ///        +
532   ///        |
533   ///        +-- T
534   ///
535   /// ST1 is said to "depend" on T because it has T as a sub-type.
536   /// But because T is recursive, then ST1 is said to depend on a
537   /// recursive type.  Notice however that ST0 does not depend on any
538   /// recursive type.
539   ///
540   /// When we are at the point of comparing the sub-type T of ST1
541   /// against its counterpart, the stack of the right-hand-side
542   /// operands of the type canonicalization is going to look like
543   /// this:
544   ///
545   ///    | T | ST1 |
546   ///
547   /// We don't add the type T to the stack as we detect that T was
548   /// already in there (recursive cycle).
549   ///
550   /// So, this function will basically mark ST1 as being NON-eligible
551   /// to being the target of canonical type propagation.
552   ///
553   /// @param right the right-hand-side operand of the type comparison.
554   ///
555   /// @return true iff the operation was successful.
556   bool
mark_dependant_types_compared_untilpriv557   mark_dependant_types_compared_until(const type_base* right)
558   {
559     bool result = false;
560 
561     result |=
562       mark_dependant_types(right,
563 			   right_type_comp_operands_);
564     return result;
565   }
566 
567   /// Propagate the canonical type of a type to another one.
568   ///
569   /// @param src the type to propagate the canonical type from.
570   ///
571   /// @param dest the type to propagate the canonical type of @p src
572   /// to.
573   ///
574   /// @return bool iff the canonical was propagated.
575   bool
propagate_ctpriv576   propagate_ct(const type_base& src, const type_base& dest)
577   {
578     type_base_sptr canonical = src.get_canonical_type();
579     ABG_ASSERT(canonical);
580     dest.priv_->canonical_type = canonical;
581     dest.priv_->naked_canonical_type = canonical.get();
582     dest.priv_->set_canonical_type_propagated(true);
583     return true;
584   }
585 
586   /// Mark a set of types that have been the target of canonical type
587   /// propagation and that depend on a recursive type as being
588   /// permanently canonicalized.
589   ///
590   /// To understand the sentence above, please read the description of
591   /// type canonicalization and especially about the "canonical type
592   /// propagation optimization" at @ref OnTheFlyCanonicalization, in
593   /// the src/abg-ir.cc file.
594   void
confirm_ct_propagationpriv595   confirm_ct_propagation(const type_base* dependant_type)
596   {
597     pointer_set to_remove;
598     for (auto i : types_with_non_confirmed_propagated_ct_)
599       {
600 	type_base *t = reinterpret_cast<type_base*>(i);
601 	ABG_ASSERT(t->priv_->depends_on_recursive_type());
602 	t->priv_->set_does_not_depend_on_recursive_type(dependant_type);
603 	if (!t->priv_->depends_on_recursive_type())
604 	  to_remove.insert(i);
605       }
606 
607     for (auto i : to_remove)
608       types_with_non_confirmed_propagated_ct_.erase(i);
609   }
610 
611   /// Collect the types that depends on a given "target" type.
612   ///
613   /// Walk a set of types and if they depend directly or indirectly on
614   /// a "target" type, then collect them into a set.
615   ///
616   /// @param target the target type to consider.
617   ///
618   /// @param types the types to walk to detect those who depend on @p
619   /// target.
620   ///
621   /// @return true iff one or more type from @p types is found to
622   /// depend on @p target.
623   bool
collect_types_that_depends_onpriv624   collect_types_that_depends_on(const type_base *target,
625 				const pointer_set& types,
626 				pointer_set& collected)
627   {
628     bool result = false;
629     for (const auto i : types)
630       {
631 	// First avoid infinite loop if we've already collected the
632 	// current type.
633 	if (collected.find(i) != collected.end())
634 	  continue;
635 
636 	type_base *t = reinterpret_cast<type_base*>(i);
637 	if (t->priv_->depends_on_recursive_type(target))
638 	  {
639 	    collected.insert(i);
640 	    collect_types_that_depends_on(t, types, collected);
641 	    result = true;
642 	  }
643       }
644     return result;
645   }
646 
647   /// Reset the canonical type (set it nullptr) of a set of types that
648   /// have been the target of canonical type propagation and that
649   /// depend on a given recursive type.
650   ///
651   /// Once the canonical type of a type in that set is reset, the type
652   /// is marked as non being dependant on a recursive type anymore.
653   ///
654   /// To understand the sentences above, please read the description
655   /// of type canonicalization and especially about the "canonical
656   /// type propagation optimization" at @ref OnTheFlyCanonicalization,
657   /// in the src/abg-ir.cc file.
658   ///
659   /// @param target if a type which has been subject to the canonical
660   /// type propagation optimizationdepends on a this target type, then
661   /// cancel its canonical type.
662   void
cancel_ct_propagationpriv663   cancel_ct_propagation(const type_base* target)
664   {
665     pointer_set to_remove;
666     collect_types_that_depends_on(target,
667 				  types_with_non_confirmed_propagated_ct_,
668 				  to_remove);
669 
670     for (auto i : to_remove)
671       {
672 	type_base *t = reinterpret_cast<type_base*>(i);
673 	ABG_ASSERT(t->priv_->depends_on_recursive_type());
674 	type_base_sptr canonical = t->priv_->canonical_type.lock();
675 	if (canonical)
676 	  {
677 	    t->priv_->clear_propagated_canonical_type();
678 	    t->priv_->set_does_not_depend_on_recursive_type();
679 	  }
680       }
681 
682     for (auto i : to_remove)
683       types_with_non_confirmed_propagated_ct_.erase(i);
684   }
685 
686   /// Remove a given type from the set of types that have been
687   /// non-confirmed subjects of the canonical type propagation
688   /// optimization.
689   ///
690   /// @param dependant the dependant type to consider.
691   void
remove_from_types_with_non_confirmed_propagated_ctpriv692   remove_from_types_with_non_confirmed_propagated_ct(const type_base* dependant)
693   {
694     uintptr_t i = reinterpret_cast<uintptr_t>(dependant);
695     types_with_non_confirmed_propagated_ct_.erase(i);
696   }
697 
698 #ifdef WITH_DEBUG_SELF_COMPARISON
699   /// When debugging self comparison, verify that a type T
700   /// de-serialized from abixml has the same canonical type as the
701   /// initial type built from DWARF that was serialized into T in the
702   /// first place.
703   ///
704   /// @param t deserialized type (from abixml) to consider.
705   ///
706   /// @param c the canonical type @p t should have.
707   ///
708   /// @return true iff @p c is the canonical type that @p t should
709   /// have.
710   bool
check_canonical_type_from_abixml_during_self_comppriv711   check_canonical_type_from_abixml_during_self_comp(const type_base* t,
712 						    const type_base* c)
713   {
714     if (!t || !t->get_corpus() || !c)
715       return false;
716 
717     if (!(t->get_corpus()->get_origin() == ir::corpus::NATIVE_XML_ORIGIN))
718       return false;
719 
720     // Get the abixml type-id that this type was constructed from.
721     string type_id;
722     {
723       unordered_map<uintptr_t, string>::const_iterator it =
724 	pointer_type_id_map_.find(reinterpret_cast<uintptr_t>(t));
725       if (it == pointer_type_id_map_.end())
726 	return false;
727       type_id = it->second;
728     }
729 
730     // Get the canonical type the original in-memory type (constructed
731     // from DWARF) had when it was serialized into abixml in the first place.
732     type_base *original_canonical_type = nullptr;
733     if (!type_id.empty())
734       {
735 	unordered_map<string, uintptr_t>::const_iterator it =
736 	  type_id_canonical_type_map_.find(type_id);
737 	if (it == type_id_canonical_type_map_.end())
738 	  return false;
739 	original_canonical_type = reinterpret_cast<type_base*>(it->second);
740       }
741 
742     // Now perform the real check.
743     //
744     // We want to ensure that the canonical type 'c' of 't' is the
745     // same as the canonical type of initial in-memory type (built
746     // from DWARF) that was serialized into 't' (in abixml) in the
747     // first place.
748     if (original_canonical_type == c)
749       return true;
750 
751     return false;
752   }
753 
754   /// When debugging self comparison, verify that a type T
755   /// de-serialized from abixml has the same canonical type as the
756   /// initial type built from DWARF that was serialized into T in the
757   /// first place.
758   ///
759   /// @param t deserialized type (from abixml) to consider.
760   ///
761   /// @param c the canonical type @p t should have.
762   ///
763   /// @return true iff @p c is the canonical type that @p t should
764   /// have.
765   bool
check_canonical_type_from_abixml_during_self_comppriv766   check_canonical_type_from_abixml_during_self_comp(const type_base_sptr& t,
767 						    const type_base_sptr& c)
768   {
769     return check_canonical_type_from_abixml_during_self_comp(t.get(), c.get());
770   }
771 #endif
772 };// end struct environment::priv
773 
774 // <class_or_union::priv definitions>
775 struct class_or_union::priv
776 {
777   typedef_decl_wptr		naming_typedef_;
778   member_types			member_types_;
779   data_members			data_members_;
780   data_members			non_static_data_members_;
781   member_functions		member_functions_;
782   // A map that associates a linkage name to a member function.
783   string_mem_fn_sptr_map_type	mem_fns_map_;
784   // A map that associates function signature strings to member
785   // function.
786   string_mem_fn_ptr_map_type	signature_2_mem_fn_map_;
787   member_function_templates	member_function_templates_;
788   member_class_templates	member_class_templates_;
789 
privpriv790   priv()
791   {}
792 
privpriv793   priv(class_or_union::member_types& mbr_types,
794        class_or_union::data_members& data_mbrs,
795        class_or_union::member_functions& mbr_fns)
796     : member_types_(mbr_types),
797       data_members_(data_mbrs),
798       member_functions_(mbr_fns)
799   {
800     for (data_members::const_iterator i = data_members_.begin();
801 	 i != data_members_.end();
802 	 ++i)
803       if (!get_member_is_static(*i))
804 	non_static_data_members_.push_back(*i);
805   }
806 
807   /// Mark a class or union or union as being currently compared using
808   /// the class_or_union== operator.
809   ///
810   /// Note that is marking business is to avoid infinite loop when
811   /// comparing a class or union or union. If via the comparison of a
812   /// data member or a member function a recursive re-comparison of
813   /// the class or union is attempted, the marking business help to
814   /// detect that infinite loop possibility and avoid it.
815   ///
816   /// @param klass the class or union or union to mark as being
817   /// currently compared.
818   void
mark_as_being_comparedpriv819   mark_as_being_compared(const class_or_union& klass) const
820   {
821     const environment* env = klass.get_environment();
822     ABG_ASSERT(env);
823     env->priv_->classes_being_compared_.insert(&klass);
824   }
825 
826   /// Mark a class or union as being currently compared using the
827   /// class_or_union== operator.
828   ///
829   /// Note that is marking business is to avoid infinite loop when
830   /// comparing a class or union. If via the comparison of a data
831   /// member or a member function a recursive re-comparison of the
832   /// class or union is attempted, the marking business help to detect
833   /// that infinite loop possibility and avoid it.
834   ///
835   /// @param klass the class or union to mark as being currently
836   /// compared.
837   void
mark_as_being_comparedpriv838   mark_as_being_compared(const class_or_union* klass) const
839   {mark_as_being_compared(*klass);}
840 
841   /// Mark a class or union as being currently compared using the
842   /// class_or_union== operator.
843   ///
844   /// Note that is marking business is to avoid infinite loop when
845   /// comparing a class or union. If via the comparison of a data
846   /// member or a member function a recursive re-comparison of the
847   /// class or union is attempted, the marking business help to detect
848   /// that infinite loop possibility and avoid it.
849   ///
850   /// @param klass the class or union to mark as being currently
851   /// compared.
852   void
mark_as_being_comparedpriv853   mark_as_being_compared(const class_or_union_sptr& klass) const
854   {mark_as_being_compared(*klass);}
855 
856   /// If the instance of class_or_union has been previously marked as
857   /// being compared -- via an invocation of mark_as_being_compared()
858   /// this method unmarks it.  Otherwise is has no effect.
859   ///
860   /// This method is not thread safe because it uses the static data
861   /// member classes_being_compared_.  If you wish to use it in a
862   /// multi-threaded environment you should probably protect the
863   /// access to that static data member with a mutex or somesuch.
864   ///
865   /// @param klass the instance of class_or_union to unmark.
866   void
unmark_as_being_comparedpriv867   unmark_as_being_compared(const class_or_union& klass) const
868   {
869     const environment* env = klass.get_environment();
870     ABG_ASSERT(env);
871     env->priv_->classes_being_compared_.erase(&klass);
872   }
873 
874   /// If the instance of class_or_union has been previously marked as
875   /// being compared -- via an invocation of mark_as_being_compared()
876   /// this method unmarks it.  Otherwise is has no effect.
877   ///
878   /// @param klass the instance of class_or_union to unmark.
879   void
unmark_as_being_comparedpriv880   unmark_as_being_compared(const class_or_union* klass) const
881   {
882     if (klass)
883       return unmark_as_being_compared(*klass);
884   }
885 
886   /// Test if a given instance of class_or_union is being currently
887   /// compared.
888   ///
889   ///@param klass the class or union to test.
890   ///
891   /// @return true if @p klass is being compared, false otherwise.
892   bool
comparison_startedpriv893   comparison_started(const class_or_union& klass) const
894   {
895     const environment* env = klass.get_environment();
896     ABG_ASSERT(env);
897     return env->priv_->classes_being_compared_.count(&klass);
898   }
899 
900   /// Test if a given instance of class_or_union is being currently
901   /// compared.
902   ///
903   ///@param klass the class or union to test.
904   ///
905   /// @return true if @p klass is being compared, false otherwise.
906   bool
comparison_startedpriv907   comparison_started(const class_or_union* klass) const
908   {
909     if (klass)
910       return comparison_started(*klass);
911     return false;
912   }
913 }; // end struct class_or_union::priv
914 
915 } // end namespace ir
916 
917 } // end namespace abigail
918 
919 #endif // __ABG_IR_PRIV_H__
920