1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 2 // -*- Mode: C++ -*- 3 // 4 // Copyright (C) 2016-2022 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 #include <iostream> 18 19 #include "abg-ir.h" 20 #include "abg-corpus.h" 21 22 namespace abigail 23 { 24 25 namespace ir 26 { 27 28 using std::string; 29 using abg_compat::optional; 30 31 /// The result of structural comparison of type ABI artifacts. 32 enum comparison_result 33 { 34 COMPARISON_RESULT_DIFFERENT = 0, 35 COMPARISON_RESULT_EQUAL = 1, 36 COMPARISON_RESULT_CYCLE_DETECTED = 2, 37 COMPARISON_RESULT_UNKNOWN = 3, 38 }; //end enum comparison_result 39 40 /// The internal representation of an integral type. 41 /// 42 /// This is a "utility type" used internally to canonicalize the name 43 /// of fundamental integral types, so that "unsignd long" and "long 44 /// unsined int" end-up having the same name. 45 class integral_type 46 { 47 public: 48 /// The possible base types of integral types. We might have 49 /// forgotten many of these, so do not hesitate to add new ones. 50 /// 51 /// If you do add new ones, please also consider updating functions 52 /// parse_base_integral_type and integral_type::to_string. 53 enum base_type 54 { 55 /// The "int" base type. 56 INT_BASE_TYPE, 57 /// The "char" base type. 58 CHAR_BASE_TYPE, 59 /// The "bool" base type in C++ or "_Bool" in C11. 60 BOOL_BASE_TYPE, 61 /// The "double" base type. 62 DOUBLE_BASE_TYPE, 63 /// The "float" base type. 64 FLOAT_BASE_TYPE, 65 /// The "char16_t base type. 66 CHAR16_T_BASE_TYPE, 67 /// The "char32_t" base type. 68 CHAR32_T_BASE_TYPE, 69 /// The "wchar_t" base type. 70 WCHAR_T_BASE_TYPE 71 }; 72 73 /// The modifiers of the base types above. Several modifiers can be 74 /// combined for a given base type. The presence of modifiers is 75 /// usually modelled by a bitmap of modifiers. 76 /// 77 /// If you add a new modifier, please consider updating functions 78 /// parse_integral_type_modifier and integral_type::to_string. 79 enum modifiers_type 80 { 81 NO_MODIFIER = 0, 82 /// The "signed" modifier. 83 SIGNED_MODIFIER = 1, 84 /// The "unsigned" modier. 85 UNSIGNED_MODIFIER = 1 << 1, 86 /// The "short" modifier. 87 SHORT_MODIFIER = 1 << 2, 88 /// The "long" modifier. 89 LONG_MODIFIER = 1 << 3, 90 /// The "long long" modifier. 91 LONG_LONG_MODIFIER = 1 << 4 92 }; 93 94 private: 95 base_type base_; 96 modifiers_type modifiers_; 97 98 public: 99 100 integral_type(); 101 integral_type(const string& name); 102 integral_type(base_type, modifiers_type); 103 104 base_type 105 get_base_type() const; 106 107 modifiers_type 108 get_modifiers() const; 109 110 void 111 set_modifiers(modifiers_type); 112 113 bool 114 operator==(const integral_type&) const; 115 116 string 117 to_string(bool internal=false) const; 118 119 operator string() const; 120 }; // end class integral_type 121 122 integral_type::modifiers_type 123 operator|(integral_type::modifiers_type l, integral_type::modifiers_type r); 124 125 integral_type::modifiers_type 126 operator&(integral_type::modifiers_type l, integral_type::modifiers_type r); 127 128 integral_type::modifiers_type 129 operator~(integral_type::modifiers_type l); 130 131 integral_type::modifiers_type& 132 operator|=(integral_type::modifiers_type& l, integral_type::modifiers_type r); 133 134 integral_type::modifiers_type& 135 operator &=(integral_type::modifiers_type& l, integral_type::modifiers_type r); 136 137 bool 138 parse_integral_type(const string& type_name, 139 integral_type& type); 140 141 /// Private type to hold private members of @ref translation_unit 142 struct translation_unit::priv 143 { 144 const environment& env_; 145 corpus* corp; 146 bool is_constructed_; 147 char address_size_; 148 language language_; 149 std::string path_; 150 std::string comp_dir_path_; 151 std::string abs_path_; 152 location_manager loc_mgr_; 153 mutable global_scope_sptr global_scope_; 154 mutable vector<type_base_sptr> synthesized_types_; 155 vector<function_type_sptr> live_fn_types_; 156 type_maps types_; 157 158 privpriv159 priv(const environment& env) 160 : env_(env), 161 corp(), 162 is_constructed_(), 163 address_size_(), 164 language_(LANG_UNKNOWN) 165 {} 166 ~privpriv167 ~priv() 168 {} 169 170 type_maps& get_typespriv171 get_types() 172 {return types_;} 173 }; // end translation_unit::priv 174 175 // <type_base definitions> 176 177 /// Definition of the private data of @ref type_base. 178 struct type_base::priv 179 { 180 size_t size_in_bits; 181 size_t alignment_in_bits; 182 type_base_wptr canonical_type; 183 // The data member below holds the canonical type that is managed by 184 // the smart pointer referenced by the canonical_type data member 185 // above. We are storing this underlying (naked) pointer here, so 186 // that users can access it *fast*. Otherwise, accessing 187 // canonical_type above implies creating a shared_ptr, and that has 188 // been measured to be slow for some performance hot spots. 189 type_base* naked_canonical_type; 190 // Computing the representation of a type again and again can be 191 // costly. So we cache the internal and non-internal type 192 // representation strings here. 193 interned_string internal_cached_repr_; 194 interned_string cached_repr_; 195 // The next two data members are used while comparing types during 196 // canonicalization. They are useful for the "canonical type 197 // propagation" (aka on-the-fly-canonicalization) optimization 198 // implementation. 199 200 // The set of canonical recursive types this type depends on. 201 unordered_set<uintptr_t> depends_on_recursive_type_; 202 bool canonical_type_propagated_; 203 bool propagated_canonical_type_confirmed_; 204 privpriv205 priv() 206 : size_in_bits(), 207 alignment_in_bits(), 208 naked_canonical_type(), 209 canonical_type_propagated_(false), 210 propagated_canonical_type_confirmed_(false) 211 {} 212 213 priv(size_t s, 214 size_t a, 215 type_base_sptr c = type_base_sptr()) size_in_bitspriv216 : size_in_bits(s), 217 alignment_in_bits(a), 218 canonical_type(c), 219 naked_canonical_type(c.get()), 220 canonical_type_propagated_(false), 221 propagated_canonical_type_confirmed_(false) 222 {} 223 224 /// Test if the current type depends on recursive type comparison. 225 /// 226 /// A recursive type T is a type T which has a sub-type that is T 227 /// (recursively) itself. 228 /// 229 /// So this function tests if the current type has a recursive 230 /// sub-type or is a recursive type itself. 231 /// 232 /// @return true if the current type depends on a recursive type. 233 bool depends_on_recursive_typepriv234 depends_on_recursive_type() const 235 {return !depends_on_recursive_type_.empty();} 236 237 /// Test if the current type depends on a given recursive type. 238 /// 239 /// A recursive type T is a type T which has a sub-type that is T 240 /// (recursively) itself. 241 /// 242 /// So this function tests if the current type depends on a given 243 /// recursive type. 244 /// 245 /// @param dependant the type we want to test if the current type 246 /// depends on. 247 /// 248 /// @return true if the current type depends on the recursive type 249 /// @dependant. 250 bool depends_on_recursive_typepriv251 depends_on_recursive_type(const type_base* dependant) const 252 { 253 return 254 (depends_on_recursive_type_.find(reinterpret_cast<uintptr_t>(dependant)) 255 != depends_on_recursive_type_.end()); 256 } 257 258 /// Set the flag that tells if the current type depends on a given 259 /// recursive type. 260 /// 261 /// A recursive type T is a type T which has asub-type that is T 262 /// (recursively) itself. 263 /// 264 /// So this function tests if the current type depends on a 265 /// recursive type. 266 /// 267 /// @param t the recursive type that current type depends on. 268 void set_depends_on_recursive_typepriv269 set_depends_on_recursive_type(const type_base * t) 270 {depends_on_recursive_type_.insert(reinterpret_cast<uintptr_t>(t));} 271 272 /// Unset the flag that tells if the current type depends on a given 273 /// recursive type. 274 /// 275 /// A recursive type T is a type T which has asub-type that is T 276 /// (recursively) itself. 277 /// 278 /// So this function flags the current type as not being dependant 279 /// on a given recursive type. 280 /// 281 /// 282 /// @param t the recursive type to consider. 283 void set_does_not_depend_on_recursive_typepriv284 set_does_not_depend_on_recursive_type(const type_base *t) 285 {depends_on_recursive_type_.erase(reinterpret_cast<uintptr_t>(t));} 286 287 /// Flag the current type as not being dependant on any recursive type. 288 void set_does_not_depend_on_recursive_typepriv289 set_does_not_depend_on_recursive_type() 290 {depends_on_recursive_type_.clear();} 291 292 /// Test if the type carries a canonical type that is the result of 293 /// maybe_propagate_canonical_type(), aka, "canonical type 294 /// propagation optimization". 295 /// 296 /// @return true iff the current type carries a canonical type that 297 /// is the result of canonical type propagation. 298 bool canonical_type_propagatedpriv299 canonical_type_propagated() 300 {return canonical_type_propagated_;} 301 302 /// Set the flag that says if the type carries a canonical type that 303 /// is the result of maybe_propagate_canonical_type(), aka, 304 /// "canonical type propagation optimization". 305 /// 306 /// @param f true iff the current type carries a canonical type that 307 /// is the result of canonical type propagation. 308 void set_canonical_type_propagatedpriv309 set_canonical_type_propagated(bool f) 310 {canonical_type_propagated_ = f;} 311 312 /// Getter of the property propagated-canonical-type-confirmed. 313 /// 314 /// If canonical_type_propagated() returns true, then this property 315 /// says if the propagated canonical type has been confirmed or not. 316 /// If it hasn't been confirmed, then it means it can still 317 /// cancelled. 318 /// 319 /// @return true iff the propagated canonical type has been 320 /// confirmed. 321 bool propagated_canonical_type_confirmedpriv322 propagated_canonical_type_confirmed() const 323 {return propagated_canonical_type_confirmed_;} 324 325 /// Setter of the property propagated-canonical-type-confirmed. 326 /// 327 /// If canonical_type_propagated() returns true, then this property 328 /// says if the propagated canonical type has been confirmed or not. 329 /// If it hasn't been confirmed, then it means it can still 330 /// cancelled. 331 /// 332 /// @param f If this is true then the propagated canonical type has 333 /// been confirmed. 334 void set_propagated_canonical_type_confirmedpriv335 set_propagated_canonical_type_confirmed(bool f) 336 {propagated_canonical_type_confirmed_ = f;} 337 338 /// If the current canonical type was set as the result of the 339 /// "canonical type propagation optimization", then clear it. 340 void clear_propagated_canonical_typepriv341 clear_propagated_canonical_type() 342 { 343 if (canonical_type_propagated_ && !propagated_canonical_type_confirmed_) 344 { 345 canonical_type.reset(); 346 naked_canonical_type = nullptr; 347 set_canonical_type_propagated(false); 348 } 349 } 350 }; // end struct type_base::priv 351 352 // <environment definitions> 353 354 /// The hashing functor for a pair of uint64_t. 355 struct uint64_t_pair_hash 356 { 357 /// Hashing function for a pair of uint64_t. 358 /// 359 /// @param p the pair to hash. 360 uint64_t operatoruint64_t_pair_hash361 operator()(const std::pair<uint64_t, uint64_t>& p) const 362 {return abigail::hashing::combine_hashes(p.first, p.second);} 363 }; 364 365 /// A convenience typedef for a pair of uint64_t which is initially 366 /// intended to store a pair of pointer values. 367 typedef std::pair<uint64_t, uint64_t> uint64_t_pair_type; 368 369 /// A convenience typedef for a set of @ref uint64_t_pair 370 typedef unordered_set<uint64_t_pair_type, 371 uint64_t_pair_hash> uint64_t_pairs_set_type; 372 /// A convenience typedef for a map which key is a pair of uint64_t 373 /// and which value is a boolean. This is initially intended to cache 374 /// the result of comparing two (sub-)types. 375 typedef unordered_map<uint64_t_pair_type, bool, 376 uint64_t_pair_hash> type_comparison_result_type; 377 378 /// The private data of the @ref environment type. 379 struct environment::priv 380 { 381 config config_; 382 canonical_types_map_type canonical_types_; 383 mutable vector<type_base_sptr> sorted_canonical_types_; 384 type_base_sptr void_type_; 385 type_base_sptr variadic_marker_type_; 386 // The set of pairs of class types being currently compared. It's 387 // used to avoid endless loops while recursively comparing types. 388 // This should be empty when none of the 'equal' overloads are 389 // currently being invoked. 390 uint64_t_pairs_set_type classes_being_compared_; 391 // The set of pairs of function types being currently compared. It's used 392 // to avoid endless loops while recursively comparing types. This 393 // should be empty when none of the 'equal' overloads are currently 394 // being invoked. 395 uint64_t_pairs_set_type fn_types_being_compared_; 396 // This is a cache for the result of comparing two sub-types (of 397 // either class or function types) that are designated by their 398 // memory address in the IR. 399 type_comparison_result_type type_comparison_results_cache_; 400 vector<type_base_sptr> extra_live_types_; 401 interned_string_pool string_pool_; 402 // The two vectors below represent the stack of left and right 403 // operands of the current type comparison operation that is 404 // happening during type canonicalization. 405 // 406 // Basically, that stack of operand looks like below. 407 // 408 // First, suppose we have a type T_L that has two sub-types as this: 409 // 410 // T_L 411 // | 412 // +-- L_OP0 413 // | 414 // +-- L_OP1 415 // 416 // Now suppose that we have another type T_R that has two sub-types 417 // as this: 418 // 419 // T_R 420 // | 421 // +-- R_OP0 422 // | 423 // +-- R_OP1 424 // 425 // Now suppose that we compare T_L against T_R. We are going to 426 // have a stack of pair of types. Each pair of types represents 427 // two (sub) types being compared against each other. 428 // 429 // On the stack, we will thus first have the pair (T_L, T_R) 430 // being compared. Then, we will have the pair (L_OP0, R_OP0) 431 // being compared, and then the pair (L_OP1, R_OP1) being 432 // compared. Like this: 433 // 434 // | T_L | L_OP0 | L_OP1 | <-- this goes into left_type_comp_operands_; 435 // -------- ------------- 436 // | T_R | R_OP0 | R_OP1 | <-- this goes into right_type_comp_operands_; 437 // 438 // This "stack of operands of the current type comparison, during 439 // type canonicalization" is used in the context of the @ref 440 // OnTheFlyCanonicalization optimization. It's used to detect if a 441 // sub-type of the type being canonicalized depends on a recursive 442 // type. 443 vector<const type_base*> left_type_comp_operands_; 444 vector<const type_base*> right_type_comp_operands_; 445 // Vector of types that protentially received propagated canonical types. 446 // If the canonical type propagation is confirmed, the potential 447 // canonical types must be promoted as canonical types. Otherwise if 448 // the canonical type propagation is cancelled, the canonical types 449 // must be cleared. 450 pointer_set types_with_non_confirmed_propagated_ct_; 451 pointer_set recursive_types_; 452 #ifdef WITH_DEBUG_SELF_COMPARISON 453 // This is used for debugging purposes. 454 // When abidw is used with the option --debug-abidiff, some 455 // libabigail internals need to get a hold on the initial binary 456 // input of abidw, as well as as the abixml file that represents the 457 // ABI of that binary. 458 // 459 // So this one is the corpus for the input binary. 460 corpus_wptr first_self_comparison_corpus_; 461 // This one is the corpus for the ABIXML file representing the 462 // serialization of the input binary. 463 corpus_wptr second_self_comparison_corpus_; 464 // This is also used for debugging purposes, when using 465 // 'abidw --debug-abidiff <binary>'. It holds the set of mapping of 466 // an abixml (canonical) type and its type-id. 467 unordered_map<string, uintptr_t> type_id_canonical_type_map_; 468 // Likewise. It holds a map that associates the pointer to a type 469 // read from abixml and the type-id string it corresponds to. 470 unordered_map<uintptr_t, string> pointer_type_id_map_; 471 #endif 472 bool canonicalization_is_done_; 473 bool do_on_the_fly_canonicalization_; 474 bool decl_only_class_equals_definition_; 475 bool use_enum_binary_only_equality_; 476 bool allow_type_comparison_results_caching_; 477 optional<bool> analyze_exported_interfaces_only_; 478 #ifdef WITH_DEBUG_SELF_COMPARISON 479 bool self_comparison_debug_on_; 480 #endif 481 #ifdef WITH_DEBUG_TYPE_CANONICALIZATION 482 // This controls whether to use canonical type comparison during 483 // type comparison or not. This is only used for debugging, when we 484 // want to ensure that comparing types using canonical or structural 485 // comparison yields the same result. 486 bool use_canonical_type_comparison_; 487 // Whether we are debugging type canonicalization or not. When 488 // debugging type canonicalization, a type is compared to its 489 // potential canonical type twice: The first time with canonical 490 // comparison activated, and the second time with structural 491 // comparison activated. The two comparison should yield the same 492 // result, otherwise, canonicalization is "broken" for that 493 // particular type. 494 bool debug_type_canonicalization_; 495 bool debug_die_canonicalization_; 496 #endif 497 privpriv498 priv() 499 : canonicalization_is_done_(), 500 do_on_the_fly_canonicalization_(true), 501 decl_only_class_equals_definition_(false), 502 use_enum_binary_only_equality_(true), 503 allow_type_comparison_results_caching_(false) 504 #ifdef WITH_DEBUG_SELF_COMPARISON 505 , 506 self_comparison_debug_on_(false) 507 #endif 508 #ifdef WITH_DEBUG_TYPE_CANONICALIZATION 509 , 510 use_canonical_type_comparison_(true), 511 debug_type_canonicalization_(false), 512 debug_die_canonicalization_(false) 513 #endif 514 {} 515 516 /// Allow caching of the sub-types comparison results during the 517 /// invocation of the @ref equal overloads for class and function 518 /// types. 519 /// 520 /// @param f if true, allow type comparison result caching. 521 void allow_type_comparison_results_cachingpriv522 allow_type_comparison_results_caching(bool f) 523 {allow_type_comparison_results_caching_ = f;} 524 525 /// Check whether if caching of the sub-types comparison results during the 526 /// invocation of the @ref equal overloads for class and function 527 /// types is in effect. 528 /// 529 /// @return true iff caching of the sub-types comparison results 530 /// during the invocation of the @ref equal overloads for class and 531 /// function types is in effect. 532 bool allow_type_comparison_results_cachingpriv533 allow_type_comparison_results_caching() const 534 {return allow_type_comparison_results_caching_;} 535 536 /// Cache the result of comparing two sub-types. 537 /// 538 /// @param first the first sub-type that has been compared. Its 539 /// address is going to be stored in the cache. 540 /// 541 /// @param second the second sub-type that has been compared. Its 542 /// address is going to be stored in the cache. 543 /// 544 /// @param r the result of comparing @p first and @p second. This 545 /// is going to be stored in the cache, as well as the addresses of 546 /// @p first and @p second. 547 template<typename T> 548 void cache_type_comparison_resultpriv549 cache_type_comparison_result(T& first, T& second, bool r) 550 { 551 if (allow_type_comparison_results_caching() 552 && (r == false 553 || 554 (!is_recursive_type(&first) 555 && !is_recursive_type(&second) 556 && !is_type(&first)->priv_->depends_on_recursive_type() 557 && !is_type(&second)->priv_->depends_on_recursive_type()))) 558 { 559 type_comparison_results_cache_.emplace 560 (std::make_pair(reinterpret_cast<uint64_t>(&first), 561 reinterpret_cast<uint64_t>(&second)), 562 r); 563 } 564 } 565 566 /// Retrieve the result of comparing two sub-types from the cache, 567 /// if it was previously stored. 568 /// 569 /// @param first the first sub-type to consider. 570 /// 571 /// @param second the second sub-type to consider. The pair of 572 /// addresses of {@p first, @p second} is going to be looked up in 573 /// the cache. If it's present, then the associated result of the 574 /// comparison of @p first against @p second is present as well, and 575 /// is returned. 576 /// 577 /// @param r this is an out parameter which is set to the result of 578 /// the comparison of @p first against @p second if the pair of 579 /// addresses of {@p first, @p second} is present in the cache. 580 /// 581 /// @return true iff the pair of addresses of {@p first, @p second} 582 /// is present in the cache. In that case, the associated result of 583 /// the comparison of @p first against @p second is returned in the 584 /// argument of @p r. 585 template<typename T> 586 bool is_type_comparison_cachedpriv587 is_type_comparison_cached(T& first, T& second, bool& r) 588 { 589 if (!allow_type_comparison_results_caching()) 590 return false; 591 592 type_comparison_result_type::const_iterator it = 593 type_comparison_results_cache_.find 594 (std::make_pair(reinterpret_cast<uint64_t>(&first), 595 reinterpret_cast<uint64_t>(&second))); 596 if (it == type_comparison_results_cache_.end()) 597 return false; 598 599 r = it->second; 600 return true; 601 } 602 603 /// Clear the cache type comparison results. 604 void clear_type_comparison_results_cachepriv605 clear_type_comparison_results_cache() 606 {type_comparison_results_cache_.clear();} 607 608 /// Dumps a textual representation (to the standard error output) of 609 /// the content of the set of classes being currently compared using 610 /// the @ref equal overloads. 611 /// 612 /// This function is for debugging purposes. 613 void dump_classes_being_comparedpriv614 dump_classes_being_compared() 615 { 616 std::cerr << "classes being compared: " << classes_being_compared_.size() 617 << "\n" 618 << "=====================================\n"; 619 for (auto& p : classes_being_compared_) 620 { 621 class_or_union* c = reinterpret_cast<class_or_union*>(p.first); 622 std::cerr << "'" << c->get_pretty_representation() 623 << " / (" << std::hex << p.first << "," << p.second << ")" 624 << "'\n"; 625 } 626 std::cerr << "=====================================\n"; 627 } 628 629 /// Dumps a textual representation (to the standard error output) of 630 /// the content of the set of classes being currently compared using 631 /// the @ref equal overloads. 632 /// 633 /// This function is for debugging purposes. 634 void dump_fn_types_being_comparedpriv635 dump_fn_types_being_compared() 636 { 637 std::cerr << "fn_types being compared: " << fn_types_being_compared_.size() 638 << "\n" 639 << "=====================================\n"; 640 for (auto& p : fn_types_being_compared_) 641 { 642 function_type* c = reinterpret_cast<function_type*>(p.first); 643 std::cerr << "'" << c->get_pretty_representation() 644 << " / (" << std::hex << p.first << "," << p.second << ")" 645 << "'\n"; 646 } 647 std::cerr << "=====================================\n"; 648 } 649 650 /// Push a pair of operands on the stack of operands of the current 651 /// type comparison, during type canonicalization. 652 /// 653 /// For more information on this, please look at the description of 654 /// the right_type_comp_operands_ data member. 655 /// 656 /// @param left the left-hand-side comparison operand to push. 657 /// 658 /// @param right the right-hand-side comparison operand to push. 659 void push_composite_type_comparison_operandspriv660 push_composite_type_comparison_operands(const type_base* left, 661 const type_base* right) 662 { 663 ABG_ASSERT(left && right); 664 665 left_type_comp_operands_.push_back(left); 666 right_type_comp_operands_.push_back(right); 667 } 668 669 /// Pop a pair of operands from the stack of operands to the current 670 /// type comparison. 671 /// 672 /// For more information on this, please look at the description of 673 /// the right_type_comp_operands_ data member. 674 /// 675 /// @param left the left-hand-side comparison operand we expect to 676 /// pop from the top of the stack. If this doesn't match the 677 /// operand found on the top of the stack, the function aborts. 678 /// 679 /// @param right the right-hand-side comparison operand we expect to 680 /// pop from the bottom of the stack. If this doesn't match the 681 /// operand found on the top of the stack, the function aborts. 682 void pop_composite_type_comparison_operandspriv683 pop_composite_type_comparison_operands(const type_base* left, 684 const type_base* right) 685 { 686 const type_base *t = left_type_comp_operands_.back(); 687 ABG_ASSERT(t == left); 688 t = right_type_comp_operands_.back(); 689 ABG_ASSERT(t == right); 690 691 left_type_comp_operands_.pop_back(); 692 right_type_comp_operands_.pop_back(); 693 } 694 695 /// Mark all the types that comes after a certain one as NOT being 696 /// eligible for the canonical type propagation optimization. 697 /// 698 /// @param type the type that represents the "marker type". All 699 /// types after this one will be marked as being NON-eligible to 700 /// the canonical type propagation optimization. 701 /// 702 /// @param types the set of types to consider. In that vector, all 703 /// types that come after @p type are going to be marked as being 704 /// non-eligible to the canonical type propagation optimization. 705 /// 706 /// @return true iff the operation was successful. 707 bool mark_dependant_typespriv708 mark_dependant_types(const type_base* type, 709 vector<const type_base*>& types) 710 { 711 bool found = false; 712 for (auto t : types) 713 { 714 if (!found 715 && (reinterpret_cast<uintptr_t>(t) 716 == reinterpret_cast<uintptr_t>(type))) 717 { 718 found = true; 719 continue; 720 } 721 else if (found) 722 t->priv_->set_depends_on_recursive_type(type); 723 } 724 return found; 725 } 726 727 /// In the stack of the current types being compared (as part of 728 /// type canonicalization), mark all the types that comes after a 729 /// certain one as NOT being eligible to the canonical type 730 /// propagation optimization. 731 /// 732 /// For a starter, please read about the @ref 733 /// OnTheFlyCanonicalization, aka, "canonical type propagation 734 /// optimization". 735 /// 736 /// To implement that optimization, we need, among other things to 737 /// maintain stack of the types (and their sub-types) being 738 /// currently compared as part of type canonicalization. 739 /// 740 /// Note that we only consider the type that is the right-hand-side 741 /// operand of the comparison because it's that one that is being 742 /// canonicalized and thus, that is not yet canonicalized. 743 /// 744 /// The reason why a type is deemed NON-eligible to the canonical 745 /// type propagation optimization is that it "depends" on 746 /// recursively present type. Let me explain. 747 /// 748 /// Suppose we have a type T that has sub-types named ST0 and ST1. 749 /// Suppose ST1 itself has a sub-type that is T itself. In this 750 /// case, we say that T is a recursive type, because it has T 751 /// (itself) as one of its sub-types: 752 /// 753 /// T 754 /// +-- ST0 755 /// | 756 /// +-- ST1 757 /// + 758 /// | 759 /// +-- T 760 /// 761 /// ST1 is said to "depend" on T because it has T as a sub-type. 762 /// But because T is recursive, then ST1 is said to depend on a 763 /// recursive type. Notice however that ST0 does not depend on any 764 /// recursive type. 765 /// 766 /// When we are at the point of comparing the sub-type T of ST1 767 /// against its counterpart, the stack of the right-hand-side 768 /// operands of the type canonicalization is going to look like 769 /// this: 770 /// 771 /// | T | ST1 | 772 /// 773 /// We don't add the type T to the stack as we detect that T was 774 /// already in there (recursive cycle). 775 /// 776 /// So, this function will basically mark ST1 as being NON-eligible 777 /// to being the target of canonical type propagation. 778 /// 779 /// @param right the right-hand-side operand of the type comparison. 780 /// 781 /// @return true iff the operation was successful. 782 bool mark_dependant_types_compared_untilpriv783 mark_dependant_types_compared_until(const type_base* right) 784 { 785 bool result = false; 786 787 result |= 788 mark_dependant_types(right, 789 right_type_comp_operands_); 790 recursive_types_.insert(reinterpret_cast<uintptr_t>(right)); 791 return result; 792 } 793 794 /// Test if a type is a recursive one. 795 /// 796 /// @param t the type to consider. 797 /// 798 /// @return true iff @p t is recursive. 799 bool is_recursive_typepriv800 is_recursive_type(const type_base* t) 801 { 802 return (recursive_types_.find(reinterpret_cast<uintptr_t>(t)) 803 != recursive_types_.end()); 804 } 805 806 807 /// Unflag a type as being recursive 808 /// 809 /// @param t the type to unflag 810 void set_is_not_recursivepriv811 set_is_not_recursive(const type_base* t) 812 {recursive_types_.erase(reinterpret_cast<uintptr_t>(t));} 813 814 /// Propagate the canonical type of a type to another one. 815 /// 816 /// @param src the type to propagate the canonical type from. 817 /// 818 /// @param dest the type to propagate the canonical type of @p src 819 /// to. 820 /// 821 /// @return bool iff the canonical was propagated. 822 bool propagate_ctpriv823 propagate_ct(const type_base& src, const type_base& dest) 824 { 825 type_base_sptr canonical = src.get_canonical_type(); 826 ABG_ASSERT(canonical); 827 dest.priv_->canonical_type = canonical; 828 dest.priv_->naked_canonical_type = canonical.get(); 829 dest.priv_->set_canonical_type_propagated(true); 830 return true; 831 } 832 833 /// Mark a set of types that have been the target of canonical type 834 /// propagation and that depend on a recursive type as being 835 /// permanently canonicalized. 836 /// 837 /// To understand the sentence above, please read the description of 838 /// type canonicalization and especially about the "canonical type 839 /// propagation optimization" at @ref OnTheFlyCanonicalization, in 840 /// the src/abg-ir.cc file. 841 void confirm_ct_propagation_for_types_dependant_onpriv842 confirm_ct_propagation_for_types_dependant_on(const type_base* dependant_type) 843 { 844 pointer_set to_remove; 845 for (auto i : types_with_non_confirmed_propagated_ct_) 846 { 847 type_base *t = reinterpret_cast<type_base*>(i); 848 ABG_ASSERT(t->get_environment().priv_->is_recursive_type(t) 849 || t->priv_->depends_on_recursive_type()); 850 t->priv_->set_does_not_depend_on_recursive_type(dependant_type); 851 if (!t->priv_->depends_on_recursive_type()) 852 { 853 to_remove.insert(i); 854 t->priv_->set_propagated_canonical_type_confirmed(true); 855 } 856 } 857 858 for (auto i : to_remove) 859 types_with_non_confirmed_propagated_ct_.erase(i); 860 } 861 862 /// Mark a type that has been the target of canonical type 863 /// propagation as being permanently canonicalized. 864 /// 865 /// This function also marks the set of types that have been the 866 /// target of canonical type propagation and that depend on a 867 /// recursive type as being permanently canonicalized. 868 /// 869 /// To understand the sentence above, please read the description of 870 /// type canonicalization and especially about the "canonical type 871 /// propagation optimization" at @ref OnTheFlyCanonicalization, in 872 /// the src/abg-ir.cc file. 873 void confirm_ct_propagationpriv874 confirm_ct_propagation(const type_base*t) 875 { 876 if (!t || t->priv_->propagated_canonical_type_confirmed()) 877 return; 878 879 const environment& env = t->get_environment(); 880 881 env.priv_->confirm_ct_propagation_for_types_dependant_on(t); 882 t->priv_->set_does_not_depend_on_recursive_type(); 883 env.priv_->remove_from_types_with_non_confirmed_propagated_ct(t); 884 env.priv_->set_is_not_recursive(t); 885 t->priv_->set_propagated_canonical_type_confirmed(true); 886 } 887 888 /// Mark all the types that have been the target of canonical type 889 /// propagation and that are not yet confirmed as being permanently 890 /// canonicalized (aka confirmed). 891 /// 892 /// To understand the sentence above, please read the description of 893 /// type canonicalization and especially about the "canonical type 894 /// propagation optimization" at @ref OnTheFlyCanonicalization, in 895 /// the src/abg-ir.cc file. 896 void confirm_ct_propagationpriv897 confirm_ct_propagation() 898 { 899 for (auto i : types_with_non_confirmed_propagated_ct_) 900 { 901 type_base *t = reinterpret_cast<type_base*>(i); 902 ABG_ASSERT(t->get_environment().priv_->is_recursive_type(t) 903 || t->priv_->depends_on_recursive_type()); 904 t->priv_->set_does_not_depend_on_recursive_type(); 905 t->priv_->set_propagated_canonical_type_confirmed(true); 906 } 907 types_with_non_confirmed_propagated_ct_.clear(); 908 } 909 910 /// Collect the types that depends on a given "target" type. 911 /// 912 /// Walk a set of types and if they depend directly or indirectly on 913 /// a "target" type, then collect them into a set. 914 /// 915 /// @param target the target type to consider. 916 /// 917 /// @param types the types to walk to detect those who depend on @p 918 /// target. 919 /// 920 /// @return true iff one or more type from @p types is found to 921 /// depend on @p target. 922 bool collect_types_that_depends_onpriv923 collect_types_that_depends_on(const type_base *target, 924 const pointer_set& types, 925 pointer_set& collected) 926 { 927 bool result = false; 928 for (const auto i : types) 929 { 930 // First avoid infinite loop if we've already collected the 931 // current type. 932 if (collected.find(i) != collected.end()) 933 continue; 934 935 type_base *t = reinterpret_cast<type_base*>(i); 936 if (t->priv_->depends_on_recursive_type(target)) 937 { 938 collected.insert(i); 939 collect_types_that_depends_on(t, types, collected); 940 result = true; 941 } 942 } 943 return result; 944 } 945 946 /// Reset the canonical type (set it nullptr) of a set of types that 947 /// have been the target of canonical type propagation and that 948 /// depend on a given recursive type. 949 /// 950 /// Once the canonical type of a type in that set is reset, the type 951 /// is marked as being non-dependant on a recursive type anymore. 952 /// 953 /// To understand the sentences above, please read the description 954 /// of type canonicalization and especially about the "canonical 955 /// type propagation optimization" at @ref OnTheFlyCanonicalization, 956 /// in the src/abg-ir.cc file. 957 /// 958 /// @param target if a type which has been subject to the canonical 959 /// type propagation optimizationdepends on a this target type, then 960 /// cancel its canonical type. 961 void cancel_ct_propagation_for_types_dependant_onpriv962 cancel_ct_propagation_for_types_dependant_on(const type_base* target) 963 { 964 pointer_set to_remove; 965 collect_types_that_depends_on(target, 966 types_with_non_confirmed_propagated_ct_, 967 to_remove); 968 969 for (auto i : to_remove) 970 { 971 type_base *t = reinterpret_cast<type_base*>(i); 972 ABG_ASSERT(t->get_environment().priv_->is_recursive_type(t) 973 || t->priv_->depends_on_recursive_type()); 974 type_base_sptr canonical = t->priv_->canonical_type.lock(); 975 if (canonical) 976 { 977 t->priv_->clear_propagated_canonical_type(); 978 t->priv_->set_does_not_depend_on_recursive_type(); 979 } 980 } 981 982 for (auto i : to_remove) 983 types_with_non_confirmed_propagated_ct_.erase(i); 984 } 985 986 /// Reset the canonical type (set it nullptr) of a type that has 987 /// been the target of canonical type propagation. 988 /// 989 /// This also resets the propagated canonical type of the set of 990 /// types that depends on a given recursive type. 991 /// 992 /// Once the canonical type of a type in that set is reset, the type 993 /// is marked as being non-dependant on a recursive type anymore. 994 /// 995 /// To understand the sentences above, please read the description 996 /// of type canonicalization and especially about the "canonical 997 /// type propagation optimization" at @ref OnTheFlyCanonicalization, 998 /// in the src/abg-ir.cc file. 999 /// 1000 /// @param target if a type which has been subject to the canonical 1001 /// type propagation optimizationdepends on a this target type, then 1002 /// cancel its canonical type. 1003 void cancel_ct_propagationpriv1004 cancel_ct_propagation(const type_base* t) 1005 { 1006 if (!t) 1007 return; 1008 1009 const environment& env = t->get_environment(); 1010 env.priv_->cancel_ct_propagation_for_types_dependant_on(t); 1011 if (t->priv_->depends_on_recursive_type() 1012 || env.priv_->is_recursive_type(t)) 1013 { 1014 // This cannot carry any tentative canonical type at this 1015 // point. 1016 if (t->priv_->canonical_type_propagated() 1017 && !t->priv_->propagated_canonical_type_confirmed()) 1018 t->priv_->clear_propagated_canonical_type(); 1019 // Reset the marking of the type as it no longer carries a 1020 // tentative canonical type that might be later cancelled. 1021 t->priv_->set_does_not_depend_on_recursive_type(); 1022 env.priv_->remove_from_types_with_non_confirmed_propagated_ct(t); 1023 } 1024 } 1025 1026 /// Add a given type to the set of types that have been 1027 /// non-confirmed subjects of the canonical type propagation 1028 /// optimization. 1029 /// 1030 /// @param t the dependant type to consider. 1031 void add_to_types_with_non_confirmed_propagated_ctpriv1032 add_to_types_with_non_confirmed_propagated_ct(const type_base *t) 1033 { 1034 uintptr_t v = reinterpret_cast<uintptr_t>(t); 1035 types_with_non_confirmed_propagated_ct_.insert(v); 1036 } 1037 1038 /// Remove a given type from the set of types that have been 1039 /// non-confirmed subjects of the canonical type propagation 1040 /// optimization. 1041 /// 1042 /// @param dependant the dependant type to consider. 1043 void remove_from_types_with_non_confirmed_propagated_ctpriv1044 remove_from_types_with_non_confirmed_propagated_ct(const type_base* dependant) 1045 { 1046 uintptr_t i = reinterpret_cast<uintptr_t>(dependant); 1047 types_with_non_confirmed_propagated_ct_.erase(i); 1048 } 1049 1050 #ifdef WITH_DEBUG_SELF_COMPARISON 1051 /// When debugging self comparison, verify that a type T 1052 /// de-serialized from abixml has the same canonical type as the 1053 /// initial type built from DWARF that was serialized into T in the 1054 /// first place. 1055 /// 1056 /// @param t deserialized type (from abixml) to consider. 1057 /// 1058 /// @param c the canonical type @p t should have. 1059 /// 1060 /// @return true iff @p c is the canonical type that @p t should 1061 /// have. 1062 bool check_canonical_type_from_abixml_during_self_comppriv1063 check_canonical_type_from_abixml_during_self_comp(const type_base* t, 1064 const type_base* c) 1065 { 1066 if (!t || !t->get_corpus() || !c) 1067 return false; 1068 1069 if (!(t->get_corpus()->get_origin() == ir::corpus::NATIVE_XML_ORIGIN)) 1070 return false; 1071 1072 // Get the abixml type-id that this type was constructed from. 1073 string type_id; 1074 { 1075 unordered_map<uintptr_t, string>::const_iterator it = 1076 pointer_type_id_map_.find(reinterpret_cast<uintptr_t>(t)); 1077 if (it == pointer_type_id_map_.end()) 1078 // This type didn't have a type-id in the abixml file. Maybe 1079 // it's a function or method type. So let's just keep going. 1080 return true; 1081 type_id = it->second; 1082 } 1083 1084 // Get the canonical type the original in-memory type (constructed 1085 // from DWARF) had when it was serialized into abixml in the first place. 1086 type_base *original_canonical_type = nullptr; 1087 if (!type_id.empty()) 1088 { 1089 unordered_map<string, uintptr_t>::const_iterator it = 1090 type_id_canonical_type_map_.find(type_id); 1091 if (it == type_id_canonical_type_map_.end()) 1092 return false; 1093 original_canonical_type = reinterpret_cast<type_base*>(it->second); 1094 } 1095 1096 // Now perform the real check. 1097 // 1098 // We want to ensure that the canonical type 'c' of 't' is the 1099 // same as the canonical type of initial in-memory type (built 1100 // from DWARF) that was serialized into 't' (in abixml) in the 1101 // first place. 1102 if (original_canonical_type == c) 1103 return true; 1104 1105 return false; 1106 } 1107 1108 /// When debugging self comparison, verify that a type T 1109 /// de-serialized from abixml has the same canonical type as the 1110 /// initial type built from DWARF that was serialized into T in the 1111 /// first place. 1112 /// 1113 /// @param t deserialized type (from abixml) to consider. 1114 /// 1115 /// @param c the canonical type @p t should have. 1116 /// 1117 /// @return true iff @p c is the canonical type that @p t should 1118 /// have. 1119 bool check_canonical_type_from_abixml_during_self_comppriv1120 check_canonical_type_from_abixml_during_self_comp(const type_base_sptr& t, 1121 const type_base_sptr& c) 1122 { 1123 return check_canonical_type_from_abixml_during_self_comp(t.get(), c.get()); 1124 } 1125 #endif 1126 };// end struct environment::priv 1127 1128 // <class_or_union::priv definitions> 1129 struct class_or_union::priv 1130 { 1131 typedef_decl_wptr naming_typedef_; 1132 data_members data_members_; 1133 data_members non_static_data_members_; 1134 member_functions member_functions_; 1135 // A map that associates a linkage name to a member function. 1136 string_mem_fn_sptr_map_type mem_fns_map_; 1137 // A map that associates function signature strings to member 1138 // function. 1139 string_mem_fn_ptr_map_type signature_2_mem_fn_map_; 1140 member_function_templates member_function_templates_; 1141 member_class_templates member_class_templates_; 1142 privpriv1143 priv() 1144 {} 1145 privpriv1146 priv(class_or_union::data_members& data_mbrs, 1147 class_or_union::member_functions& mbr_fns) 1148 : data_members_(data_mbrs), 1149 member_functions_(mbr_fns) 1150 { 1151 for (data_members::const_iterator i = data_members_.begin(); 1152 i != data_members_.end(); 1153 ++i) 1154 if (!get_member_is_static(*i)) 1155 non_static_data_members_.push_back(*i); 1156 } 1157 1158 /// Mark a pair of classes or unions as being currently compared 1159 /// using the class_or_union== operator. 1160 /// 1161 /// Note that this marking business is to avoid infinite loop when 1162 /// comparing a pair of classes or unions. If via the comparison of 1163 /// a data member or a member function a recursive re-comparison of 1164 /// the class or union is attempted, the marking process helps to 1165 /// detect that infinite loop possibility and avoid it. 1166 /// 1167 /// @param first the class or union (of the pair) to mark as being 1168 /// currently compared. 1169 /// 1170 /// @param second the second class or union (of the pair) to mark as 1171 /// being currently compared. 1172 void mark_as_being_comparedpriv1173 mark_as_being_compared(const class_or_union& first, 1174 const class_or_union& second) const 1175 { 1176 const environment& env = first.get_environment(); 1177 env.priv_->classes_being_compared_.insert 1178 (std::make_pair(reinterpret_cast<uint64_t>(&first), 1179 reinterpret_cast<uint64_t>(&second))); 1180 } 1181 1182 /// Mark a pair of classes or unions as being currently compared 1183 /// using the class_or_union== operator. 1184 /// 1185 /// Note that this marking business is to avoid infinite loop when 1186 /// comparing a pair of classes or unions. If via the comparison of 1187 /// a data member or a member function a recursive re-comparison of 1188 /// the class or union is attempted, the marking process helps to 1189 /// detect that infinite loop possibility and avoid it. 1190 /// 1191 /// @param first the class or union (of the pair) to mark as being 1192 /// currently compared. 1193 /// 1194 /// @param second the second class or union (of the pair) to mark as 1195 /// being currently compared. 1196 void mark_as_being_comparedpriv1197 mark_as_being_compared(const class_or_union* first, 1198 const class_or_union* second) const 1199 {mark_as_being_compared(*first, *second);} 1200 1201 /// Mark a pair of classes or unions as being currently compared 1202 /// using the class_or_union== operator. 1203 /// 1204 /// Note that this marking business is to avoid infinite loop when 1205 /// comparing a pair of classes or unions. If via the comparison of 1206 /// a data member or a member function a recursive re-comparison of 1207 /// the class or union is attempted, the marking process helps to 1208 /// detect that infinite loop possibility and avoid it. 1209 /// 1210 /// @param first the class or union (of the pair) to mark as being 1211 /// currently compared. 1212 /// 1213 /// @param second the second class or union (of the pair) to mark as 1214 /// being currently compared. 1215 void mark_as_being_comparedpriv1216 mark_as_being_compared(const class_or_union_sptr& first, 1217 const class_or_union_sptr& second) const 1218 {mark_as_being_compared(*first, *second);} 1219 1220 /// If a pair of class_or_union has been previously marked as 1221 /// being compared -- via an invocation of mark_as_being_compared() 1222 /// this method unmarks it. Otherwise is has no effect. 1223 /// 1224 /// This method is not thread safe because it uses the static data 1225 /// member classes_being_compared_. If you wish to use it in a 1226 /// multi-threaded environment you should probably protect the 1227 /// access to that static data member with a mutex or somesuch. 1228 /// 1229 /// @param first the first instance of class_or_union (of the pair) 1230 /// to unmark. 1231 /// 1232 /// @param second the second instance of class_or_union (of the 1233 /// pair) to unmark. 1234 void unmark_as_being_comparedpriv1235 unmark_as_being_compared(const class_or_union& first, 1236 const class_or_union& second) const 1237 { 1238 const environment& env = first.get_environment(); 1239 env.priv_->classes_being_compared_.erase 1240 (std::make_pair(reinterpret_cast<uint64_t>(&first), 1241 reinterpret_cast<uint64_t>(&second))); 1242 } 1243 1244 /// If a pair of class_or_union has been previously marked as 1245 /// being compared -- via an invocation of mark_as_being_compared() 1246 /// this method unmarks it. Otherwise is has no effect. 1247 /// 1248 /// This method is not thread safe because it uses the static data 1249 /// member classes_being_compared_. If you wish to use it in a 1250 /// multi-threaded environment you should probably protect the 1251 /// access to that static data member with a mutex or somesuch. 1252 /// 1253 /// @param first the first instance of class_or_union (of the pair) 1254 /// to unmark. 1255 /// 1256 /// @param second the second instance of class_or_union (of the 1257 /// pair) to unmark. 1258 void unmark_as_being_comparedpriv1259 unmark_as_being_compared(const class_or_union* first, 1260 const class_or_union* second) const 1261 { 1262 if (!first || !second) 1263 return; 1264 unmark_as_being_compared(*first, *second); 1265 } 1266 1267 /// Test if a pair of class_or_union is being currently compared. 1268 /// 1269 ///@param first the first class or union (of the pair) to test for. 1270 /// 1271 ///@param second the second class or union (of the pair) to test for. 1272 /// 1273 /// @return true if the pair {@p first, @p second} is being 1274 /// compared, false otherwise. 1275 bool comparison_startedpriv1276 comparison_started(const class_or_union& first, 1277 const class_or_union& second) const 1278 { 1279 const environment& env = first.get_environment(); 1280 return env.priv_-> 1281 classes_being_compared_.count 1282 (std::make_pair(reinterpret_cast<uint64_t>(&first), 1283 reinterpret_cast<uint64_t>((&second)))); 1284 } 1285 1286 /// Test if a pair of class_or_union is being currently compared. 1287 /// 1288 ///@param first the first class or union (of the pair) to test for. 1289 /// 1290 ///@param second the second class or union (of the pair) to test for. 1291 /// 1292 /// @return true if the pair {@p first, @p second} is being 1293 /// compared, false otherwise. 1294 bool comparison_startedpriv1295 comparison_started(const class_or_union* first, 1296 const class_or_union* second) const 1297 { 1298 if (first && second) 1299 return comparison_started(*first, *second); 1300 return false; 1301 } 1302 }; // end struct class_or_union::priv 1303 1304 // <function_type::priv definitions> 1305 1306 /// The type of the private data of the @ref function_type type. 1307 struct function_type::priv 1308 { 1309 parameters parms_; 1310 type_base_wptr return_type_; 1311 interned_string cached_name_; 1312 interned_string internal_cached_name_; 1313 interned_string temp_internal_cached_name_; 1314 privpriv1315 priv() 1316 {} 1317 privpriv1318 priv(const parameters& parms, 1319 type_base_sptr return_type) 1320 : parms_(parms), 1321 return_type_(return_type) 1322 {} 1323 privpriv1324 priv(type_base_sptr return_type) 1325 : return_type_(return_type) 1326 {} 1327 1328 /// Mark a given pair of @ref function_type as being compared. 1329 /// 1330 /// @param first the first @ref function_type of the pair being 1331 /// compared, to mark. 1332 /// 1333 /// @param second the second @ref function_type of the pair being 1334 /// compared, to mark. 1335 void mark_as_being_comparedpriv1336 mark_as_being_compared(const function_type& first, 1337 const function_type& second) const 1338 { 1339 const environment& env = first.get_environment(); 1340 env.priv_->fn_types_being_compared_.insert 1341 (std::make_pair(reinterpret_cast<uint64_t>(&first), 1342 reinterpret_cast<uint64_t>(&second))); 1343 } 1344 1345 /// Mark a given pair of @ref function_type as being compared. 1346 /// 1347 /// @param first the first @ref function_type of the pair being 1348 /// compared, to mark. 1349 /// 1350 /// @param second the second @ref function_type of the pair being 1351 /// compared, to mark. 1352 void unmark_as_being_comparedpriv1353 unmark_as_being_compared(const function_type& first, 1354 const function_type& second) const 1355 { 1356 const environment& env = first.get_environment(); 1357 env.priv_->fn_types_being_compared_.erase 1358 (std::make_pair(reinterpret_cast<uint64_t>(&first), 1359 reinterpret_cast<uint64_t>(&second))); 1360 } 1361 1362 /// Tests if a @ref function_type is currently being compared. 1363 /// 1364 /// @param type the function type to take into account. 1365 /// 1366 /// @return true if @p type is being compared. 1367 bool comparison_startedpriv1368 comparison_started(const function_type& first, 1369 const function_type& second) const 1370 { 1371 const environment& env = first.get_environment(); 1372 return env.priv_->fn_types_being_compared_.count 1373 (std::make_pair(reinterpret_cast<uint64_t>(&first), 1374 reinterpret_cast<uint64_t>(&second))); 1375 } 1376 };// end struc function_type::priv 1377 1378 // </function_type::priv definitions> 1379 1380 } // end namespace ir 1381 1382 } // end namespace abigail 1383 1384 #endif // __ABG_IR_PRIV_H__ 1385