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