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 show_syms_unreferenced_by_di_; 201 bool show_added_syms_unreferenced_by_di_; 202 bool show_unreachable_types_; 203 bool show_impacted_interfaces_; 204 bool dump_diff_tree_; 205 privpriv206 priv() 207 : allowed_category_(EVERYTHING_CATEGORY), 208 reporter_(), 209 default_output_stream_(), 210 error_output_stream_(), 211 leaf_changes_only_(), 212 forbid_visiting_a_node_twice_(true), 213 reset_visited_diffs_for_each_interface_(), 214 hex_values_(), 215 show_offsets_sizes_in_bits_(true), 216 show_relative_offset_changes_(true), 217 show_stats_only_(false), 218 show_soname_change_(true), 219 show_architecture_change_(true), 220 show_deleted_fns_(true), 221 show_changed_fns_(true), 222 show_added_fns_(true), 223 show_deleted_vars_(true), 224 show_changed_vars_(true), 225 show_added_vars_(true), 226 show_linkage_names_(false), 227 show_locs_(true), 228 show_redundant_changes_(true), 229 show_syms_unreferenced_by_di_(true), 230 show_added_syms_unreferenced_by_di_(true), 231 show_unreachable_types_(false), 232 show_impacted_interfaces_(true), 233 dump_diff_tree_() 234 {} 235 };// end struct diff_context::priv 236 237 struct type_diff_base::priv 238 { 239 public: 240 friend class type_diff_base; 241 }; // end class type_diff_base 242 243 /// Private data for the @ref diff type. The details of generic view 244 /// of the diff node are expressed here. 245 struct diff::priv 246 { 247 bool finished_; 248 bool traversing_; 249 type_or_decl_base_sptr first_subject_; 250 type_or_decl_base_sptr second_subject_; 251 vector<diff*> children_; 252 diff* parent_; 253 diff* parent_interface_; 254 diff* canonical_diff_; 255 diff_context_wptr ctxt_; 256 diff_category local_category_; 257 diff_category category_; 258 mutable bool reported_once_; 259 mutable bool currently_reporting_; 260 mutable string pretty_representation_; 261 262 priv(); 263 264 public: 265 privpriv266 priv(type_or_decl_base_sptr first_subject, 267 type_or_decl_base_sptr second_subject, 268 diff_context_sptr ctxt, 269 diff_category category, 270 bool reported_once, 271 bool currently_reporting) 272 : finished_(), 273 traversing_(), 274 first_subject_(first_subject), 275 second_subject_(second_subject), 276 parent_(), 277 parent_interface_(), 278 canonical_diff_(), 279 ctxt_(ctxt), 280 local_category_(category), 281 category_(category), 282 reported_once_(reported_once), 283 currently_reporting_(currently_reporting) 284 {} 285 286 /// Getter of the diff context associated with this diff. 287 /// 288 /// @returnt a smart pointer to the diff context. 289 diff_context_sptr get_contextpriv290 get_context() const 291 {return ctxt_.lock();} 292 293 /// Check if a given categorization of a diff node should make it be 294 /// filtered out. 295 /// 296 /// @param category the categorization to take into account. 297 bool is_filtered_outpriv298 is_filtered_out(diff_category category) 299 { 300 diff_context_sptr ctxt = get_context(); 301 if (!ctxt) 302 return false; 303 304 if (ctxt->get_allowed_category() == EVERYTHING_CATEGORY) 305 return false; 306 307 /// We don't want to display nodes suppressed by a user-provided 308 /// suppression specification or by a "private type" suppression 309 /// specification. 310 if (category & (SUPPRESSED_CATEGORY | PRIVATE_TYPE_CATEGORY)) 311 return true; 312 313 // We don't want to display redundant diff nodes, when the user 314 // asked to avoid seeing redundant diff nodes. 315 if (!ctxt->show_redundant_changes() 316 && (category & REDUNDANT_CATEGORY)) 317 return true; 318 319 if (category == NO_CHANGE_CATEGORY) 320 return false; 321 322 // Ignore the REDUNDANT_CATEGORY bit when comparing allowed 323 // categories and the current set of categories. 324 return !((category & ~REDUNDANT_CATEGORY) 325 & (ctxt->get_allowed_category() 326 & ~REDUNDANT_CATEGORY)); 327 } 328 };// end class diff::priv 329 330 /// A functor to compare two instances of @ref diff_sptr. 331 struct diff_less_than_functor 332 { 333 /// An operator that takes two instances of @ref diff_sptr returns 334 /// true if its first operand compares less than its second operand. 335 /// 336 /// @param l the first operand to consider. 337 /// 338 /// @param r the second operand to consider. 339 /// 340 /// @return true if @p l compares less than @p r. 341 bool operatordiff_less_than_functor342 operator()(const diff* l, const diff* r) const 343 { 344 if (!l || !r || !l->first_subject() || !r->first_subject()) 345 return false; 346 347 string l_qn = get_name(l->first_subject()); 348 string r_qn = get_name(r->first_subject()); 349 350 return l_qn < r_qn; 351 } 352 353 /// An operator that takes two instances of @ref diff_sptr returns 354 /// true if its first operand compares less than its second operand. 355 /// 356 /// @param l the first operand to consider. 357 /// 358 /// @param r the second operand to consider. 359 /// 360 /// @return true if @p l compares less than @p r. 361 bool operatordiff_less_than_functor362 operator()(const diff_sptr& l, const diff_sptr& r) const 363 {return operator()(l.get(), r.get());} 364 }; // end struct diff_less_than_functor 365 366 struct decl_diff_base::priv 367 { 368 public: 369 friend class decl_diff_base; 370 };//end class priv 371 372 /// The private data structure for @ref distinct_diff. 373 struct distinct_diff::priv 374 { 375 diff_sptr compatible_child_diff; 376 };// end struct distinct_diff 377 378 /// The internal type for the impl idiom implementation of @ref 379 /// var_diff. 380 struct var_diff::priv 381 { 382 diff_wptr type_diff_; 383 };//end struct var_diff 384 385 /// The internal type for the impl idiom implementation of @ref 386 /// pointer_diff. 387 struct pointer_diff::priv 388 { 389 diff_sptr underlying_type_diff_; 390 privpriv391 priv(diff_sptr ud) 392 : underlying_type_diff_(ud) 393 {} 394 };//end struct pointer_diff::priv 395 396 struct array_diff::priv 397 { 398 /// The diff between the two array element types. 399 diff_sptr element_type_diff_; 400 privpriv401 priv(diff_sptr element_type_diff) 402 : element_type_diff_(element_type_diff) 403 {} 404 };//end struct array_diff::priv 405 406 struct reference_diff::priv 407 { 408 diff_sptr underlying_type_diff_; privpriv409 priv(diff_sptr underlying) 410 : underlying_type_diff_(underlying) 411 {} 412 };//end struct reference_diff::priv 413 414 struct qualified_type_diff::priv 415 { 416 diff_sptr underlying_type_diff; 417 mutable diff_sptr leaf_underlying_type_diff; 418 privpriv419 priv(diff_sptr underlying) 420 : underlying_type_diff(underlying) 421 {} 422 };// end struct qualified_type_diff::priv 423 424 struct enum_diff::priv 425 { 426 diff_sptr underlying_type_diff_; 427 edit_script enumerators_changes_; 428 string_enumerator_map deleted_enumerators_; 429 string_enumerator_map inserted_enumerators_; 430 string_changed_enumerator_map changed_enumerators_; 431 privpriv432 priv(diff_sptr underlying) 433 : underlying_type_diff_(underlying) 434 {} 435 };//end struct enum_diff::priv 436 437 /// A functor to compare two enumerators based on their value. This 438 /// implements the "less than" operator. 439 struct enumerator_value_comp 440 { 441 bool operatorenumerator_value_comp442 operator()(const enum_type_decl::enumerator& f, 443 const enum_type_decl::enumerator& s) const 444 {return f.get_value() < s.get_value();} 445 };//end struct enumerator_value_comp 446 447 /// A functor to compare two changed enumerators, based on their 448 /// initial value. 449 struct changed_enumerator_comp 450 { 451 bool operatorchanged_enumerator_comp452 operator()(const changed_enumerator& f, 453 const changed_enumerator& s) const 454 {return f.first.get_value() < s.first.get_value();} 455 };// end struct changed_enumerator_comp. 456 457 /// The type of private data of @ref class_or_union_diff. 458 struct class_or_union_diff::priv 459 { 460 edit_script member_types_changes_; 461 edit_script data_members_changes_; 462 edit_script member_fns_changes_; 463 edit_script member_fn_tmpls_changes_; 464 edit_script member_class_tmpls_changes_; 465 466 string_decl_base_sptr_map deleted_member_types_; 467 string_decl_base_sptr_map inserted_member_types_; 468 string_diff_sptr_map changed_member_types_; 469 diff_sptrs_type sorted_changed_member_types_; 470 string_decl_base_sptr_map deleted_data_members_; 471 unsigned_decl_base_sptr_map deleted_dm_by_offset_; 472 string_decl_base_sptr_map inserted_data_members_; 473 unsigned_decl_base_sptr_map inserted_dm_by_offset_; 474 // This map contains the data member which sub-type changed. 475 string_var_diff_sptr_map subtype_changed_dm_; 476 var_diff_sptrs_type sorted_subtype_changed_dm_; 477 // This one contains the list of data members changes that can be 478 // represented as a data member foo that got removed from offset N, 479 // and a data member bar that got inserted at offset N; IOW, this 480 // can be translated as data member foo that got changed into data 481 // member bar at offset N. 482 unsigned_var_diff_sptr_map changed_dm_; 483 var_diff_sptrs_type sorted_changed_dm_; 484 485 // This is a data structure to represent data members that have been 486 // replaced by anonymous data members. It's a map that associates 487 // the name of the data member to the anonymous data member that 488 // replaced it. 489 string_decl_base_sptr_map dms_replaced_by_adms_; 490 mutable changed_var_sptrs_type dms_replaced_by_adms_ordered_; 491 string_member_function_sptr_map deleted_member_functions_; 492 class_or_union::member_functions sorted_deleted_member_functions_; 493 string_member_function_sptr_map inserted_member_functions_; 494 class_or_union::member_functions sorted_inserted_member_functions_; 495 string_function_decl_diff_sptr_map changed_member_functions_; 496 function_decl_diff_sptrs_type sorted_changed_member_functions_; 497 string_decl_base_sptr_map deleted_member_class_tmpls_; 498 string_decl_base_sptr_map inserted_member_class_tmpls_; 499 string_diff_sptr_map changed_member_class_tmpls_; 500 diff_sptrs_type sorted_changed_member_class_tmpls_; 501 502 type_or_decl_base_sptr 503 member_type_has_changed(decl_base_sptr) const; 504 505 decl_base_sptr 506 subtype_changed_dm(decl_base_sptr) const; 507 508 decl_base_sptr 509 member_class_tmpl_has_changed(decl_base_sptr) const; 510 511 size_t 512 get_deleted_non_static_data_members_number() const; 513 514 size_t 515 get_inserted_non_static_data_members_number() const; 516 517 size_t 518 count_filtered_subtype_changed_dm(bool local_only = false); 519 520 size_t 521 count_filtered_changed_dm(bool local_only = false); 522 523 size_t 524 count_filtered_changed_mem_fns(const diff_context_sptr&); 525 526 size_t 527 count_filtered_inserted_mem_fns(const diff_context_sptr&); 528 529 size_t 530 count_filtered_deleted_mem_fns(const diff_context_sptr&); 531 privpriv532 priv() 533 {} 534 }; // end struct class_or_union_diff::priv 535 536 /// A comparison functor to compare two data members based on their 537 /// offset. 538 struct data_member_comp 539 { 540 541 /// Compare two data members. 542 /// 543 /// First look at their offset and then their name. 544 /// 545 /// @parm first_dm the first data member to consider. 546 /// 547 /// @param second_dm the second data member to consider. 548 bool compare_data_membersdata_member_comp549 compare_data_members(const var_decl_sptr& first_dm, 550 const var_decl_sptr& second_dm) const 551 { 552 ABG_ASSERT(first_dm); 553 ABG_ASSERT(second_dm); 554 555 size_t first_offset = get_data_member_offset(first_dm); 556 size_t second_offset = get_data_member_offset(second_dm); 557 558 // The data member at the smallest offset comes first. 559 if (first_offset != second_offset) 560 return first_offset < second_offset; 561 562 string first_dm_name = first_dm->get_name(); 563 string second_dm_name = second_dm->get_name(); 564 565 // But in case the two data members are at the same offset, then 566 // sort them lexicographically. 567 return first_dm_name < second_dm_name; 568 } 569 570 /// Compare two data members. 571 /// 572 /// First look at their offset and then their name. 573 /// 574 /// @parm first_dm the first data member to consider. 575 /// 576 /// @param second_dm the second data member to consider. 577 bool operatordata_member_comp578 operator()(const decl_base_sptr& f, 579 const decl_base_sptr& s) const 580 { 581 var_decl_sptr first_dm = is_data_member(f); 582 var_decl_sptr second_dm = is_data_member(s); 583 584 return compare_data_members(first_dm, second_dm); 585 } 586 587 /// Compare two data members. 588 /// 589 /// First look at their offset and then their name. 590 /// 591 /// @parm first_dm the first data member to consider. 592 /// 593 /// @param second_dm the second data member to consider. 594 bool operatordata_member_comp595 operator()(const changed_var_sptr& f, 596 const changed_var_sptr& s) const 597 { 598 var_decl_sptr first_dm = is_data_member(is_decl(f.first)); 599 var_decl_sptr second_dm = is_data_member(is_decl(s.first)); 600 601 return compare_data_members(first_dm, second_dm); 602 } 603 };//end struct data_member_comp 604 605 /// The type of the private data (pimpl sub-object) of the @ref 606 /// class_diff type. 607 struct class_diff::priv 608 { 609 edit_script base_changes_; 610 string_base_sptr_map deleted_bases_; 611 class_decl::base_specs sorted_deleted_bases_; 612 string_base_sptr_map inserted_bases_; 613 class_decl::base_specs sorted_inserted_bases_; 614 string_base_diff_sptr_map changed_bases_; 615 base_diff_sptrs_type sorted_changed_bases_; 616 vector<class_decl::base_spec_sptr> moved_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