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