• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2017-2023 Red Hat, Inc.
5 //
6 // Author: Dodji Seketeli
7 
8 /// @file
9 ///
10 /// The private data and functions of the @ref abigail::ir::comparison types.
11 ///
12 /// Interfaces declared/defined in this file are to be used by parts
13 /// of libabigail but *NOT* by clients of libabigail.
14 ///
15 
16 #ifndef __ABG_COMPARISON_PRIV_H__
17 #define __ABG_COMPARISON_PRIV_H__
18 
19 #include "abg-internal.h"
20 // <headers defining libabigail's API go under here>
21 #include <memory>
22 #include <unordered_set>
23 ABG_BEGIN_EXPORT_DECLARATIONS
24 
25 #include "abg-hash.h"
26 #include "abg-suppression.h"
27 #include "abg-comparison.h"
28 #include "abg-comp-filter.h"
29 #include "abg-sptr-utils.h"
30 #include "abg-tools-utils.h"
31 
32 ABG_END_EXPORT_DECLARATIONS
33 // </headers defining libabigail's API>
34 
35 namespace abigail
36 {
37 
38 namespace comparison
39 {
40 
41 using std::unordered_set;
42 using namespace abigail::suppr;
43 
44 // Inject types from outside in here.
45 using std::vector;
46 using std::dynamic_pointer_cast;
47 using std::static_pointer_cast;
48 using abigail::sptr_utils::noop_deleter;
49 
50 /// Convenience typedef for a pair of decls or types.
51 typedef std::pair<const type_or_decl_base_sptr,
52 		  const type_or_decl_base_sptr> types_or_decls_type;
53 
54 /// A hashing functor for @ref types_or_decls_type.
55 struct types_or_decls_hash
56 {
57   size_t
operatortypes_or_decls_hash58   operator()(const types_or_decls_type& d) const
59   {
60     size_t h1 = hash_type_or_decl(d.first);
61     size_t h2 = hash_type_or_decl(d.second);
62     return hashing::combine_hashes(h1, h2);
63   }
64 };
65 
66 /// An equality functor for @ref types_or_decls_type.
67 struct types_or_decls_equal
68 {
69   bool
operatortypes_or_decls_equal70   operator()(const types_or_decls_type &d1, const types_or_decls_type &d2) const
71   {return d1.first == d2.first && d1.second == d2.second;}
72 };
73 
74 /// A convenience typedef for a map of @ref types_or_decls_type and
75 /// diff_sptr.
76 typedef unordered_map<types_or_decls_type, diff_sptr,
77 		      types_or_decls_hash, types_or_decls_equal>
78   types_or_decls_diff_map_type;
79 
80 /// A hashing functor for using @ref diff_sptr and @ref diff* in a
81 /// hash map or set.
82 struct diff_hash
83 {
84   /// The function-call operator to hash a @ref diff node.
85   ///
86   /// @param d the @ref diff node to hash.
87   ///
88   /// @return the hash value of @p d.
89   size_t
operatordiff_hash90   operator()(const diff_sptr& d) const
91   {return operator()(*d);}
92 
93   /// The function-call operator to hash a @ref diff node.
94   ///
95   /// @param d the @ref diff node to hash.
96   ///
97   /// @return the hash value of @p d.
98   size_t
operatordiff_hash99   operator()(const diff *d) const
100   {return operator()(*d);}
101 
102   /// The function-call operator to hash a @ref diff node.
103   ///
104   /// @param d the @ref diff node to hash.
105   ///
106   /// @return the hash value of @p d.
107   size_t
operatordiff_hash108   operator()(const diff& d) const
109   {
110     diff* canonical_diff = d.get_canonical_diff();
111     ABG_ASSERT(canonical_diff);
112     return reinterpret_cast<size_t>(canonical_diff);
113   }
114 }; // end struct diff_hash
115 
116 /// A comparison functor for using @ref diff_sptr and @ref diff* in a
117 /// hash map or set.
118 struct diff_equal
119 {
120   /// The function-call operator to compare two @ref diff nodes.
121   ///
122   /// @param d1 the first diff node involved in the comparison.
123   ///
124   /// @param d2 the second diff node involved in the comparison.
125   ///
126   /// @return true iff @p d1 equals @p d2.
127   bool
operatordiff_equal128   operator()(const diff* d1, const diff* d2) const
129   {return operator()(*d1, *d2);}
130 
131   /// The function-call operator to compare two @ref diff nodes.
132   ///
133   /// @param d1 the first diff node involved in the comparison.
134   ///
135   /// @param d2 the second diff node involved in the comparison.
136   ///
137   /// @return true iff @p d1 equals @p d2.
138   bool
operatordiff_equal139   operator()(const diff_sptr& d1, const diff_sptr& d2) const
140   {return operator()(*d1, *d2);}
141 
142   /// The function-call operator to compare two @ref diff nodes.
143   ///
144   /// @param d1 the first diff node involved in the comparison.
145   ///
146   /// @param d2 the second diff node involved in the comparison.
147   ///
148   /// @return true iff @p d1 equals @p d2.
149   bool
operatordiff_equal150   operator()(const diff& d1, const diff& d2) const
151   {
152     diff* canonical_diff1 = d1.get_canonical_diff();
153     ABG_ASSERT(canonical_diff1);
154 
155     diff *canonical_diff2 = d2.get_canonical_diff();
156     ABG_ASSERT(canonical_diff2);
157 
158     return canonical_diff1 == canonical_diff2;
159   }
160 }; // end struct diff_equal
161 
162 /// A convenience typedef for an unordered_map which key is a @ref
163 /// diff* and which value is a @ref artifact_sptr_set_type.
164 typedef unordered_map<const diff*, artifact_sptr_set_type,
165 		      diff_hash, diff_equal>
166 diff_artifact_set_map_type;
167 
168 /// The private member (pimpl) for @ref diff_context.
169 struct diff_context::priv
170 {
171   diff_category			allowed_category_;
172   reporter_base_sptr			reporter_;
173   types_or_decls_diff_map_type		types_or_decls_diff_map;
174   unordered_diff_sptr_set		live_diffs_;
175   vector<diff_sptr>			canonical_diffs;
176   vector<filtering::filter_base_sptr>	filters_;
177   // All the suppressions specifications are stored in this data
178   // member.
179   suppressions_type			suppressions_;
180   // The negated suppressions specifications that are in
181   // suppressions_ are stored here.  Each time suppressions_ is
182   // modified, this data member should be cleared.
183   suppressions_type			negated_suppressions_;
184   // The non-negated suppressions specifications that are in
185   // suppressions_ are stored here.  Each time suppressions_ is
186   // modified, this data member should be cleared.
187   suppressions_type			direct_suppressions_;
188   pointer_map				visited_diff_nodes_;
189   corpus_diff_sptr			corpus_diff_;
190   ostream*				default_output_stream_;
191   ostream*				error_output_stream_;
192   bool					perform_change_categorization_;
193   bool					leaf_changes_only_;
194   bool					forbid_visiting_a_node_twice_;
195   bool					reset_visited_diffs_for_each_interface_;
196   bool					hex_values_;
197   bool					show_offsets_sizes_in_bits_;
198   bool					show_relative_offset_changes_;
199   bool					show_stats_only_;
200   bool					show_soname_change_;
201   bool					show_architecture_change_;
202   bool					show_deleted_fns_;
203   bool					show_changed_fns_;
204   bool					show_added_fns_;
205   bool					show_deleted_vars_;
206   bool					show_changed_vars_;
207   bool					show_added_vars_;
208   bool					show_linkage_names_;
209   bool					show_locs_;
210   bool					show_redundant_changes_;
211   bool					show_syms_unreferenced_by_di_;
212   bool					show_added_syms_unreferenced_by_di_;
213   bool					show_unreachable_types_;
214   bool					show_impacted_interfaces_;
215   bool					dump_diff_tree_;
216   bool					do_log_;
217 
privpriv218   priv()
219     : allowed_category_(EVERYTHING_CATEGORY),
220       reporter_(),
221       default_output_stream_(),
222       error_output_stream_(),
223       perform_change_categorization_(true),
224       leaf_changes_only_(),
225       forbid_visiting_a_node_twice_(true),
226       reset_visited_diffs_for_each_interface_(),
227       hex_values_(),
228       show_offsets_sizes_in_bits_(true),
229       show_relative_offset_changes_(true),
230       show_stats_only_(false),
231       show_soname_change_(true),
232       show_architecture_change_(true),
233       show_deleted_fns_(true),
234       show_changed_fns_(true),
235       show_added_fns_(true),
236       show_deleted_vars_(true),
237       show_changed_vars_(true),
238       show_added_vars_(true),
239       show_linkage_names_(false),
240       show_locs_(true),
241       show_redundant_changes_(true),
242       show_syms_unreferenced_by_di_(true),
243       show_added_syms_unreferenced_by_di_(true),
244       show_unreachable_types_(false),
245       show_impacted_interfaces_(true),
246       dump_diff_tree_(),
247       do_log_()
248    {}
249 };// end struct diff_context::priv
250 
251 struct type_diff_base::priv
252 {
253 public:
254   friend class type_diff_base;
255 }; // end class type_diff_base
256 
257 /// Private data for the @ref diff type.  The details of generic view
258 /// of the diff node are expressed here.
259 struct diff::priv
260 {
261   bool				finished_;
262   bool				traversing_;
263   type_or_decl_base_sptr	first_subject_;
264   type_or_decl_base_sptr	second_subject_;
265   vector<diff*>		children_;
266   diff*			parent_;
267   diff*			parent_interface_;
268   diff*			canonical_diff_;
269   diff_context_wptr		ctxt_;
270   diff_category		local_category_;
271   diff_category		category_;
272   mutable bool			reported_once_;
273   mutable bool			currently_reporting_;
274   mutable string		pretty_representation_;
275 
276   priv();
277 
278 public:
279 
privpriv280   priv(type_or_decl_base_sptr first_subject,
281        type_or_decl_base_sptr second_subject,
282        diff_context_sptr ctxt,
283        diff_category category,
284        bool reported_once,
285        bool currently_reporting)
286     : finished_(),
287       traversing_(),
288       first_subject_(first_subject),
289       second_subject_(second_subject),
290       parent_(),
291       parent_interface_(),
292       canonical_diff_(),
293       ctxt_(ctxt),
294       local_category_(category),
295       category_(category),
296       reported_once_(reported_once),
297       currently_reporting_(currently_reporting)
298   {}
299 
300   /// Getter of the diff context associated with this diff.
301   ///
302   /// @returnt a smart pointer to the diff context.
303   diff_context_sptr
get_contextpriv304   get_context() const
305   {return ctxt_.lock();}
306 
307   /// Check if a given categorization of a diff node should make it be
308   /// filtered out.
309   ///
310   /// @param category the categorization to take into account.
311   bool
is_filtered_outpriv312   is_filtered_out(diff_category category)
313   {
314     diff_context_sptr ctxt = get_context();
315     if (!ctxt)
316       return false;
317 
318     if (ctxt->get_allowed_category() == EVERYTHING_CATEGORY)
319       return false;
320 
321     // If this node is on the path of a node that *must* be reported,
322     // then do not filter it.
323     if (category & (HAS_DESCENDANT_WITH_ALLOWED_CHANGE_CATEGORY
324 		    | HAS_PARENT_WITH_ALLOWED_CHANGE_CATEGORY
325 		    | HAS_ALLOWED_CHANGE_CATEGORY))
326       return false;
327 
328   /// We don't want to display nodes suppressed by a user-provided
329   /// suppression specification or by a "private type" suppression
330   /// specification.
331     if (category & (SUPPRESSED_CATEGORY | PRIVATE_TYPE_CATEGORY))
332     return true;
333 
334   // We don't want to display redundant diff nodes, when the user
335   // asked to avoid seeing redundant diff nodes.
336   if (!ctxt->show_redundant_changes()
337       && (category & REDUNDANT_CATEGORY))
338     return true;
339 
340   if (category == NO_CHANGE_CATEGORY)
341     return false;
342 
343   // Ignore the REDUNDANT_CATEGORY bit when comparing allowed
344   // categories and the current set of categories.
345   return !((category & ~REDUNDANT_CATEGORY)
346 	   & (ctxt->get_allowed_category()
347 	      & ~REDUNDANT_CATEGORY));
348   }
349 };// end class diff::priv
350 
351 /// A functor to compare two instances of @ref diff_sptr.
352 struct diff_less_than_functor
353 {
354   /// An operator that takes two instances of @ref diff_sptr returns
355   /// true if its first operand compares less than its second operand.
356   ///
357   /// @param l the first operand to consider.
358   ///
359   /// @param r the second operand to consider.
360   ///
361   /// @return true if @p l compares less than @p r.
362   bool
operatordiff_less_than_functor363   operator()(const diff* l, const diff* r) const
364   {
365     if (!l || !r || !l->first_subject() || !r->first_subject())
366       return false;
367 
368     string l_qn = get_name(l->first_subject());
369     string r_qn = get_name(r->first_subject());
370 
371     return l_qn < r_qn;
372   }
373 
374   /// An operator that takes two instances of @ref diff_sptr returns
375   /// true if its first operand compares less than its second operand.
376   ///
377   /// @param l the first operand to consider.
378   ///
379   /// @param r the second operand to consider.
380   ///
381   /// @return true if @p l compares less than @p r.
382   bool
operatordiff_less_than_functor383   operator()(const diff_sptr& l, const diff_sptr& r) const
384   {return operator()(l.get(), r.get());}
385 }; // end struct diff_less_than_functor
386 
387 struct decl_diff_base::priv
388 {
389 public:
390   friend class decl_diff_base;
391 };//end class priv
392 
393 /// The private data structure for @ref distinct_diff.
394 struct distinct_diff::priv
395 {
396   diff_sptr compatible_child_diff;
397 };// end struct distinct_diff
398 
399 /// The internal type for the impl idiom implementation of @ref
400 /// var_diff.
401 struct var_diff::priv
402 {
403   diff_wptr type_diff_;
404 };//end struct var_diff
405 
406 /// The internal type for the impl idiom implementation of @ref
407 /// pointer_diff.
408 struct pointer_diff::priv
409 {
410   diff_sptr underlying_type_diff_;
411 
privpriv412   priv(diff_sptr ud)
413     : underlying_type_diff_(ud)
414   {}
415 };//end struct pointer_diff::priv
416 
417 /// The internal type for the impl idiom implementation of @ref
418 /// subrange_diff.
419 struct subrange_diff::priv
420 {
421   diff_sptr underlying_type_diff_;
422 
privpriv423   priv(diff_sptr u)
424     : underlying_type_diff_(u)
425   {}
426 }; // end struct subrange_diff::priv
427 
428 struct array_diff::priv
429 {
430   /// The diff between the two array element types.
431   diff_sptr element_type_diff_;
432 
privpriv433   priv(diff_sptr element_type_diff)
434     : element_type_diff_(element_type_diff)
435   {}
436 };//end struct array_diff::priv
437 
438 struct reference_diff::priv
439 {
440   diff_sptr underlying_type_diff_;
privpriv441   priv(diff_sptr underlying)
442     : underlying_type_diff_(underlying)
443   {}
444 };//end struct reference_diff::priv
445 
446 struct qualified_type_diff::priv
447 {
448   diff_sptr underlying_type_diff;
449   mutable diff_sptr leaf_underlying_type_diff;
450 
privpriv451   priv(diff_sptr underlying)
452     : underlying_type_diff(underlying)
453   {}
454 };// end struct qualified_type_diff::priv
455 
456 struct enum_diff::priv
457 {
458   diff_sptr underlying_type_diff_;
459   edit_script enumerators_changes_;
460   string_enumerator_map deleted_enumerators_;
461   string_enumerator_map inserted_enumerators_;
462   string_changed_enumerator_map changed_enumerators_;
463 
privpriv464   priv(diff_sptr underlying)
465     : underlying_type_diff_(underlying)
466   {}
467 };//end struct enum_diff::priv
468 
469 /// A functor to compare two enumerators based on their value.  This
470 /// implements the "less than" operator.
471 struct enumerator_value_comp
472 {
473   bool
operatorenumerator_value_comp474   operator()(const enum_type_decl::enumerator& f,
475 	     const enum_type_decl::enumerator& s) const
476   {return f.get_value() < s.get_value();}
477 };//end struct enumerator_value_comp
478 
479 /// A functor to compare two changed enumerators, based on their
480 /// initial value.
481 struct changed_enumerator_comp
482 {
483   bool
operatorchanged_enumerator_comp484   operator()(const changed_enumerator& f,
485 	     const changed_enumerator& s) const
486   {return f.first.get_value() < s.first.get_value();}
487 };// end struct changed_enumerator_comp.
488 
489 /// The type of private data of @ref class_or_union_diff.
490 struct class_or_union_diff::priv
491 {
492   edit_script member_types_changes_;
493   edit_script data_members_changes_;
494   edit_script member_fns_changes_;
495   edit_script member_fn_tmpls_changes_;
496   edit_script member_class_tmpls_changes_;
497 
498   string_decl_base_sptr_map deleted_member_types_;
499   string_decl_base_sptr_map inserted_member_types_;
500   string_diff_sptr_map changed_member_types_;
501   diff_sptrs_type sorted_changed_member_types_;
502   string_decl_base_sptr_map deleted_data_members_;
503   unsigned_decl_base_sptr_map deleted_dm_by_offset_;
504   string_decl_base_sptr_map inserted_data_members_;
505   unsigned_decl_base_sptr_map inserted_dm_by_offset_;
506   // This map contains the data member which sub-type changed.
507   string_var_diff_sptr_map subtype_changed_dm_;
508   var_diff_sptrs_type sorted_subtype_changed_dm_;
509   // This one contains the list of data members changes that can be
510   // represented as a data member foo that got removed from offset N,
511   // and a data member bar that got inserted at offset N; IOW, this
512   // can be translated as data member foo that got changed into data
513   // member bar at offset N.
514   unsigned_var_diff_sptr_map changed_dm_;
515   var_diff_sptrs_type sorted_changed_dm_;
516 
517   // This is a data structure to represent data members that have been
518   // replaced by anonymous data members.  It's a map that associates
519   // the name of the data member to the anonymous data member that
520   // replaced it.
521   string_decl_base_sptr_map dms_replaced_by_adms_;
522   mutable changed_var_sptrs_type dms_replaced_by_adms_ordered_;
523   string_member_function_sptr_map deleted_member_functions_;
524   class_or_union::member_functions sorted_deleted_member_functions_;
525   string_member_function_sptr_map inserted_member_functions_;
526   class_or_union::member_functions sorted_inserted_member_functions_;
527   string_function_decl_diff_sptr_map changed_member_functions_;
528   function_decl_diff_sptrs_type sorted_changed_member_functions_;
529   string_decl_base_sptr_map deleted_member_class_tmpls_;
530   string_decl_base_sptr_map inserted_member_class_tmpls_;
531   string_diff_sptr_map changed_member_class_tmpls_;
532   diff_sptrs_type sorted_changed_member_class_tmpls_;
533 
534   type_or_decl_base_sptr
535   member_type_has_changed(decl_base_sptr) const;
536 
537   decl_base_sptr
538   subtype_changed_dm(decl_base_sptr) const;
539 
540   decl_base_sptr
541   member_class_tmpl_has_changed(decl_base_sptr) const;
542 
543   size_t
544   get_deleted_non_static_data_members_number() const;
545 
546   size_t
547   get_inserted_non_static_data_members_number() const;
548 
549   size_t
550   count_filtered_subtype_changed_dm(bool local_only = false);
551 
552   size_t
553   count_filtered_changed_dm(bool local_only = false);
554 
555   size_t
556   count_filtered_changed_mem_fns(const diff_context_sptr&);
557 
558   size_t
559   count_filtered_inserted_mem_fns(const diff_context_sptr&);
560 
561   size_t
562   count_filtered_deleted_mem_fns(const diff_context_sptr&);
563 
privpriv564   priv()
565   {}
566 }; // end struct class_or_union_diff::priv
567 
568 /// A comparison functor to compare two data members based on their
569 /// offset.
570 struct data_member_comp
571 {
572 
573   /// Compare two data members.
574   ///
575   /// First look at their offset and then their name.
576   ///
577   /// @parm first_dm the first data member to consider.
578   ///
579   /// @param second_dm the second data member to consider.
580   bool
compare_data_membersdata_member_comp581   compare_data_members(const var_decl_sptr& first_dm,
582 		       const var_decl_sptr& second_dm) const
583   {
584     ABG_ASSERT(first_dm);
585     ABG_ASSERT(second_dm);
586 
587     size_t first_offset = get_data_member_offset(first_dm);
588     size_t second_offset = get_data_member_offset(second_dm);
589 
590     // The data member at the smallest offset comes first.
591     if (first_offset != second_offset)
592       return first_offset < second_offset;
593 
594     string first_dm_name = first_dm->get_name();
595     string second_dm_name = second_dm->get_name();
596 
597     // But in case the two data members are at the same offset, then
598     // sort them lexicographically.
599     return first_dm_name < second_dm_name;
600   }
601 
602   /// Compare two data members.
603   ///
604   /// First look at their offset and then their name.
605   ///
606   /// @parm first_dm the first data member to consider.
607   ///
608   /// @param second_dm the second data member to consider.
609   bool
operatordata_member_comp610   operator()(const decl_base_sptr& f,
611 	     const decl_base_sptr& s) const
612   {
613     var_decl_sptr first_dm = is_data_member(f);
614     var_decl_sptr second_dm = is_data_member(s);
615 
616     return compare_data_members(first_dm, second_dm);
617   }
618 
619   /// Compare two data members.
620   ///
621   /// First look at their offset and then their name.
622   ///
623   /// @parm first_dm the first data member to consider.
624   ///
625   /// @param second_dm the second data member to consider.
626   bool
operatordata_member_comp627   operator()(const changed_var_sptr& f,
628 	     const changed_var_sptr& s) const
629   {
630     var_decl_sptr first_dm = is_data_member(is_decl(f.first));
631     var_decl_sptr second_dm = is_data_member(is_decl(s.first));
632 
633     return compare_data_members(first_dm, second_dm);
634   }
635 };//end struct data_member_comp
636 
637 /// The type of the private data (pimpl sub-object) of the @ref
638 /// class_diff type.
639 struct class_diff::priv
640 {
641   edit_script base_changes_;
642   string_base_sptr_map deleted_bases_;
643   class_decl::base_specs sorted_deleted_bases_;
644   string_base_sptr_map inserted_bases_;
645   class_decl::base_specs sorted_inserted_bases_;
646   string_base_diff_sptr_map changed_bases_;
647   base_diff_sptrs_type sorted_changed_bases_;
648   vector<class_decl::base_spec_sptr> moved_bases_;
649 
650   class_decl::base_spec_sptr
651   base_has_changed(class_decl::base_spec_sptr) const;
652 
653   size_t
654   count_filtered_bases();
655 
privpriv656   priv()
657   {}
658 };//end struct class_diff::priv
659 
660 /// A functor to compare instances of @ref class_decl::base_spec.
661 struct base_spec_comp
662 {
663   bool
operatorbase_spec_comp664   operator()(const class_decl::base_spec&l,
665 	     const class_decl::base_spec&r)
666   {
667     string str1 = l.get_pretty_representation();
668     string str2 = r.get_pretty_representation();
669     return str1 < str2;
670   }
671   bool
operatorbase_spec_comp672   operator()(const class_decl::base_spec_sptr&l,
673 	     const class_decl::base_spec_sptr&r)
674   {return operator()(*l, *r);}
675 }; // end base_spec_comp
676 
677 /// A comparison function for instances of @ref base_diff.
678 struct base_diff_comp
679 {
680   bool
operatorbase_diff_comp681   operator()(const base_diff& l, const base_diff& r) const
682   {
683     class_decl::base_spec_sptr f = l.first_base(), s = r.first_base();
684     if (f->get_offset_in_bits() >= 0
685 	&& s->get_offset_in_bits() >= 0)
686       return f->get_offset_in_bits() < s->get_offset_in_bits();
687     else
688       return (f->get_base_class()->get_pretty_representation()
689 	      < s->get_base_class()->get_pretty_representation());
690   }
691 
692   bool
operatorbase_diff_comp693   operator()(const base_diff* l, const base_diff* r) const
694   {return operator()(*l, *r);}
695 
696   bool
operatorbase_diff_comp697   operator()(const base_diff_sptr l, const base_diff_sptr r) const
698   {return operator()(l.get(), r.get());}
699 }; // end struct base_diff_comp
700 
701 /// A comparison functor to compare two instances of @ref var_diff
702 /// that represent changed data members based on the offset of the
703 /// initial data members, or if equal, based on their qualified name.
704 /// If equal again, then the offset and qualified name of the new data
705 /// members are considered.
706 struct data_member_diff_comp
707 {
708   /// @param f the first change to data member to take into account
709   ///
710   /// @param s the second change to data member to take into account.
711   ///
712   /// @return true iff f is before s.
713   bool
operatordata_member_diff_comp714   operator()(const var_diff_sptr f,
715 	     const var_diff_sptr s) const
716   {
717     var_decl_sptr first_dm = f->first_var();
718     var_decl_sptr second_dm = s->first_var();
719 
720     ABG_ASSERT(is_data_member(first_dm));
721     ABG_ASSERT(is_data_member(second_dm));
722 
723     size_t off1 = get_data_member_offset(first_dm);
724     size_t off2 = get_data_member_offset(second_dm);
725 
726     if (off1 != off2)
727       return off1 < off2;
728 
729     // The two offsets of the initial data members are the same.  So
730     // lets compare the qualified name of these initial data members.
731 
732     string name1 = first_dm->get_qualified_name();
733     string name2 = second_dm->get_qualified_name();
734 
735     if (name1 != name2)
736       return name1 < name2;
737 
738     // The offsets and the qualified names of the initial data members
739     // are the same.  Let's now compare the offsets of the *new* data
740     // members.
741 
742     first_dm = f->second_var();
743     second_dm = s->second_var();
744 
745     ABG_ASSERT(is_data_member(first_dm));
746     ABG_ASSERT(is_data_member(second_dm));
747 
748     off1 = get_data_member_offset(first_dm);
749     off2 = get_data_member_offset(second_dm);
750 
751     if (off1 != off2)
752       return off1 < off2;
753 
754     // The offsets of the new data members are the same, dang!  Let's
755     // compare the qualified names of these new data members then.
756 
757     name1 = first_dm->get_qualified_name();
758     name2 = second_dm->get_qualified_name();
759 
760     return name1 < name2;
761   }
762 }; // end struct var_diff_comp
763 
764 /// A comparison functor for instances of @ref function_decl_diff that
765 /// represent changes between two virtual member functions.
766 struct virtual_member_function_diff_comp
767 {
768   bool
operatorvirtual_member_function_diff_comp769   operator()(const function_decl_diff& l,
770 	     const function_decl_diff& r) const
771   {
772     ABG_ASSERT(get_member_function_is_virtual(l.first_function_decl()));
773     ABG_ASSERT(get_member_function_is_virtual(r.first_function_decl()));
774 
775     return (get_member_function_vtable_offset(l.first_function_decl())
776 	    < get_member_function_vtable_offset(r.first_function_decl()));
777   }
778 
779   bool
operatorvirtual_member_function_diff_comp780   operator()(const function_decl_diff* l,
781 	     const function_decl_diff* r)
782   {return operator()(*l, *r);}
783 
784   bool
operatorvirtual_member_function_diff_comp785   operator()(const function_decl_diff_sptr l,
786 	     const function_decl_diff_sptr r)
787   {return operator()(l.get(), r.get());}
788 }; // end struct virtual_member_function_diff_comp
789 
790 struct base_diff::priv
791 {
792   class_diff_sptr underlying_class_diff_;
793 
privpriv794   priv(class_diff_sptr underlying)
795     : underlying_class_diff_(underlying)
796   {}
797 }; // end struct base_diff::priv
798 
799 struct scope_diff::priv
800 {
801   // The edit script built by the function compute_diff.
802   edit_script member_changes_;
803 
804   // Below are the useful lookup tables.
805   //
806   // If you add a new lookup table, please update member functions
807   // clear_lookup_tables, lookup_tables_empty and
808   // ensure_lookup_tables_built.
809 
810   // The deleted/inserted types/decls.  These basically map what is
811   // inside the member_changes_ data member.  Note that for instance,
812   // a given type T might be deleted from the first scope and added to
813   // the second scope again; this means that the type was *changed*.
814   string_decl_base_sptr_map deleted_types_;
815   string_decl_base_sptr_map deleted_decls_;
816   string_decl_base_sptr_map inserted_types_;
817   string_decl_base_sptr_map inserted_decls_;
818 
819   // The changed types/decls lookup tables.
820   //
821   // These lookup tables are populated from the lookup tables above.
822   //
823   // Note that the value stored in each of these tables is a pair
824   // containing the old decl/type and the new one.  That way it is
825   // easy to run a diff between the old decl/type and the new one.
826   //
827   // A changed type/decl is one that has been deleted from the first
828   // scope and that has been inserted into the second scope.
829   string_diff_sptr_map changed_types_;
830   diff_sptrs_type sorted_changed_types_;
831   string_diff_sptr_map changed_decls_;
832   diff_sptrs_type sorted_changed_decls_;
833 
834   // The removed types/decls lookup tables.
835   //
836   // A removed type/decl is one that has been deleted from the first
837   // scope and that has *NOT* been inserted into it again.
838   string_decl_base_sptr_map removed_types_;
839   string_decl_base_sptr_map removed_decls_;
840 
841   // The added types/decls lookup tables.
842   //
843   // An added type/decl is one that has been inserted to the first
844   // scope but that has not been deleted from it.
845   string_decl_base_sptr_map added_types_;
846   string_decl_base_sptr_map added_decls_;
847 };//end struct scope_diff::priv
848 
849 /// A comparison functor for instances of @ref diff.
850 struct diff_comp
851 {
852   /// Lexicographically compare two diff nodes.
853   ///
854   /// Compare the pretty representation of the first subjects of two
855   /// diff nodes.
856   ///
857   /// @return true iff @p l is less than @p r.
858   bool
operatordiff_comp859   operator()(const diff& l, diff& r) const
860   {
861     return (get_pretty_representation(l.first_subject(), true)
862 	    <
863 	    get_pretty_representation(r.first_subject(), true));
864   }
865 
866   /// Lexicographically compare two diff nodes.
867   ///
868   /// Compare the pretty representation of the first subjects of two
869   /// diff nodes.
870   ///
871   /// @return true iff @p l is less than @p r.
872   bool
operatordiff_comp873   operator()(const diff* l, diff* r) const
874   {return operator()(*l, *r);}
875 
876   /// Lexicographically compare two diff nodes.
877   ///
878   /// Compare the pretty representation of the first subjects of two
879   /// diff nodes.
880   ///
881   /// @return true iff @p l is less than @p r.
882   bool
operatordiff_comp883   operator()(const diff_sptr l, diff_sptr r) const
884   {return operator()(l.get(), r.get());}
885 }; // end struct diff_comp;
886 
887 struct fn_parm_diff::priv
888 {
889   mutable diff_sptr type_diff;
890 }; // end struct fn_parm_diff::priv
891 
892 struct function_type_diff::priv
893 {
894   diff_sptr	return_type_diff_;
895   edit_script	parm_changes_;
896 
897   // useful lookup tables.
898   string_parm_map			deleted_parms_;
899   vector<function_decl::parameter_sptr> sorted_deleted_parms_;
900   string_parm_map			added_parms_;
901   vector<function_decl::parameter_sptr> sorted_added_parms_;
902   // This map contains parameters sub-type changes that don't change
903   // the name of the type of the parameter.
904   string_fn_parm_diff_sptr_map		subtype_changed_parms_;
905   vector<fn_parm_diff_sptr>		sorted_subtype_changed_parms_;
906   // This map contains parameter type changes that actually change the
907   // name of the type of the parameter, but in a compatible way;
908   // otherwise, the mangling of the function would have changed (in
909   // c++ at least).
910   unsigned_fn_parm_diff_sptr_map	changed_parms_by_id_;
911   vector<fn_parm_diff_sptr>		sorted_changed_parms_by_id_;
912   unsigned_parm_map			deleted_parms_by_id_;
913   unsigned_parm_map			added_parms_by_id_;
914 
privpriv915   priv()
916   {}
917 }; // end struct function_type_diff::priv
918 
919 struct function_decl_diff::priv
920 {
921   function_type_diff_sptr type_diff_;
922 
privpriv923   priv()
924   {}
925 };// end struct function_decl_diff::priv
926 
927 /// A comparison functor to compare two instances of @ref fn_parm_diff
928 /// based on their indexes.
929 struct fn_parm_diff_comp
930 {
931   /// @param f the first diff
932   ///
933   /// @param s the second diff
934   ///
935   /// @return true if the index of @p f is less than the index of @p
936   /// s.
937   bool
operatorfn_parm_diff_comp938   operator()(const fn_parm_diff& f, const fn_parm_diff& s)
939   {return f.first_parameter()->get_index() < s.first_parameter()->get_index();}
940 
941   bool
operatorfn_parm_diff_comp942   operator()(const fn_parm_diff_sptr& f, const fn_parm_diff_sptr& s)
943   {return operator()(*f, *s);}
944 }; // end struct fn_parm_diff_comp
945 
946 /// Functor that compares two function parameters for the purpose of
947 /// sorting them.
948 struct parm_comp
949 {
950   /// Returns true iff the index of the first parameter is smaller
951   /// than the of the second parameter.
952   ///
953   /// @param l the first parameter to compare.
954   ///
955   /// @param r the second parameter to compare.
956   ///
957   /// @return true iff the index of the first parameter is smaller
958   /// than the of the second parameter.
959   bool
operatorparm_comp960   operator()(const function_decl::parameter& l,
961 	     const function_decl::parameter& r)
962   {return l.get_index() < r.get_index();}
963 
964   /// Returns true iff the index of the first parameter is smaller
965   /// than the of the second parameter.
966   ///
967   /// @param l the first parameter to compare.
968   ///
969   /// @param r the second parameter to compare.
970   ///
971   /// @return true iff the index of the first parameter is smaller
972   /// than the of the second parameter.
973   bool
operatorparm_comp974   operator()(const function_decl::parameter_sptr& l,
975 	     const function_decl::parameter_sptr& r)
976   {return operator()(*l, *r);}
977 }; // end struct parm_comp
978 
979 /// A functor to compare instances of @ref var_decl base on their
980 /// qualified names.
981 struct var_comp
982 {
983   bool
operatorvar_comp984   operator() (const var_decl& l, const var_decl& r) const
985   {
986     string name1 = l.get_qualified_name(), name2 = r.get_qualified_name();
987     return name1 < name2;
988   }
989 
990   bool
operatorvar_comp991   operator() (const var_decl* l, const var_decl* r) const
992   {return operator()(*l, *r);}
993 };// end struct var_comp
994 
995 /// A functor to compare instances of @ref elf_symbol base on their
996 /// names.
997 struct elf_symbol_comp
998 {
999   bool
operatorelf_symbol_comp1000   operator()(const elf_symbol& l, const elf_symbol& r)
1001   {
1002     string name1 = l.get_id_string(), name2 = r.get_id_string();
1003     return name1 < name2;
1004   }
1005 
1006   bool
operatorelf_symbol_comp1007   operator()(const elf_symbol* l, const elf_symbol* r)
1008   {return operator()(*l, *r);}
1009 
1010   bool
operatorelf_symbol_comp1011   operator()(const elf_symbol_sptr& l, const elf_symbol_sptr& r)
1012   {return operator()(l.get(), r.get());}
1013 }; //end struct elf_symbol_comp
1014 
1015 struct typedef_diff::priv
1016 {
1017   diff_sptr underlying_type_diff_;
1018 
privpriv1019   priv(const diff_sptr underlying_type_diff)
1020     : underlying_type_diff_(underlying_type_diff)
1021   {}
1022 };//end struct typedef_diff::priv
1023 
1024 struct translation_unit_diff::priv
1025 {
1026   translation_unit_sptr first_;
1027   translation_unit_sptr second_;
1028 
privpriv1029   priv(translation_unit_sptr f, translation_unit_sptr s)
1030     : first_(f), second_(s)
1031   {}
1032 };//end struct translation_unit_diff::priv
1033 
1034 struct corpus_diff::priv
1035 {
1036   bool					finished_;
1037   string				pretty_representation_;
1038   vector<diff*>			children_;
1039   corpus_sptr				first_;
1040   corpus_sptr				second_;
1041   diff_context_wptr			ctxt_;
1042   corpus_diff::diff_stats_sptr		diff_stats_;
1043   bool					sonames_equal_;
1044   bool					architectures_equal_;
1045   edit_script				fns_edit_script_;
1046   edit_script				vars_edit_script_;
1047   edit_script				unrefed_fn_syms_edit_script_;
1048   edit_script				unrefed_var_syms_edit_script_;
1049   string_function_ptr_map		deleted_fns_;
1050   string_function_ptr_map		suppressed_deleted_fns_;
1051   string_function_ptr_map		added_fns_;
1052   string_function_ptr_map		suppressed_added_fns_;
1053   string_function_decl_diff_sptr_map	changed_fns_map_;
1054   function_decl_diff_sptrs_type	changed_fns_;
1055   string_var_ptr_map			deleted_vars_;
1056   string_var_ptr_map			suppressed_deleted_vars_;
1057   string_var_ptr_map			added_vars_;
1058   string_var_ptr_map			suppressed_added_vars_;
1059   string_var_diff_sptr_map		changed_vars_map_;
1060   var_diff_sptrs_type			sorted_changed_vars_;
1061   string_elf_symbol_map		added_unrefed_fn_syms_;
1062   string_elf_symbol_map		suppressed_added_unrefed_fn_syms_;
1063   string_elf_symbol_map		deleted_unrefed_fn_syms_;
1064   string_elf_symbol_map		suppressed_deleted_unrefed_fn_syms_;
1065   string_elf_symbol_map		added_unrefed_var_syms_;
1066   string_elf_symbol_map		suppressed_added_unrefed_var_syms_;
1067   string_elf_symbol_map		deleted_unrefed_var_syms_;
1068   string_elf_symbol_map		suppressed_deleted_unrefed_var_syms_;
1069   edit_script				unreachable_types_edit_script_;
1070   string_type_base_sptr_map		deleted_unreachable_types_;
1071   vector<type_base_sptr>		deleted_unreachable_types_sorted_;
1072   string_type_base_sptr_map		suppressed_deleted_unreachable_types_;
1073   string_type_base_sptr_map		added_unreachable_types_;
1074   vector<type_base_sptr>		added_unreachable_types_sorted_;
1075   string_type_base_sptr_map		suppressed_added_unreachable_types_;
1076   string_diff_sptr_map			changed_unreachable_types_;
1077   mutable vector<diff_sptr>		changed_unreachable_types_sorted_;
1078   diff_maps				leaf_diffs_;
1079 
1080   /// Default constructor of corpus_diff::priv.
privpriv1081   priv()
1082     : finished_(false),
1083       sonames_equal_(false),
1084       architectures_equal_(false)
1085   {}
1086 
1087   /// Constructor of corpus_diff::priv.
1088   ///
1089   /// @param first the first corpus of this diff.
1090   ///
1091   /// @param second the second corpus of this diff.
1092   ///
1093   /// @param ctxt the context of the diff.
privpriv1094   priv(corpus_sptr first,
1095        corpus_sptr second,
1096        diff_context_sptr ctxt)
1097     : finished_(false),
1098       first_(first),
1099       second_(second),
1100       ctxt_(ctxt),
1101       sonames_equal_(false),
1102       architectures_equal_(false)
1103   {}
1104 
1105   diff_context_sptr
1106   get_context();
1107 
1108   bool
1109   lookup_tables_empty() const;
1110 
1111   void
1112   clear_lookup_tables();
1113 
1114   void
1115   ensure_lookup_tables_populated();
1116 
1117   void
1118   apply_supprs_to_added_removed_fns_vars_unreachable_types();
1119 
1120   bool
1121   deleted_function_is_suppressed(const function_decl* fn) const;
1122 
1123   bool
1124   added_function_is_suppressed(const function_decl* fn) const;
1125 
1126   bool
1127   deleted_variable_is_suppressed(const var_decl* var) const;
1128 
1129   bool
1130   added_variable_is_suppressed(const var_decl* var) const;
1131 
1132   bool
1133   added_unreachable_type_is_suppressed(const type_base *t)const ;
1134 
1135   bool
1136   deleted_unreachable_type_is_suppressed(const type_base *t)const ;
1137 
1138   bool
1139   deleted_unrefed_fn_sym_is_suppressed(const elf_symbol*) const;
1140 
1141   bool
1142   added_unrefed_fn_sym_is_suppressed(const elf_symbol*) const;
1143 
1144   bool
1145   deleted_unrefed_var_sym_is_suppressed(const elf_symbol*) const;
1146 
1147   bool
1148   added_unrefed_var_sym_is_suppressed(const elf_symbol*) const;
1149 
1150   void count_leaf_changes(size_t &num_changes, size_t &num_filtered);
1151 
1152   void count_leaf_type_changes(size_t &num_type_changes,
1153 			       size_t &num_type_changes_filtered);
1154 
1155   void count_unreachable_types(size_t &num_added,
1156 			       size_t &num_removed,
1157 			       size_t &num_changed,
1158 			       size_t &num_filtered_added,
1159 			       size_t &num_filtered_removed,
1160 			       size_t &num_filtered_changed);
1161 
1162   const string_diff_sptr_map&
1163   changed_unreachable_types() const;
1164 
1165   const vector<diff_sptr>&
1166   changed_unreachable_types_sorted() const;
1167 
1168   void
1169   apply_filters_and_compute_diff_stats(corpus_diff::diff_stats&);
1170 
1171   void
1172   emit_diff_stats(const diff_stats&	stats,
1173 		  ostream&		out,
1174 		  const string&	indent);
1175 
1176   void
1177   categorize_redundant_changed_sub_nodes();
1178 
1179   void
1180   clear_redundancy_categorization();
1181 
1182   void
1183   maybe_dump_diff_tree();
1184 }; // end corpus::priv
1185 
1186 /// "Less than" functor to compare instances of @ref function_decl.
1187 struct function_comp
1188 {
1189   /// The actual "less than" operator for instances of @ref
1190   /// function_decl.  It returns true if the first @ref function_decl
1191   /// is lest than the second one.
1192   ///
1193   /// @param f the first @ref function_decl to take in account.
1194   ///
1195   /// @param s the second @ref function_decl to take in account.
1196   ///
1197   /// @return true iff @p f is less than @p s.
1198   bool
operatorfunction_comp1199   operator()(const function_decl& f, const function_decl& s)
1200   {return abigail::ir::function_decl_is_less_than(f, s);}
1201 
1202   /// The actual "less than" operator for instances of @ref
1203   /// function_decl.  It returns true if the first @ref function_decl
1204   /// is lest than the second one.
1205   ///
1206   /// @param f the first @ref function_decl to take in account.
1207   ///
1208   /// @param s the second @ref function_decl to take in account.
1209   ///
1210   /// @return true iff @p f is less than @p s.
1211   bool
operatorfunction_comp1212   operator()(const function_decl* f, const function_decl* s)
1213   {return operator()(*f, *s);}
1214 
1215   /// The actual "less than" operator for instances of @ref
1216   /// function_decl.  It returns true if the first @ref function_decl
1217   /// is lest than the second one.
1218   ///
1219   /// @param f the first @ref function_decl to take in account.
1220   ///
1221   /// @param s the second @ref function_decl to take in account.
1222   ///
1223   /// @return true iff @p f is less than @p s.
1224   bool
operatorfunction_comp1225   operator()(const function_decl_sptr f, const function_decl_sptr s)
1226   {return operator()(f.get(), s.get());}
1227 }; // end function_comp
1228 
1229 /// A "Less Than" functor to compare instance of @ref
1230 /// function_decl_diff.
1231 struct function_decl_diff_comp
1232 {
1233   /// The actual less than operator.
1234   ///
1235   /// It returns true if the first @ref function_decl_diff is less
1236   /// than the second one.
1237   ///
1238   /// param first the first @ref function_decl_diff to consider.
1239   ///
1240   /// @param second the second @ref function_decl_diff to consider.
1241   ///
1242   /// @return true iff @p first is less than @p second.
1243   bool
operatorfunction_decl_diff_comp1244   operator()(const function_decl_diff& first,
1245 	     const function_decl_diff& second)
1246   {
1247     function_decl_sptr f = first.first_function_decl(),
1248       s = second.first_function_decl();
1249 
1250     string fr = f->get_qualified_name(),
1251       sr = s->get_qualified_name();
1252 
1253     if (fr == sr)
1254       {
1255 	if (f->get_symbol())
1256 	  fr = f->get_symbol()->get_id_string();
1257 	else if (!f->get_linkage_name().empty())
1258 	  fr = f->get_linkage_name();
1259 	else
1260 	  fr = f->get_pretty_representation();
1261 
1262 	if (s->get_symbol())
1263 	  sr = s->get_symbol()->get_id_string();
1264 	else if (!s->get_linkage_name().empty())
1265 	  sr = s->get_linkage_name();
1266 	else
1267 	  sr = s->get_pretty_representation();
1268       }
1269 
1270     return (fr.compare(sr) < 0);
1271   }
1272 
1273   /// The actual less than operator.
1274   ///
1275   /// It returns true if the first @ref function_decl_diff_sptr is
1276   /// less than the second one.
1277   ///
1278   /// param first the first @ref function_decl_diff_sptr to consider.
1279   ///
1280   /// @param second the second @ref function_decl_diff_sptr to
1281   /// consider.
1282   ///
1283   /// @return true iff @p first is less than @p second.
1284   bool
operatorfunction_decl_diff_comp1285   operator()(const function_decl_diff_sptr first,
1286 	     const function_decl_diff_sptr second)
1287   {return operator()(*first, *second);}
1288 }; // end struct function_decl_diff_comp
1289 
1290 /// Functor to sort instances of @ref var_diff_sptr
1291 struct var_diff_sptr_comp
1292 {
1293   /// Return true if the first argument is less than the second one.
1294   ///
1295   /// @param f the first argument to consider.
1296   ///
1297   /// @param s the second argument to consider.
1298   ///
1299   /// @return true if @p f is less than @p s.
1300   bool
operatorvar_diff_sptr_comp1301   operator()(const var_diff_sptr f,
1302 	     const var_diff_sptr s)
1303   {
1304     return (f->first_var()->get_qualified_name()
1305 	    < s->first_var()->get_qualified_name());
1306   }
1307 }; // end struct var_diff_sptr_comp
1308 
1309 /// The type of the private data of corpus_diff::diff_stats.
1310 struct corpus_diff::diff_stats::priv
1311 {
1312   friend class corpus_diff::diff_stats;
1313 
1314   diff_context_wptr	ctxt_;
1315   size_t		num_func_removed;
1316   size_t		num_removed_func_filtered_out;
1317   size_t		num_func_added;
1318   size_t		num_added_func_filtered_out;
1319   size_t		num_func_changed;
1320   size_t		num_changed_func_filtered_out;
1321   size_t		num_func_with_virt_offset_changes;
1322   size_t		num_vars_removed;
1323   size_t		num_removed_vars_filtered_out;
1324   size_t		num_vars_added;
1325   size_t		num_added_vars_filtered_out;
1326   size_t		num_vars_changed;
1327   size_t		num_changed_vars_filtered_out;
1328   size_t		num_func_syms_removed;
1329   size_t		num_removed_func_syms_filtered_out;
1330   size_t		num_func_syms_added;
1331   size_t		num_added_func_syms_filtered_out;
1332   size_t		num_var_syms_removed;
1333   size_t		num_removed_var_syms_filtered_out;
1334   size_t		num_var_syms_added;
1335   size_t		num_added_var_syms_filtered_out;
1336   size_t		num_leaf_changes;
1337   size_t		num_leaf_changes_filtered_out;
1338   size_t		num_leaf_type_changes;
1339   size_t		num_leaf_type_changes_filtered_out;
1340   size_t		num_leaf_func_changes;
1341   size_t		num_leaf_func_changes_filtered_out;
1342   size_t		num_leaf_var_changes;
1343   size_t		num_leaf_var_changes_filtered_out;
1344   size_t		num_added_unreachable_types;
1345   size_t		num_added_unreachable_types_filtered_out;
1346   size_t		num_removed_unreachable_types;
1347   size_t		num_removed_unreachable_types_filtered_out;
1348   size_t		num_changed_unreachable_types;
1349   size_t		num_changed_unreachable_types_filtered_out;
1350 
privpriv1351   priv(diff_context_sptr ctxt)
1352     : ctxt_(ctxt),
1353       num_func_removed(),
1354       num_removed_func_filtered_out(),
1355       num_func_added(),
1356       num_added_func_filtered_out(),
1357       num_func_changed(),
1358       num_changed_func_filtered_out(),
1359       num_func_with_virt_offset_changes(),
1360       num_vars_removed(),
1361       num_removed_vars_filtered_out(),
1362       num_vars_added(),
1363       num_added_vars_filtered_out(),
1364       num_vars_changed(),
1365       num_changed_vars_filtered_out(),
1366       num_func_syms_removed(),
1367       num_removed_func_syms_filtered_out(),
1368       num_func_syms_added(),
1369       num_added_func_syms_filtered_out(),
1370       num_var_syms_removed(),
1371       num_removed_var_syms_filtered_out(),
1372       num_var_syms_added(),
1373       num_added_var_syms_filtered_out(),
1374       num_leaf_changes(),
1375       num_leaf_changes_filtered_out(),
1376       num_leaf_type_changes(),
1377       num_leaf_type_changes_filtered_out(),
1378       num_leaf_func_changes(),
1379       num_leaf_func_changes_filtered_out(),
1380       num_leaf_var_changes(),
1381       num_leaf_var_changes_filtered_out(),
1382       num_added_unreachable_types(),
1383       num_added_unreachable_types_filtered_out(),
1384       num_removed_unreachable_types(),
1385       num_removed_unreachable_types_filtered_out(),
1386       num_changed_unreachable_types(),
1387       num_changed_unreachable_types_filtered_out()
1388   {}
1389 
1390   diff_context_sptr
ctxtpriv1391   ctxt()
1392   {return ctxt_.lock();}
1393 }; // end class corpus_diff::diff_stats::priv
1394 
1395 void
1396 sort_enumerators(const string_enumerator_map& enumerators_map,
1397 		 enum_type_decl::enumerators& sorted);
1398 
1399 void
1400 sort_changed_enumerators(const string_changed_enumerator_map& enumerators_map,
1401 			 changed_enumerators_type& sorted);
1402 
1403 void
1404 sort_data_members(const string_decl_base_sptr_map &data_members,
1405 		  vector<decl_base_sptr>& sorted);
1406 
1407 void
1408 sort_changed_data_members(changed_var_sptrs_type& input);
1409 
1410 void
1411 sort_string_function_ptr_map(const string_function_ptr_map& map,
1412 			     vector<function_decl*>& sorted);
1413 
1414 void
1415 sort_string_member_function_sptr_map(const string_member_function_sptr_map& map,
1416 				     class_or_union::member_functions& sorted);
1417 
1418 void
1419 sort_string_type_base_sptr_map(string_type_base_sptr_map& map,
1420 			       vector<type_base_sptr>& sorted);
1421 
1422 void
1423 sort_string_function_decl_diff_sptr_map
1424 (const string_function_decl_diff_sptr_map& map,
1425  function_decl_diff_sptrs_type& sorted);
1426 
1427 void
1428 sort_string_var_diff_sptr_map(const string_var_diff_sptr_map& map,
1429 			      var_diff_sptrs_type& sorted);
1430 
1431 void
1432 sort_string_elf_symbol_map(const string_elf_symbol_map& map,
1433 			   vector<elf_symbol_sptr>& sorted);
1434 
1435 void
1436 sort_string_var_ptr_map(const string_var_ptr_map& map,
1437 			vector<var_decl*>& sorted);
1438 
1439 void
1440 sort_string_data_member_diff_sptr_map(const string_var_diff_sptr_map& map,
1441 				      var_diff_sptrs_type& sorted);
1442 
1443 void
1444 sort_unsigned_data_member_diff_sptr_map(const unsigned_var_diff_sptr_map map,
1445 					var_diff_sptrs_type& sorted);
1446 
1447 void
1448 sort_string_virtual_member_function_diff_sptr_map
1449 (const string_function_decl_diff_sptr_map& map,
1450  function_decl_diff_sptrs_type& sorted);
1451 
1452 void
1453 sort_string_diff_sptr_map(const string_diff_sptr_map& map,
1454 			  diff_sptrs_type& sorted);
1455 
1456 void
1457 sort_string_diff_ptr_map(const string_diff_ptr_map& map,
1458 			 diff_ptrs_type& sorted);
1459 
1460 void
1461 sort_string_base_diff_sptr_map(const string_base_diff_sptr_map& map,
1462 			       base_diff_sptrs_type& sorted);
1463 
1464 void
1465 sort_string_base_sptr_map(const string_base_sptr_map& m,
1466 			  class_decl::base_specs& sorted);
1467 
1468 void
1469 sort_string_fn_parm_diff_sptr_map(const unsigned_fn_parm_diff_sptr_map& map,
1470 				  vector<fn_parm_diff_sptr>&		sorted);
1471 void
1472 sort_string_fn_parm_diff_sptr_map(const string_fn_parm_diff_sptr_map&	map,
1473 				  vector<fn_parm_diff_sptr>&		sorted);
1474 void
1475 sort_string_parm_map(const string_parm_map& map,
1476 		     vector<function_decl::parameter_sptr>& sorted);
1477 
1478 void
1479 sort_artifacts_set(const artifact_sptr_set_type& set,
1480 		   vector<type_or_decl_base_sptr>& sorted);
1481 
1482 type_base_sptr
1483 get_leaf_type(qualified_type_def_sptr t);
1484 
1485 diff*
1486 get_fn_decl_or_var_decl_diff_ancestor(const diff *);
1487 
1488 bool
1489 is_diff_of_global_decls(const diff*);
1490 
1491 } // end namespace comparison
1492 
1493 } // namespace abigail
1494 
1495 #endif // __ABG_COMPARISON_PRIV_H__
1496