1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2017-2020 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   suppressions_type			suppressions_;
178   pointer_map				visited_diff_nodes_;
179   corpus_diff_sptr			corpus_diff_;
180   ostream*				default_output_stream_;
181   ostream*				error_output_stream_;
182   bool					leaf_changes_only_;
183   bool					forbid_visiting_a_node_twice_;
184   bool					reset_visited_diffs_for_each_interface_;
185   bool					hex_values_;
186   bool					show_offsets_sizes_in_bits_;
187   bool					show_relative_offset_changes_;
188   bool					show_stats_only_;
189   bool					show_soname_change_;
190   bool					show_architecture_change_;
191   bool					show_deleted_fns_;
192   bool					show_changed_fns_;
193   bool					show_added_fns_;
194   bool					show_deleted_vars_;
195   bool					show_changed_vars_;
196   bool					show_added_vars_;
197   bool					show_linkage_names_;
198   bool					show_locs_;
199   bool					show_redundant_changes_;
200   bool					flag_indirect_changes_;
201   bool					show_syms_unreferenced_by_di_;
202   bool					show_added_syms_unreferenced_by_di_;
203   bool					show_unreachable_types_;
204   bool					show_impacted_interfaces_;
205   bool					dump_diff_tree_;
206 
privpriv207   priv()
208     : allowed_category_(EVERYTHING_CATEGORY),
209       reporter_(),
210       default_output_stream_(),
211       error_output_stream_(),
212       leaf_changes_only_(),
213       forbid_visiting_a_node_twice_(true),
214       reset_visited_diffs_for_each_interface_(),
215       hex_values_(),
216       show_offsets_sizes_in_bits_(true),
217       show_relative_offset_changes_(true),
218       show_stats_only_(false),
219       show_soname_change_(true),
220       show_architecture_change_(true),
221       show_deleted_fns_(true),
222       show_changed_fns_(true),
223       show_added_fns_(true),
224       show_deleted_vars_(true),
225       show_changed_vars_(true),
226       show_added_vars_(true),
227       show_linkage_names_(false),
228       show_locs_(true),
229       show_redundant_changes_(true),
230       flag_indirect_changes_(false),
231       show_syms_unreferenced_by_di_(true),
232       show_added_syms_unreferenced_by_di_(true),
233       show_unreachable_types_(false),
234       show_impacted_interfaces_(true),
235       dump_diff_tree_()
236    {}
237 };// end struct diff_context::priv
238 
239 struct type_diff_base::priv
240 {
241 public:
242   friend class type_diff_base;
243 }; // end class type_diff_base
244 
245 /// Private data for the @ref diff type.
246 struct diff::priv
247 {
248   bool				finished_;
249   bool				traversing_;
250   type_or_decl_base_sptr	first_subject_;
251   type_or_decl_base_sptr	second_subject_;
252   vector<diff*>		children_;
253   diff*			parent_;
254   diff*			parent_interface_;
255   diff*			canonical_diff_;
256   diff_context_wptr		ctxt_;
257   diff_category		local_category_;
258   diff_category		category_;
259   mutable bool			reported_once_;
260   mutable bool			currently_reporting_;
261   mutable string		pretty_representation_;
262 
263   priv();
264 
265 public:
266 
privpriv267   priv(type_or_decl_base_sptr first_subject,
268        type_or_decl_base_sptr second_subject,
269        diff_context_sptr ctxt,
270        diff_category category,
271        bool reported_once,
272        bool currently_reporting)
273     : finished_(),
274       traversing_(),
275       first_subject_(first_subject),
276       second_subject_(second_subject),
277       parent_(),
278       parent_interface_(),
279       canonical_diff_(),
280       ctxt_(ctxt),
281       local_category_(category),
282       category_(category),
283       reported_once_(reported_once),
284       currently_reporting_(currently_reporting)
285   {}
286 
287   /// Getter of the diff context associated with this diff.
288   ///
289   /// @returnt a smart pointer to the diff context.
290   diff_context_sptr
get_contextpriv291   get_context() const
292   {return ctxt_.lock();}
293 
294   /// Check if a given categorization of a diff node should make it be
295   /// filtered out.
296   ///
297   /// @param category the categorization to take into account.
298   bool
is_filtered_outpriv299   is_filtered_out(diff_category category)
300   {
301     diff_context_sptr ctxt = get_context();
302     if (!ctxt)
303       return false;
304 
305     if (ctxt->get_allowed_category() == EVERYTHING_CATEGORY)
306       return false;
307 
308   /// We don't want to display nodes suppressed by a user-provided
309   /// suppression specification or by a "private type" suppression
310   /// specification.
311     if (category & (SUPPRESSED_CATEGORY | PRIVATE_TYPE_CATEGORY))
312     return true;
313 
314   // We don't want to display redundant diff nodes, when the user
315   // asked to avoid seeing redundant diff nodes.
316   if (!ctxt->show_redundant_changes()
317       && (category & REDUNDANT_CATEGORY))
318     return true;
319 
320   if (category == NO_CHANGE_CATEGORY)
321     return false;
322 
323   // Ignore the REDUNDANT_CATEGORY bit when comparing allowed
324   // categories and the current set of categories.
325   return !((category & ~REDUNDANT_CATEGORY)
326 	   & (ctxt->get_allowed_category()
327 	      & ~REDUNDANT_CATEGORY));
328   }
329 };// end class diff::priv
330 
331 /// A functor to compare two instances of @ref diff_sptr.
332 struct diff_less_than_functor
333 {
334   /// An operator that takes two instances of @ref diff_sptr returns
335   /// true if its first operand compares less than its second operand.
336   ///
337   /// @param l the first operand to consider.
338   ///
339   /// @param r the second operand to consider.
340   ///
341   /// @return true if @p l compares less than @p r.
342   bool
operatordiff_less_than_functor343   operator()(const diff* l, const diff* r) const
344   {
345     if (!l || !r || !l->first_subject() || !r->first_subject())
346       return false;
347 
348     string l_qn = get_name(l->first_subject());
349     string r_qn = get_name(r->first_subject());
350 
351     return l_qn < r_qn;
352   }
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_sptr& l, const diff_sptr& r) const
364   {return operator()(l.get(), r.get());}
365 }; // end struct diff_less_than_functor
366 
367 struct decl_diff_base::priv
368 {
369 public:
370   friend class decl_diff_base;
371 };//end class priv
372 
373 /// The private data structure for @ref distinct_diff.
374 struct distinct_diff::priv
375 {
376   diff_sptr compatible_child_diff;
377 };// end struct distinct_diff
378 
379 /// The internal type for the impl idiom implementation of @ref
380 /// var_diff.
381 struct var_diff::priv
382 {
383   diff_wptr type_diff_;
384 };//end struct var_diff
385 
386 /// The internal type for the impl idiom implementation of @ref
387 /// pointer_diff.
388 struct pointer_diff::priv
389 {
390   diff_sptr underlying_type_diff_;
391 
privpriv392   priv(diff_sptr ud)
393     : underlying_type_diff_(ud)
394   {}
395 };//end struct pointer_diff::priv
396 
397 struct array_diff::priv
398 {
399   /// The diff between the two array element types.
400   diff_sptr element_type_diff_;
401 
privpriv402   priv(diff_sptr element_type_diff)
403     : element_type_diff_(element_type_diff)
404   {}
405 };//end struct array_diff::priv
406 
407 struct reference_diff::priv
408 {
409   diff_sptr underlying_type_diff_;
privpriv410   priv(diff_sptr underlying)
411     : underlying_type_diff_(underlying)
412   {}
413 };//end struct reference_diff::priv
414 
415 struct qualified_type_diff::priv
416 {
417   diff_sptr underlying_type_diff;
418   mutable diff_sptr leaf_underlying_type_diff;
419 
privpriv420   priv(diff_sptr underlying)
421     : underlying_type_diff(underlying)
422   {}
423 };// end struct qualified_type_diff::priv
424 
425 struct enum_diff::priv
426 {
427   diff_sptr underlying_type_diff_;
428   edit_script enumerators_changes_;
429   string_enumerator_map deleted_enumerators_;
430   string_enumerator_map inserted_enumerators_;
431   string_changed_enumerator_map changed_enumerators_;
432 
privpriv433   priv(diff_sptr underlying)
434     : underlying_type_diff_(underlying)
435   {}
436 };//end struct enum_diff::priv
437 
438 /// A functor to compare two enumerators based on their value.  This
439 /// implements the "less than" operator.
440 struct enumerator_value_comp
441 {
442   bool
operatorenumerator_value_comp443   operator()(const enum_type_decl::enumerator& f,
444 	     const enum_type_decl::enumerator& s) const
445   {return f.get_value() < s.get_value();}
446 };//end struct enumerator_value_comp
447 
448 /// A functor to compare two changed enumerators, based on their
449 /// initial value.
450 struct changed_enumerator_comp
451 {
452   bool
operatorchanged_enumerator_comp453   operator()(const changed_enumerator& f,
454 	     const changed_enumerator& s) const
455   {return f.first.get_value() < s.first.get_value();}
456 };// end struct changed_enumerator_comp.
457 
458 /// The type of private data of @ref class_or_union_diff.
459 struct class_or_union_diff::priv
460 {
461   edit_script member_types_changes_;
462   edit_script data_members_changes_;
463   edit_script member_fns_changes_;
464   edit_script member_fn_tmpls_changes_;
465   edit_script member_class_tmpls_changes_;
466 
467   string_decl_base_sptr_map deleted_member_types_;
468   string_decl_base_sptr_map inserted_member_types_;
469   string_diff_sptr_map changed_member_types_;
470   diff_sptrs_type sorted_changed_member_types_;
471   string_decl_base_sptr_map deleted_data_members_;
472   unsigned_decl_base_sptr_map deleted_dm_by_offset_;
473   string_decl_base_sptr_map inserted_data_members_;
474   unsigned_decl_base_sptr_map inserted_dm_by_offset_;
475   // This map contains the data member which sub-type changed.
476   string_var_diff_sptr_map subtype_changed_dm_;
477   var_diff_sptrs_type sorted_subtype_changed_dm_;
478   // This one contains the list of data members changes that can be
479   // represented as a data member foo that got removed from offset N,
480   // and a data member bar that got inserted at offset N; IOW, this
481   // can be translated as data member foo that got changed into data
482   // member bar at offset N.
483   unsigned_var_diff_sptr_map changed_dm_;
484   var_diff_sptrs_type sorted_changed_dm_;
485 
486   // This is a data structure to represent data members that have been
487   // replaced by anonymous data members.  It's a map that associates
488   // the name of the data member to the anonymous data member that
489   // replaced it.
490   string_decl_base_sptr_map dms_replaced_by_adms_;
491   mutable changed_var_sptrs_type dms_replaced_by_adms_ordered_;
492   string_member_function_sptr_map deleted_member_functions_;
493   class_or_union::member_functions sorted_deleted_member_functions_;
494   string_member_function_sptr_map inserted_member_functions_;
495   class_or_union::member_functions sorted_inserted_member_functions_;
496   string_function_decl_diff_sptr_map changed_member_functions_;
497   function_decl_diff_sptrs_type sorted_changed_member_functions_;
498   string_decl_base_sptr_map deleted_member_class_tmpls_;
499   string_decl_base_sptr_map inserted_member_class_tmpls_;
500   string_diff_sptr_map changed_member_class_tmpls_;
501   diff_sptrs_type sorted_changed_member_class_tmpls_;
502 
503   type_or_decl_base_sptr
504   member_type_has_changed(decl_base_sptr) const;
505 
506   decl_base_sptr
507   subtype_changed_dm(decl_base_sptr) const;
508 
509   decl_base_sptr
510   member_class_tmpl_has_changed(decl_base_sptr) const;
511 
512   size_t
513   get_deleted_non_static_data_members_number() const;
514 
515   size_t
516   get_inserted_non_static_data_members_number() const;
517 
518   size_t
519   count_filtered_subtype_changed_dm(bool local_only = false);
520 
521   size_t
522   count_filtered_changed_dm(bool local_only = false);
523 
524   size_t
525   count_filtered_changed_mem_fns(const diff_context_sptr&);
526 
527   size_t
528   count_filtered_inserted_mem_fns(const diff_context_sptr&);
529 
530   size_t
531   count_filtered_deleted_mem_fns(const diff_context_sptr&);
532 
privpriv533   priv()
534   {}
535 }; // end struct class_or_union_diff::priv
536 
537 /// A comparison functor to compare two data members based on their
538 /// offset.
539 struct data_member_comp
540 {
541 
542   /// Compare two data members.
543   ///
544   /// First look at their offset and then their name.
545   ///
546   /// @parm first_dm the first data member to consider.
547   ///
548   /// @param second_dm the second data member to consider.
549   bool
compare_data_membersdata_member_comp550   compare_data_members(const var_decl_sptr& first_dm,
551 		       const var_decl_sptr& second_dm) const
552   {
553     ABG_ASSERT(first_dm);
554     ABG_ASSERT(second_dm);
555 
556     size_t first_offset = get_data_member_offset(first_dm);
557     size_t second_offset = get_data_member_offset(second_dm);
558 
559     // The data member at the smallest offset comes first.
560     if (first_offset != second_offset)
561       return first_offset < second_offset;
562 
563     string first_dm_name = first_dm->get_name();
564     string second_dm_name = second_dm->get_name();
565 
566     // But in case the two data members are at the same offset, then
567     // sort them lexicographically.
568     return first_dm_name < second_dm_name;
569   }
570 
571   /// Compare two data members.
572   ///
573   /// First look at their offset and then their name.
574   ///
575   /// @parm first_dm the first data member to consider.
576   ///
577   /// @param second_dm the second data member to consider.
578   bool
operatordata_member_comp579   operator()(const decl_base_sptr& f,
580 	     const decl_base_sptr& s) const
581   {
582     var_decl_sptr first_dm = is_data_member(f);
583     var_decl_sptr second_dm = is_data_member(s);
584 
585     return compare_data_members(first_dm, second_dm);
586   }
587 
588   /// Compare two data members.
589   ///
590   /// First look at their offset and then their name.
591   ///
592   /// @parm first_dm the first data member to consider.
593   ///
594   /// @param second_dm the second data member to consider.
595   bool
operatordata_member_comp596   operator()(const changed_var_sptr& f,
597 	     const changed_var_sptr& s) const
598   {
599     var_decl_sptr first_dm = is_data_member(is_decl(f.first));
600     var_decl_sptr second_dm = is_data_member(is_decl(s.first));
601 
602     return compare_data_members(first_dm, second_dm);
603   }
604 };//end struct data_member_comp
605 
606 /// The type of the private data (pimpl sub-object) of the @ref
607 /// class_diff type.
608 struct class_diff::priv
609 {
610   edit_script base_changes_;
611   string_base_sptr_map deleted_bases_;
612   class_decl::base_specs sorted_deleted_bases_;
613   string_base_sptr_map inserted_bases_;
614   class_decl::base_specs sorted_inserted_bases_;
615   string_base_diff_sptr_map changed_bases_;
616   base_diff_sptrs_type sorted_changed_bases_;
617 
618   class_decl::base_spec_sptr
619   base_has_changed(class_decl::base_spec_sptr) const;
620 
621   size_t
622   count_filtered_bases();
623 
privpriv624   priv()
625   {}
626 };//end struct class_diff::priv
627 
628 /// A functor to compare instances of @ref class_decl::base_spec.
629 struct base_spec_comp
630 {
631   bool
operatorbase_spec_comp632   operator()(const class_decl::base_spec&l,
633 	     const class_decl::base_spec&r)
634   {
635     string str1 = l.get_pretty_representation();
636     string str2 = r.get_pretty_representation();
637     return str1 < str2;
638   }
639   bool
operatorbase_spec_comp640   operator()(const class_decl::base_spec_sptr&l,
641 	     const class_decl::base_spec_sptr&r)
642   {return operator()(*l, *r);}
643 }; // end base_spec_comp
644 
645 /// A comparison function for instances of @ref base_diff.
646 struct base_diff_comp
647 {
648   bool
operatorbase_diff_comp649   operator()(const base_diff& l, const base_diff& r) const
650   {
651     class_decl::base_spec_sptr f = l.first_base(), s = r.first_base();
652     if (f->get_offset_in_bits() >= 0
653 	&& s->get_offset_in_bits() >= 0)
654       return f->get_offset_in_bits() < s->get_offset_in_bits();
655     else
656       return (f->get_base_class()->get_pretty_representation()
657 	      < s->get_base_class()->get_pretty_representation());
658   }
659 
660   bool
operatorbase_diff_comp661   operator()(const base_diff* l, const base_diff* r) const
662   {return operator()(*l, *r);}
663 
664   bool
operatorbase_diff_comp665   operator()(const base_diff_sptr l, const base_diff_sptr r) const
666   {return operator()(l.get(), r.get());}
667 }; // end struct base_diff_comp
668 
669 /// A comparison functor to compare two instances of @ref var_diff
670 /// that represent changed data members based on the offset of the
671 /// initial data members, or if equal, based on their qualified name.
672 /// If equal again, then the offset and qualified name of the new data
673 /// members are considered.
674 struct data_member_diff_comp
675 {
676   /// @param f the first change to data member to take into account
677   ///
678   /// @param s the second change to data member to take into account.
679   ///
680   /// @return true iff f is before s.
681   bool
operatordata_member_diff_comp682   operator()(const var_diff_sptr f,
683 	     const var_diff_sptr s) const
684   {
685     var_decl_sptr first_dm = f->first_var();
686     var_decl_sptr second_dm = s->first_var();
687 
688     ABG_ASSERT(is_data_member(first_dm));
689     ABG_ASSERT(is_data_member(second_dm));
690 
691     size_t off1 = get_data_member_offset(first_dm);
692     size_t off2 = get_data_member_offset(second_dm);
693 
694     if (off1 != off2)
695       return off1 < off2;
696 
697     // The two offsets of the initial data members are the same.  So
698     // lets compare the qualified name of these initial data members.
699 
700     string name1 = first_dm->get_qualified_name();
701     string name2 = second_dm->get_qualified_name();
702 
703     if (name1 != name2)
704       return name1 < name2;
705 
706     // The offsets and the qualified names of the initial data members
707     // are the same.  Let's now compare the offsets of the *new* data
708     // members.
709 
710     first_dm = f->second_var();
711     second_dm = s->second_var();
712 
713     ABG_ASSERT(is_data_member(first_dm));
714     ABG_ASSERT(is_data_member(second_dm));
715 
716     off1 = get_data_member_offset(first_dm);
717     off2 = get_data_member_offset(second_dm);
718 
719     if (off1 != off2)
720       return off1 < off2;
721 
722     // The offsets of the new data members are the same, dang!  Let's
723     // compare the qualified names of these new data members then.
724 
725     name1 = first_dm->get_qualified_name();
726     name2 = second_dm->get_qualified_name();
727 
728     return name1 < name2;
729   }
730 }; // end struct var_diff_comp
731 
732 /// A comparison functor for instances of @ref function_decl_diff that
733 /// represent changes between two virtual member functions.
734 struct virtual_member_function_diff_comp
735 {
736   bool
operatorvirtual_member_function_diff_comp737   operator()(const function_decl_diff& l,
738 	     const function_decl_diff& r) const
739   {
740     ABG_ASSERT(get_member_function_is_virtual(l.first_function_decl()));
741     ABG_ASSERT(get_member_function_is_virtual(r.first_function_decl()));
742 
743     return (get_member_function_vtable_offset(l.first_function_decl())
744 	    < get_member_function_vtable_offset(r.first_function_decl()));
745   }
746 
747   bool
operatorvirtual_member_function_diff_comp748   operator()(const function_decl_diff* l,
749 	     const function_decl_diff* r)
750   {return operator()(*l, *r);}
751 
752   bool
operatorvirtual_member_function_diff_comp753   operator()(const function_decl_diff_sptr l,
754 	     const function_decl_diff_sptr r)
755   {return operator()(l.get(), r.get());}
756 }; // end struct virtual_member_function_diff_comp
757 
758 struct base_diff::priv
759 {
760   class_diff_sptr underlying_class_diff_;
761 
privpriv762   priv(class_diff_sptr underlying)
763     : underlying_class_diff_(underlying)
764   {}
765 }; // end struct base_diff::priv
766 
767 struct scope_diff::priv
768 {
769   // The edit script built by the function compute_diff.
770   edit_script member_changes_;
771 
772   // Below are the useful lookup tables.
773   //
774   // If you add a new lookup table, please update member functions
775   // clear_lookup_tables, lookup_tables_empty and
776   // ensure_lookup_tables_built.
777 
778   // The deleted/inserted types/decls.  These basically map what is
779   // inside the member_changes_ data member.  Note that for instance,
780   // a given type T might be deleted from the first scope and added to
781   // the second scope again; this means that the type was *changed*.
782   string_decl_base_sptr_map deleted_types_;
783   string_decl_base_sptr_map deleted_decls_;
784   string_decl_base_sptr_map inserted_types_;
785   string_decl_base_sptr_map inserted_decls_;
786 
787   // The changed types/decls lookup tables.
788   //
789   // These lookup tables are populated from the lookup tables above.
790   //
791   // Note that the value stored in each of these tables is a pair
792   // containing the old decl/type and the new one.  That way it is
793   // easy to run a diff between the old decl/type and the new one.
794   //
795   // A changed type/decl is one that has been deleted from the first
796   // scope and that has been inserted into the second scope.
797   string_diff_sptr_map changed_types_;
798   diff_sptrs_type sorted_changed_types_;
799   string_diff_sptr_map changed_decls_;
800   diff_sptrs_type sorted_changed_decls_;
801 
802   // The removed types/decls lookup tables.
803   //
804   // A removed type/decl is one that has been deleted from the first
805   // scope and that has *NOT* been inserted into it again.
806   string_decl_base_sptr_map removed_types_;
807   string_decl_base_sptr_map removed_decls_;
808 
809   // The added types/decls lookup tables.
810   //
811   // An added type/decl is one that has been inserted to the first
812   // scope but that has not been deleted from it.
813   string_decl_base_sptr_map added_types_;
814   string_decl_base_sptr_map added_decls_;
815 };//end struct scope_diff::priv
816 
817 /// A comparison functor for instances of @ref diff.
818 struct diff_comp
819 {
820   /// Lexicographically compare two diff nodes.
821   ///
822   /// Compare the pretty representation of the first subjects of two
823   /// diff nodes.
824   ///
825   /// @return true iff @p l is less than @p r.
826   bool
operatordiff_comp827   operator()(const diff& l, diff& r) const
828   {
829     return (get_pretty_representation(l.first_subject(), true)
830 	    <
831 	    get_pretty_representation(r.first_subject(), true));
832   }
833 
834   /// Lexicographically compare two diff nodes.
835   ///
836   /// Compare the pretty representation of the first subjects of two
837   /// diff nodes.
838   ///
839   /// @return true iff @p l is less than @p r.
840   bool
operatordiff_comp841   operator()(const diff* l, diff* r) const
842   {return operator()(*l, *r);}
843 
844   /// Lexicographically compare two diff nodes.
845   ///
846   /// Compare the pretty representation of the first subjects of two
847   /// diff nodes.
848   ///
849   /// @return true iff @p l is less than @p r.
850   bool
operatordiff_comp851   operator()(const diff_sptr l, diff_sptr r) const
852   {return operator()(l.get(), r.get());}
853 }; // end struct diff_comp;
854 
855 struct fn_parm_diff::priv
856 {
857   mutable diff_sptr type_diff;
858 }; // end struct fn_parm_diff::priv
859 
860 struct function_type_diff::priv
861 {
862   diff_sptr	return_type_diff_;
863   edit_script	parm_changes_;
864 
865   // useful lookup tables.
866   string_parm_map			deleted_parms_;
867   vector<function_decl::parameter_sptr> sorted_deleted_parms_;
868   string_parm_map			added_parms_;
869   vector<function_decl::parameter_sptr> sorted_added_parms_;
870   // This map contains parameters sub-type changes that don't change
871   // the name of the type of the parameter.
872   string_fn_parm_diff_sptr_map		subtype_changed_parms_;
873   vector<fn_parm_diff_sptr>		sorted_subtype_changed_parms_;
874   // This map contains parameter type changes that actually change the
875   // name of the type of the parameter, but in a compatible way;
876   // otherwise, the mangling of the function would have changed (in
877   // c++ at least).
878   unsigned_fn_parm_diff_sptr_map	changed_parms_by_id_;
879   vector<fn_parm_diff_sptr>		sorted_changed_parms_by_id_;
880   unsigned_parm_map			deleted_parms_by_id_;
881   unsigned_parm_map			added_parms_by_id_;
882 
privpriv883   priv()
884   {}
885 }; // end struct function_type_diff::priv
886 
887 struct function_decl_diff::priv
888 {
889   function_type_diff_sptr type_diff_;
890 
privpriv891   priv()
892   {}
893 };// end struct function_decl_diff::priv
894 
895 /// A comparison functor to compare two instances of @ref fn_parm_diff
896 /// based on their indexes.
897 struct fn_parm_diff_comp
898 {
899   /// @param f the first diff
900   ///
901   /// @param s the second diff
902   ///
903   /// @return true if the index of @p f is less than the index of @p
904   /// s.
905   bool
operatorfn_parm_diff_comp906   operator()(const fn_parm_diff& f, const fn_parm_diff& s)
907   {return f.first_parameter()->get_index() < s.first_parameter()->get_index();}
908 
909   bool
operatorfn_parm_diff_comp910   operator()(const fn_parm_diff_sptr& f, const fn_parm_diff_sptr& s)
911   {return operator()(*f, *s);}
912 }; // end struct fn_parm_diff_comp
913 
914 /// Functor that compares two function parameters for the purpose of
915 /// sorting them.
916 struct parm_comp
917 {
918   /// Returns true iff the index of the first parameter is smaller
919   /// than the of the second parameter.
920   ///
921   /// @param l the first parameter to compare.
922   ///
923   /// @param r the second parameter to compare.
924   ///
925   /// @return true iff the index of the first parameter is smaller
926   /// than the of the second parameter.
927   bool
operatorparm_comp928   operator()(const function_decl::parameter& l,
929 	     const function_decl::parameter& r)
930   {return l.get_index() < r.get_index();}
931 
932   /// Returns true iff the index of the first parameter is smaller
933   /// than the of the second parameter.
934   ///
935   /// @param l the first parameter to compare.
936   ///
937   /// @param r the second parameter to compare.
938   ///
939   /// @return true iff the index of the first parameter is smaller
940   /// than the of the second parameter.
941   bool
operatorparm_comp942   operator()(const function_decl::parameter_sptr& l,
943 	     const function_decl::parameter_sptr& r)
944   {return operator()(*l, *r);}
945 }; // end struct parm_comp
946 
947 /// A functor to compare instances of @ref var_decl base on their
948 /// qualified names.
949 struct var_comp
950 {
951   bool
operatorvar_comp952   operator() (const var_decl& l, const var_decl& r) const
953   {
954     string name1 = l.get_qualified_name(), name2 = r.get_qualified_name();
955     return name1 < name2;
956   }
957 
958   bool
operatorvar_comp959   operator() (const var_decl* l, const var_decl* r) const
960   {return operator()(*l, *r);}
961 };// end struct var_comp
962 
963 /// A functor to compare instances of @ref elf_symbol base on their
964 /// names.
965 struct elf_symbol_comp
966 {
967   bool
operatorelf_symbol_comp968   operator()(const elf_symbol& l, const elf_symbol& r)
969   {
970     string name1 = l.get_id_string(), name2 = r.get_id_string();
971     return name1 < name2;
972   }
973 
974   bool
operatorelf_symbol_comp975   operator()(const elf_symbol* l, const elf_symbol* r)
976   {return operator()(*l, *r);}
977 
978   bool
operatorelf_symbol_comp979   operator()(const elf_symbol_sptr& l, const elf_symbol_sptr& r)
980   {return operator()(l.get(), r.get());}
981 }; //end struct elf_symbol_comp
982 
983 struct typedef_diff::priv
984 {
985   diff_sptr underlying_type_diff_;
986 
privpriv987   priv(const diff_sptr underlying_type_diff)
988     : underlying_type_diff_(underlying_type_diff)
989   {}
990 };//end struct typedef_diff::priv
991 
992 struct translation_unit_diff::priv
993 {
994   translation_unit_sptr first_;
995   translation_unit_sptr second_;
996 
privpriv997   priv(translation_unit_sptr f, translation_unit_sptr s)
998     : first_(f), second_(s)
999   {}
1000 };//end struct translation_unit_diff::priv
1001 
1002 struct corpus_diff::priv
1003 {
1004   bool					finished_;
1005   string				pretty_representation_;
1006   vector<diff*>			children_;
1007   corpus_sptr				first_;
1008   corpus_sptr				second_;
1009   diff_context_wptr			ctxt_;
1010   corpus_diff::diff_stats_sptr		diff_stats_;
1011   bool					sonames_equal_;
1012   bool					architectures_equal_;
1013   edit_script				fns_edit_script_;
1014   edit_script				vars_edit_script_;
1015   edit_script				unrefed_fn_syms_edit_script_;
1016   edit_script				unrefed_var_syms_edit_script_;
1017   string_function_ptr_map		deleted_fns_;
1018   string_function_ptr_map		suppressed_deleted_fns_;
1019   string_function_ptr_map		added_fns_;
1020   string_function_ptr_map		suppressed_added_fns_;
1021   string_function_decl_diff_sptr_map	changed_fns_map_;
1022   function_decl_diff_sptrs_type	changed_fns_;
1023   string_var_ptr_map			deleted_vars_;
1024   string_var_ptr_map			suppressed_deleted_vars_;
1025   string_var_ptr_map			added_vars_;
1026   string_var_ptr_map			suppressed_added_vars_;
1027   string_var_diff_sptr_map		changed_vars_map_;
1028   var_diff_sptrs_type			sorted_changed_vars_;
1029   string_elf_symbol_map		added_unrefed_fn_syms_;
1030   string_elf_symbol_map		suppressed_added_unrefed_fn_syms_;
1031   string_elf_symbol_map		deleted_unrefed_fn_syms_;
1032   string_elf_symbol_map		suppressed_deleted_unrefed_fn_syms_;
1033   string_elf_symbol_map		added_unrefed_var_syms_;
1034   string_elf_symbol_map		suppressed_added_unrefed_var_syms_;
1035   string_elf_symbol_map		deleted_unrefed_var_syms_;
1036   string_elf_symbol_map		suppressed_deleted_unrefed_var_syms_;
1037   edit_script				unreachable_types_edit_script_;
1038   string_type_base_sptr_map		deleted_unreachable_types_;
1039   vector<type_base_sptr>		deleted_unreachable_types_sorted_;
1040   string_type_base_sptr_map		suppressed_deleted_unreachable_types_;
1041   string_type_base_sptr_map		added_unreachable_types_;
1042   vector<type_base_sptr>		added_unreachable_types_sorted_;
1043   string_type_base_sptr_map		suppressed_added_unreachable_types_;
1044   string_diff_sptr_map			changed_unreachable_types_;
1045   mutable vector<diff_sptr>		changed_unreachable_types_sorted_;
1046   diff_maps				leaf_diffs_;
1047 
1048   /// Default constructor of corpus_diff::priv.
privpriv1049   priv()
1050     : finished_(false),
1051       sonames_equal_(false),
1052       architectures_equal_(false)
1053   {}
1054 
1055   /// Constructor of corpus_diff::priv.
1056   ///
1057   /// @param first the first corpus of this diff.
1058   ///
1059   /// @param second the second corpus of this diff.
1060   ///
1061   /// @param ctxt the context of the diff.
privpriv1062   priv(corpus_sptr first,
1063        corpus_sptr second,
1064        diff_context_sptr ctxt)
1065     : finished_(false),
1066       first_(first),
1067       second_(second),
1068       ctxt_(ctxt),
1069       sonames_equal_(false),
1070       architectures_equal_(false)
1071   {}
1072 
1073   diff_context_sptr
1074   get_context();
1075 
1076   bool
1077   lookup_tables_empty() const;
1078 
1079   void
1080   clear_lookup_tables();
1081 
1082   void
1083   ensure_lookup_tables_populated();
1084 
1085   void
1086   apply_supprs_to_added_removed_fns_vars_unreachable_types();
1087 
1088   bool
1089   deleted_function_is_suppressed(const function_decl* fn) const;
1090 
1091   bool
1092   added_function_is_suppressed(const function_decl* fn) const;
1093 
1094   bool
1095   deleted_variable_is_suppressed(const var_decl* var) const;
1096 
1097   bool
1098   added_variable_is_suppressed(const var_decl* var) const;
1099 
1100   bool
1101   added_unreachable_type_is_suppressed(const type_base *t)const ;
1102 
1103   bool
1104   deleted_unreachable_type_is_suppressed(const type_base *t)const ;
1105 
1106   bool
1107   deleted_unrefed_fn_sym_is_suppressed(const elf_symbol*) const;
1108 
1109   bool
1110   added_unrefed_fn_sym_is_suppressed(const elf_symbol*) const;
1111 
1112   bool
1113   deleted_unrefed_var_sym_is_suppressed(const elf_symbol*) const;
1114 
1115   bool
1116   added_unrefed_var_sym_is_suppressed(const elf_symbol*) const;
1117 
1118   void count_leaf_changes(size_t &num_changes, size_t &num_filtered);
1119 
1120   void count_leaf_type_changes(size_t &num_type_changes,
1121 			       size_t &num_type_changes_filtered);
1122 
1123   void count_unreachable_types(size_t &num_added,
1124 			       size_t &num_removed,
1125 			       size_t &num_changed,
1126 			       size_t &num_filtered_added,
1127 			       size_t &num_filtered_removed,
1128 			       size_t &num_filtered_changed);
1129 
1130   const vector<diff_sptr>&
1131   changed_unreachable_types_sorted() const;
1132 
1133   void
1134   apply_filters_and_compute_diff_stats(corpus_diff::diff_stats&);
1135 
1136   void
1137   emit_diff_stats(const diff_stats&	stats,
1138 		  ostream&		out,
1139 		  const string&	indent);
1140 
1141   void
1142   categorize_redundant_changed_sub_nodes();
1143 
1144   void
1145   clear_redundancy_categorization();
1146 
1147   void
1148   maybe_dump_diff_tree();
1149 }; // end corpus::priv
1150 
1151 /// "Less than" functor to compare instances of @ref function_decl.
1152 struct function_comp
1153 {
1154   /// The actual "less than" operator for instances of @ref
1155   /// function_decl.  It returns true if the first @ref function_decl
1156   /// is lest than the second one.
1157   ///
1158   /// @param f the first @ref function_decl to take in account.
1159   ///
1160   /// @param s the second @ref function_decl to take in account.
1161   ///
1162   /// @return true iff @p f is less than @p s.
1163   bool
operatorfunction_comp1164   operator()(const function_decl& f, const function_decl& s)
1165   {return abigail::ir::function_decl_is_less_than(f, s);}
1166 
1167   /// The actual "less than" operator for instances of @ref
1168   /// function_decl.  It returns true if the first @ref function_decl
1169   /// is lest than the second one.
1170   ///
1171   /// @param f the first @ref function_decl to take in account.
1172   ///
1173   /// @param s the second @ref function_decl to take in account.
1174   ///
1175   /// @return true iff @p f is less than @p s.
1176   bool
operatorfunction_comp1177   operator()(const function_decl* f, const function_decl* s)
1178   {return operator()(*f, *s);}
1179 
1180   /// The actual "less than" operator for instances of @ref
1181   /// function_decl.  It returns true if the first @ref function_decl
1182   /// is lest than the second one.
1183   ///
1184   /// @param f the first @ref function_decl to take in account.
1185   ///
1186   /// @param s the second @ref function_decl to take in account.
1187   ///
1188   /// @return true iff @p f is less than @p s.
1189   bool
operatorfunction_comp1190   operator()(const function_decl_sptr f, const function_decl_sptr s)
1191   {return operator()(f.get(), s.get());}
1192 }; // end function_comp
1193 
1194 /// A "Less Than" functor to compare instance of @ref
1195 /// function_decl_diff.
1196 struct function_decl_diff_comp
1197 {
1198   /// The actual less than operator.
1199   ///
1200   /// It returns true if the first @ref function_decl_diff is less
1201   /// than the second one.
1202   ///
1203   /// param first the first @ref function_decl_diff to consider.
1204   ///
1205   /// @param second the second @ref function_decl_diff to consider.
1206   ///
1207   /// @return true iff @p first is less than @p second.
1208   bool
operatorfunction_decl_diff_comp1209   operator()(const function_decl_diff& first,
1210 	     const function_decl_diff& second)
1211   {
1212     function_decl_sptr f = first.first_function_decl(),
1213       s = second.first_function_decl();
1214 
1215     string fr = f->get_qualified_name(),
1216       sr = s->get_qualified_name();
1217 
1218     if (fr == sr)
1219       {
1220 	if (f->get_symbol())
1221 	  fr = f->get_symbol()->get_id_string();
1222 	else if (!f->get_linkage_name().empty())
1223 	  fr = f->get_linkage_name();
1224 	else
1225 	  fr = f->get_pretty_representation();
1226 
1227 	if (s->get_symbol())
1228 	  sr = s->get_symbol()->get_id_string();
1229 	else if (!s->get_linkage_name().empty())
1230 	  sr = s->get_linkage_name();
1231 	else
1232 	  sr = s->get_pretty_representation();
1233       }
1234 
1235     return (fr.compare(sr) < 0);
1236   }
1237 
1238   /// The actual less than operator.
1239   ///
1240   /// It returns true if the first @ref function_decl_diff_sptr is
1241   /// less than the second one.
1242   ///
1243   /// param first the first @ref function_decl_diff_sptr to consider.
1244   ///
1245   /// @param second the second @ref function_decl_diff_sptr to
1246   /// consider.
1247   ///
1248   /// @return true iff @p first is less than @p second.
1249   bool
operatorfunction_decl_diff_comp1250   operator()(const function_decl_diff_sptr first,
1251 	     const function_decl_diff_sptr second)
1252   {return operator()(*first, *second);}
1253 }; // end struct function_decl_diff_comp
1254 
1255 /// Functor to sort instances of @ref var_diff_sptr
1256 struct var_diff_sptr_comp
1257 {
1258   /// Return true if the first argument is less than the second one.
1259   ///
1260   /// @param f the first argument to consider.
1261   ///
1262   /// @param s the second argument to consider.
1263   ///
1264   /// @return true if @p f is less than @p s.
1265   bool
operatorvar_diff_sptr_comp1266   operator()(const var_diff_sptr f,
1267 	     const var_diff_sptr s)
1268   {
1269     return (f->first_var()->get_qualified_name()
1270 	    < s->first_var()->get_qualified_name());
1271   }
1272 }; // end struct var_diff_sptr_comp
1273 
1274 /// The type of the private data of corpus_diff::diff_stats.
1275 struct corpus_diff::diff_stats::priv
1276 {
1277   friend class corpus_diff::diff_stats;
1278 
1279   diff_context_wptr	ctxt_;
1280   size_t		num_func_removed;
1281   size_t		num_removed_func_filtered_out;
1282   size_t		num_func_added;
1283   size_t		num_added_func_filtered_out;
1284   size_t		num_func_changed;
1285   size_t		num_changed_func_filtered_out;
1286   size_t		num_func_with_virt_offset_changes;
1287   size_t		num_vars_removed;
1288   size_t		num_removed_vars_filtered_out;
1289   size_t		num_vars_added;
1290   size_t		num_added_vars_filtered_out;
1291   size_t		num_vars_changed;
1292   size_t		num_changed_vars_filtered_out;
1293   size_t		num_func_syms_removed;
1294   size_t		num_removed_func_syms_filtered_out;
1295   size_t		num_func_syms_added;
1296   size_t		num_added_func_syms_filtered_out;
1297   size_t		num_var_syms_removed;
1298   size_t		num_removed_var_syms_filtered_out;
1299   size_t		num_var_syms_added;
1300   size_t		num_added_var_syms_filtered_out;
1301   size_t		num_leaf_changes;
1302   size_t		num_leaf_changes_filtered_out;
1303   size_t		num_leaf_type_changes;
1304   size_t		num_leaf_type_changes_filtered_out;
1305   size_t		num_leaf_func_changes;
1306   size_t		num_leaf_func_changes_filtered_out;
1307   size_t		num_leaf_var_changes;
1308   size_t		num_leaf_var_changes_filtered_out;
1309   size_t		num_added_unreachable_types;
1310   size_t		num_added_unreachable_types_filtered_out;
1311   size_t		num_removed_unreachable_types;
1312   size_t		num_removed_unreachable_types_filtered_out;
1313   size_t		num_changed_unreachable_types;
1314   size_t		num_changed_unreachable_types_filtered_out;
1315 
privpriv1316   priv(diff_context_sptr ctxt)
1317     : ctxt_(ctxt),
1318       num_func_removed(),
1319       num_removed_func_filtered_out(),
1320       num_func_added(),
1321       num_added_func_filtered_out(),
1322       num_func_changed(),
1323       num_changed_func_filtered_out(),
1324       num_func_with_virt_offset_changes(),
1325       num_vars_removed(),
1326       num_removed_vars_filtered_out(),
1327       num_vars_added(),
1328       num_added_vars_filtered_out(),
1329       num_vars_changed(),
1330       num_changed_vars_filtered_out(),
1331       num_func_syms_removed(),
1332       num_removed_func_syms_filtered_out(),
1333       num_func_syms_added(),
1334       num_added_func_syms_filtered_out(),
1335       num_var_syms_removed(),
1336       num_removed_var_syms_filtered_out(),
1337       num_var_syms_added(),
1338       num_added_var_syms_filtered_out(),
1339       num_leaf_changes(),
1340       num_leaf_changes_filtered_out(),
1341       num_leaf_type_changes(),
1342       num_leaf_type_changes_filtered_out(),
1343       num_leaf_func_changes(),
1344       num_leaf_func_changes_filtered_out(),
1345       num_leaf_var_changes(),
1346       num_leaf_var_changes_filtered_out(),
1347       num_added_unreachable_types(),
1348       num_added_unreachable_types_filtered_out(),
1349       num_removed_unreachable_types(),
1350       num_removed_unreachable_types_filtered_out(),
1351       num_changed_unreachable_types(),
1352       num_changed_unreachable_types_filtered_out()
1353   {}
1354 
1355   diff_context_sptr
ctxtpriv1356   ctxt()
1357   {return ctxt_.lock();}
1358 }; // end class corpus_diff::diff_stats::priv
1359 
1360 void
1361 sort_enumerators(const string_enumerator_map& enumerators_map,
1362 		 enum_type_decl::enumerators& sorted);
1363 
1364 void
1365 sort_changed_enumerators(const string_changed_enumerator_map& enumerators_map,
1366 			 changed_enumerators_type& sorted);
1367 
1368 void
1369 sort_data_members(const string_decl_base_sptr_map &data_members,
1370 		  vector<decl_base_sptr>& sorted);
1371 
1372 void
1373 sort_changed_data_members(changed_var_sptrs_type& input);
1374 
1375 void
1376 sort_string_function_ptr_map(const string_function_ptr_map& map,
1377 			     vector<function_decl*>& sorted);
1378 
1379 void
1380 sort_string_member_function_sptr_map(const string_member_function_sptr_map& map,
1381 				     class_or_union::member_functions& sorted);
1382 
1383 void
1384 sort_string_type_base_sptr_map(string_type_base_sptr_map& map,
1385 			       vector<type_base_sptr>& sorted);
1386 
1387 void
1388 sort_string_function_decl_diff_sptr_map
1389 (const string_function_decl_diff_sptr_map& map,
1390  function_decl_diff_sptrs_type& sorted);
1391 
1392 void
1393 sort_string_var_diff_sptr_map(const string_var_diff_sptr_map& map,
1394 			      var_diff_sptrs_type& sorted);
1395 
1396 void
1397 sort_string_elf_symbol_map(const string_elf_symbol_map& map,
1398 			   vector<elf_symbol_sptr>& sorted);
1399 
1400 void
1401 sort_string_var_ptr_map(const string_var_ptr_map& map,
1402 			vector<var_decl*>& sorted);
1403 
1404 void
1405 sort_string_data_member_diff_sptr_map(const string_var_diff_sptr_map& map,
1406 				      var_diff_sptrs_type& sorted);
1407 
1408 void
1409 sort_unsigned_data_member_diff_sptr_map(const unsigned_var_diff_sptr_map map,
1410 					var_diff_sptrs_type& sorted);
1411 
1412 void
1413 sort_string_virtual_member_function_diff_sptr_map
1414 (const string_function_decl_diff_sptr_map& map,
1415  function_decl_diff_sptrs_type& sorted);
1416 
1417 void
1418 sort_string_diff_sptr_map(const string_diff_sptr_map& map,
1419 			  diff_sptrs_type& sorted);
1420 
1421 void
1422 sort_string_diff_ptr_map(const string_diff_ptr_map& map,
1423 			 diff_ptrs_type& sorted);
1424 
1425 void
1426 sort_string_base_diff_sptr_map(const string_base_diff_sptr_map& map,
1427 			       base_diff_sptrs_type& sorted);
1428 
1429 void
1430 sort_string_base_sptr_map(const string_base_sptr_map& m,
1431 			  class_decl::base_specs& sorted);
1432 
1433 void
1434 sort_string_fn_parm_diff_sptr_map(const unsigned_fn_parm_diff_sptr_map& map,
1435 				  vector<fn_parm_diff_sptr>&		sorted);
1436 void
1437 sort_string_fn_parm_diff_sptr_map(const string_fn_parm_diff_sptr_map&	map,
1438 				  vector<fn_parm_diff_sptr>&		sorted);
1439 void
1440 sort_string_parm_map(const string_parm_map& map,
1441 		     vector<function_decl::parameter_sptr>& sorted);
1442 
1443 void
1444 sort_artifacts_set(const artifact_sptr_set_type& set,
1445 		   vector<type_or_decl_base_sptr>& sorted);
1446 
1447 type_base_sptr
1448 get_leaf_type(qualified_type_def_sptr t);
1449 
1450 diff*
1451 get_fn_decl_or_var_decl_diff_ancestor(const diff *);
1452 
1453 bool
1454 is_diff_of_global_decls(const diff*);
1455 
1456 } // end namespace comparison
1457 
1458 } // namespace abigail
1459 
1460 #endif // __ABG_COMPARISON_PRIV_H__
1461