1// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 2// -*- mode: C++ -*- 3// 4// Copyright (C) 2013-2022 Red Hat, Inc. 5 6/// @file 7/// 8/// This file contains the definitions of the entry points to 9/// de-serialize an instance of @ref abigail::translation_unit to an 10/// ABI Instrumentation file in libabigail native XML format. This 11/// native XML format is named "abixml". 12 13#include "config.h" 14#include <assert.h> 15#include <algorithm> 16#include <fstream> 17#include <iomanip> 18#include <ios> 19#include <iostream> 20#include <memory> 21#include <sstream> 22#include <stack> 23#include <unordered_map> 24#include <vector> 25 26#include "abg-tools-utils.h" 27 28#include "abg-internal.h" 29// <headers defining libabigail's API go under here> 30ABG_BEGIN_EXPORT_DECLARATIONS 31 32#include "abg-config.h" 33#include "abg-corpus.h" 34#include "abg-hash.h" 35#include "abg-sptr-utils.h" 36 37#include "abg-writer.h" 38#include "abg-libxml-utils.h" 39#include "abg-fwd.h" 40 41ABG_END_EXPORT_DECLARATIONS 42// </headers defining libabigail's API> 43 44namespace abigail 45{ 46using std::cerr; 47using std::shared_ptr; 48using std::dynamic_pointer_cast; 49using std::static_pointer_cast; 50using std::ofstream; 51using std::ostream; 52using std::ostringstream; 53using std::list; 54using std::vector; 55using std::stack; 56using std::unordered_map; 57using abigail::sptr_utils::noop_deleter; 58 59/// The namespace for the native XML file format writer. 60/// 61/// It contains utilities to serialize ABI artifacts from the @ref ir 62/// namespace into the native XML format. 63namespace xml_writer 64{ 65 66class id_manager 67{ 68 const environment& m_env; 69 mutable unsigned long long m_cur_id; 70 71 unsigned long long 72 get_new_id() const 73 { return ++m_cur_id; } 74 75public: 76 id_manager(const environment& env) 77 : m_env(env), 78 m_cur_id(0) {} 79 80 const environment& 81 get_environment() const 82 {return m_env;} 83 84 /// Return a unique string representing a numerical id. 85 interned_string 86 get_id() const 87 { 88 ostringstream o; 89 o << get_new_id(); 90 const environment& env = get_environment(); 91 return env.intern(o.str()); 92 } 93 94 /// Return a unique string representing a numerical ID, prefixed by 95 /// prefix. 96 /// 97 /// @param prefix the prefix of the returned unique id. 98 interned_string 99 get_id_with_prefix(const string& prefix) const 100 { 101 ostringstream o; 102 o << prefix << get_new_id(); 103 const environment& env = get_environment(); 104 return env.intern(o.str()); 105 } 106}; 107 108/// A convenience typedef for a map that associates a pointer to type 109/// to a string. 110typedef unordered_map<type_base*, interned_string> type_ptr_map; 111 112/// The hashing functor of for the set of non canonicalized types, aka 113/// @ref nc_type_ptr_set_type 114struct non_canonicalized_type_hash 115{ 116 /// Hashing function 117 /// 118 /// This hashes a string representation of the non canonicalized 119 /// types. For now, two typedefs with different names but with the 120 /// same underlying types will hash differently. 121 /// 122 /// TODO: try making typedefs with different names hash the same if 123 /// their underlying types are equal and see what breaks. 124 /// 125 /// @param p the non canonicalized type to hash. 126 /// 127 /// @return the hash value. 128 size_t 129 operator() (const type_base* p) const 130 { 131 ABG_ASSERT(is_non_canonicalized_type(p)); 132 std::hash<string> h; 133 return h(p->get_pretty_representation(/*internal=*/false, 134 // By choosing the 135 // non-internal format, 136 // classes and structs are 137 // named differently and 138 // typedefs and 139 // classes/structs are named 140 // differently. This 141 // implies less uncertainty 142 // in the sorting. 143 true)); 144 } 145}; // end struct non_canonicalized_type_hash 146 147/// The equality functor of for the set of non canonicalized types, aka 148/// @ref nc_type_ptr_set_type 149struct non_canonicalized_type_equal 150{ 151 /// The equality operator. 152 /// 153 /// @param l the left-hand operand of the operation. 154 /// 155 /// @param r the right-hand operand of the operation. 156 /// 157 /// For now, two typedefs with different names but with the same 158 /// underlying types are considered different. 159 /// 160 /// TODO: try making typedefs with different names hash the same if 161 /// their underlying types are equal and see what breaks. 162 // 163 // @return true iff @p l equals @p r. 164 bool 165 operator()(const type_base *l, const type_base *r) const 166 { 167 ABG_ASSERT(is_non_canonicalized_type(l)); 168 ABG_ASSERT(is_non_canonicalized_type(r)); 169 170 return *l == *r; 171 } 172}; // end struct non_canonicalized_type_equal 173 174// A convenience typedef for a set of type_base*. 175typedef std::unordered_set<const type_base*> type_ptr_set_type; 176 177/// A set meant to carry non canonicalized types. 178/// 179/// Those types make the function is_non_canonicalized_type return 180/// true. 181typedef std::unordered_set<const type_base*, 182 non_canonicalized_type_hash, 183 non_canonicalized_type_equal> 184nc_type_ptr_set_type; 185 186/// A map meant to carry non canonicalized types as key. 187/// 188/// Those types make the function is_non_canonicalized_type return 189/// true. 190typedef std::unordered_map<const type_base*, interned_string, 191 non_canonicalized_type_hash, 192 non_canonicalized_type_equal> 193nc_type_ptr_istr_map_type; 194 195/// A convenience typedef for a set of function type*. 196typedef std::unordered_set<function_type*> fn_type_ptr_set_type; 197 198typedef unordered_map<shared_ptr<function_tdecl>, 199 string, 200 function_tdecl::shared_ptr_hash> fn_tmpl_shared_ptr_map; 201 202typedef unordered_map<shared_ptr<class_tdecl>, 203 string, 204 class_tdecl::shared_ptr_hash> class_tmpl_shared_ptr_map; 205 206class write_context 207{ 208 const environment& m_env; 209 id_manager m_id_manager; 210 ostream* m_ostream; 211 bool m_annotate; 212 bool m_show_locs; 213 bool m_write_architecture; 214 bool m_write_corpus_path; 215 bool m_write_comp_dir; 216 bool m_write_elf_needed; 217 bool m_write_parameter_names; 218 bool m_short_locs; 219 bool m_write_default_sizes; 220 type_id_style_kind m_type_id_style; 221 mutable type_ptr_map m_type_id_map; 222 // type id map for non-canonicalized types. 223 mutable unordered_set<uint32_t> m_used_type_id_hashes; 224 mutable type_ptr_set_type m_emitted_type_set; 225 // A map of types that are referenced by emitted pointers, 226 // references or typedefs 227 type_ptr_set_type m_referenced_types_set; 228 fn_type_ptr_set_type m_referenced_fn_types_set; 229 fn_tmpl_shared_ptr_map m_fn_tmpl_id_map; 230 class_tmpl_shared_ptr_map m_class_tmpl_id_map; 231 string_elf_symbol_sptr_map_type m_fun_symbol_map; 232 string_elf_symbol_sptr_map_type m_var_symbol_map; 233 unordered_set<interned_string, hash_interned_string> m_emitted_decls_set; 234 235 write_context(); 236 237public: 238 239 /// Constructor. 240 /// 241 /// @param env the enviroment we are operating from. 242 /// 243 /// @param os the output stream to write to. 244 write_context(const environment& env, ostream& os) 245 : m_env(env), 246 m_id_manager(env), 247 m_ostream(&os), 248 m_annotate(false), 249 m_show_locs(true), 250 m_write_architecture(true), 251 m_write_corpus_path(true), 252 m_write_comp_dir(true), 253 m_write_elf_needed(true), 254 m_write_parameter_names(true), 255 m_short_locs(false), 256 m_write_default_sizes(true), 257 m_type_id_style(SEQUENCE_TYPE_ID_STYLE) 258 {} 259 260 /// Getter of the environment we are operating from. 261 /// 262 /// @return the environment we are operating from. 263 const environment& 264 get_environment() const 265 {return m_env;} 266 267 const config& 268 get_config() const 269 {return get_environment().get_config();} 270 271 /// Getter for the current ostream 272 /// 273 /// @return a reference to the current ostream 274 ostream& 275 get_ostream() 276 {return *m_ostream;} 277 278 /// Setter for the current ostream 279 /// 280 /// @param os the new ostream 281 void 282 set_ostream(ostream& os) 283 {m_ostream = &os;} 284 285 /// Getter of the annotation option. 286 /// 287 /// @return true iff ABIXML annotations are turned on 288 bool 289 get_annotate() 290 {return m_annotate;} 291 292 /// Setter of the annotation option. 293 /// 294 /// @param f the new value of the flag. 295 void 296 set_annotate(bool f) 297 {m_annotate = f;} 298 299 /// Getter of the write-architecture option. 300 /// 301 /// @return true iff architecture information shall be emitted 302 bool 303 get_write_architecture() 304 {return m_write_architecture;} 305 306 /// Setter of the write-architecture option 307 /// 308 /// @param f the new value of the flag. 309 void 310 set_write_architecture(bool f) 311 {m_write_architecture = f;} 312 313 /// Getter of the elf-needed option. 314 /// 315 /// @return true iff elf needed information shall be emitted 316 bool 317 get_write_elf_needed() 318 {return m_write_elf_needed;} 319 320 /// Setter of the elf-needed option. 321 /// 322 /// @param f the new value of the flag. 323 void 324 set_write_elf_needed(bool f) 325 {m_write_elf_needed = f;} 326 327 /// Getter of the default-sizes option. 328 /// 329 /// @return true iff default size-in-bits needs to be emitted 330 bool 331 get_write_default_sizes() 332 {return m_write_default_sizes;} 333 334 /// Setter of the default-sizes option. 335 /// 336 /// @param f the new value of the flag. 337 void 338 set_write_default_sizes(bool f) 339 {m_write_default_sizes = f;} 340 341 /// Getter of the write-corpus-path option. 342 /// 343 /// @return true iff corpus-path information shall be emitted 344 bool 345 get_write_corpus_path() 346 {return m_write_corpus_path;} 347 348 /// Setter of the write-corpus-path option 349 /// 350 /// @param f the new value of the flag. 351 void 352 set_write_corpus_path(bool f) 353 {m_write_corpus_path = f;} 354 355 /// Getter of the comp-dir-path option. 356 /// 357 /// @return true iff compilation dir information shall be emitted 358 bool 359 get_write_comp_dir() 360 {return m_write_comp_dir;} 361 362 /// Setter of the comp-dir-path option 363 /// 364 /// @param f the new value of the flag. 365 void 366 set_write_comp_dir(bool f) 367 {m_write_comp_dir = f;} 368 369 /// Getter of the short-locs option. 370 /// 371 /// @return true iff short locations shall be emitted 372 bool 373 get_short_locs() 374 {return m_short_locs;} 375 376 /// Setter of the short-locs option 377 /// 378 /// @param f the new value of the flag. 379 void 380 set_short_locs(bool f) 381 {m_short_locs = f;} 382 383 /// Getter of the parameter-names option. 384 /// 385 /// @return true iff parameter names shall be emitted 386 bool 387 get_write_parameter_names() const 388 {return m_write_parameter_names;} 389 390 /// Setter of the parameter-names option 391 /// 392 /// @param f the new value of the flag. 393 void 394 set_write_parameter_names(bool f) 395 {m_write_parameter_names = f;} 396 397 /// Getter of the "show-locs" option. 398 /// 399 /// When this option is true then the XML writer emits location 400 /// information for emitted ABI artifacts. 401 /// 402 /// @return the value of the "show-locs" option. 403 bool 404 get_show_locs() const 405 {return m_show_locs;} 406 407 /// Setter of the "show-locs" option. 408 /// 409 /// When this option is true then the XML writer emits location 410 /// information for emitted ABI artifacts. 411 /// 412 /// @param f the new value of the "show-locs" option. 413 void 414 set_show_locs(bool f) 415 {m_show_locs = f;} 416 417 /// Getter of the "type-id-style" option. 418 /// 419 /// This option controls the kind of type ids used in XML output. 420 /// 421 /// @return the value of the "type-id-style" option. 422 type_id_style_kind 423 get_type_id_style() const 424 {return m_type_id_style;} 425 426 /// Setter of the "type-id-style" option. 427 /// 428 /// This option controls the kind of type ids used in XML output. 429 /// 430 /// @param style the new value of the "type-id-style" option. 431 void 432 set_type_id_style(type_id_style_kind style) 433 {m_type_id_style = style;} 434 435 /// Getter of the @ref id_manager. 436 /// 437 /// @return the @ref id_manager used by the current instance of @ref 438 /// write_context. 439 const id_manager& 440 get_id_manager() const 441 {return m_id_manager;} 442 443 id_manager& 444 get_id_manager() 445 {return m_id_manager;} 446 447 /// @return true iff type has already been assigned an ID. 448 bool 449 type_has_existing_id(type_base_sptr type) const 450 {return type_has_existing_id(type.get());} 451 452 /// @return true iff type has already been assigned an ID. 453 bool 454 type_has_existing_id(type_base* type) const 455 { 456 type = get_exemplar_type(type); 457 return m_type_id_map.find(type) != m_type_id_map.end(); 458 } 459 460 /// Associate a unique id to a given type. For that, put the type 461 /// in a hash table, hashing the type. So if the type has no id 462 /// associated to it, create a new one and return it. Otherwise, 463 /// return the existing id for that type. 464 interned_string 465 get_id_for_type(const type_base_sptr& t) 466 {return get_id_for_type(t.get());} 467 468 /// Associate a unique id to a given type. For that, put the type 469 /// in a hash table, hashing the type. So if the type has no id 470 /// associated to it, create a new one and return it. Otherwise, 471 /// return the existing id for that type. 472 interned_string 473 get_id_for_type(type_base* type) const 474 { 475 type_base* c = get_exemplar_type(type); 476 477 auto it = m_type_id_map.find(c); 478 if (it != m_type_id_map.end()) 479 return it->second; 480 481 switch (m_type_id_style) 482 { 483 case SEQUENCE_TYPE_ID_STYLE: 484 { 485 interned_string id = get_id_manager().get_id_with_prefix("type-id-"); 486 return m_type_id_map[c] = id; 487 } 488 case HASH_TYPE_ID_STYLE: 489 { 490 interned_string pretty = c->get_cached_pretty_representation(true); 491 size_t hash = hashing::fnv_hash(pretty); 492 while (!m_used_type_id_hashes.insert(hash).second) 493 ++hash; 494 std::ostringstream os; 495 os << std::hex << std::setfill('0') << std::setw(8) << hash; 496 return m_type_id_map[c] = c->get_environment().intern(os.str()); 497 } 498 } 499 ABG_ASSERT_NOT_REACHED; 500 return interned_string(); 501 } 502 503 string 504 get_id_for_fn_tmpl(const function_tdecl_sptr& f) 505 { 506 fn_tmpl_shared_ptr_map::const_iterator it = m_fn_tmpl_id_map.find(f); 507 if (it == m_fn_tmpl_id_map.end()) 508 { 509 string id = get_id_manager().get_id_with_prefix("fn-tmpl-id-"); 510 m_fn_tmpl_id_map[f] = id; 511 return id; 512 } 513 return m_fn_tmpl_id_map[f]; 514 } 515 516 string 517 get_id_for_class_tmpl(const class_tdecl_sptr& c) 518 { 519 class_tmpl_shared_ptr_map::const_iterator it = m_class_tmpl_id_map.find(c); 520 if (it == m_class_tmpl_id_map.end()) 521 { 522 string id = get_id_manager().get_id_with_prefix("class-tmpl-id-"); 523 m_class_tmpl_id_map[c] = id; 524 return id; 525 } 526 return m_class_tmpl_id_map[c]; 527 } 528 529 void 530 clear_type_id_map() 531 { 532 m_type_id_map.clear(); 533 } 534 535 536 /// Getter of the set of types that were referenced by a pointer, 537 /// reference or typedef. 538 /// 539 /// This set contains only types that do have canonical types and 540 /// which are not function types. 541 /// 542 /// @return the set of types that were referenced. 543 const type_ptr_set_type& 544 get_referenced_types() const 545 {return m_referenced_types_set;} 546 547 /// Getter of the set of function types that were referenced by a 548 /// pointer, reference or typedef. 549 /// 550 /// @return the set of function types that were referenced. 551 const fn_type_ptr_set_type& 552 get_referenced_function_types() const 553 {return m_referenced_fn_types_set;} 554 555 /// Test if there are non emitted referenced types. 556 /// 557 /// @return true iff there are non emitted referenced types. 558 bool 559 has_non_emitted_referenced_types() const 560 { 561 for (const auto t : get_referenced_types()) 562 if (!type_is_emitted(t)) 563 return false; 564 565 return true; 566 } 567 568 /// Record a given type as being referenced by a pointer, a 569 /// reference or a typedef type that is being emitted to the XML 570 /// output. 571 /// 572 /// @param t a shared pointer to a type 573 void 574 record_type_as_referenced(const type_base_sptr& type) 575 { 576 type_base* t = get_exemplar_type(type.get()); 577 // If the type is a function type, record it in a dedicated data 578 // structure. 579 if (function_type* f = is_function_type(t)) 580 m_referenced_fn_types_set.insert(f); 581 else 582 m_referenced_types_set.insert(t); 583 } 584 585 /// Test if a given type has been referenced by a pointer, a 586 /// reference or a typedef type that was emitted to the XML output. 587 /// 588 /// @param f a shared pointer to a type 589 /// 590 /// @return true if the type has been referenced, false 591 /// otherwise. 592 bool 593 type_is_referenced(const type_base_sptr& type) 594 { 595 type_base* t = get_exemplar_type(type.get()); 596 if (function_type* f = is_function_type(t)) 597 return (m_referenced_fn_types_set.find(f) 598 != m_referenced_fn_types_set.end()); 599 else 600 return m_referenced_types_set.find(t) != m_referenced_types_set.end(); 601 } 602 603 /// A comparison functor to compare pointers to @ref type_base. 604 /// 605 /// What is compared is the string representation of the pointed-to 606 /// type. 607 struct type_ptr_cmp 608 { 609 type_ptr_map *map; 610 type_ptr_cmp(type_ptr_map *m) 611 : map(m) 612 {} 613 614 /// The comparison operator of the functor. 615 /// 616 /// @param l the first type to consider. 617 /// 618 /// @param r the second type to consider. 619 /// 620 /// @return true if the string representation of type @p l is 621 /// considered to be "less than" the string representation of the 622 /// type @p r. 623 /// 624 /// But when the two string representations are equal (for 625 /// instance, for typedefs that have the same string 626 /// representation), this function compares the type-ids of the 627 /// types. This allows for a stable result. 628 bool 629 operator()(const type_base* l, const type_base* r) const 630 { 631 if (!l && r) 632 return true; 633 if (l && !r) 634 return false; 635 if (!l && !r) 636 return false; 637 638 string r1 = ir::get_pretty_representation(l, true), 639 r2 = ir::get_pretty_representation(r, true); 640 641 if (r1 == r2) 642 { 643 // So the two operands have the same pretty representation. 644 if (is_typedef(l) || is_typedef(r)) 645 { 646 // There is a typedef in the comparison. 647 // Let's strip the typedef to look at the underlying 648 // type and consider its pretty representation instead. 649 l = peel_typedef_type(l); 650 r = peel_typedef_type(r); 651 652 r1 = ir::get_pretty_representation(l, /*internal=*/false), 653 r2 = ir::get_pretty_representation(r, /*internal=*/false); 654 655 if (r1 != r2) 656 return r1 < r2; 657 } 658 659 type_ptr_map::const_iterator i = 660 map->find(const_cast<type_base*>(l)); 661 if (i != map->end()) 662 r1 = i->second; 663 i = map->find(const_cast<type_base*>(r)); 664 if (i != map->end()) 665 r2 = i->second; 666 } 667 668 return r1 < r2; 669 } 670 671 /// The comparison operator of the functor. 672 /// 673 /// @param l the first type to consider. 674 /// 675 /// @param r the second type to consider. 676 /// 677 /// @return true if the string representation of type @p l is 678 /// considered to be "less than" the string representation of the 679 /// type @p r. 680 /// 681 /// But when the two string representations are equal (for 682 /// instance, for typedefs that have the same string 683 /// representation), this function compares the type-ids of the 684 /// types. This allows for a stable result. 685 bool 686 operator()(const type_base_sptr& l, const type_base_sptr& r) const 687 {return operator()(l.get(), r.get());} 688 }; // end struct type_ptr_cmp 689 690 /// Sort the content of a map of type pointers into a vector. 691 /// 692 /// The pointers are sorted by using their string representation as 693 /// the key to sort, lexicographically. 694 /// 695 /// @param types the map to sort. 696 /// 697 /// @param sorted the resulted sorted vector. It's set by this 698 /// function with the result of the sorting. 699 void 700 sort_types(type_ptr_set_type& types, 701 vector<type_base*>& sorted) 702 { 703 string id; 704 for (type_ptr_set_type::const_iterator i = types.begin(); 705 i != types.end(); 706 ++i) 707 sorted.push_back(const_cast<type_base*>(*i)); 708 type_ptr_cmp comp(&m_type_id_map); 709 sort(sorted.begin(), sorted.end(), comp); 710 } 711 712 /// Sort the content of a map of type pointers into a vector. 713 /// 714 /// The pointers are sorted by using their string representation as 715 /// the key to sort, lexicographically. 716 /// 717 /// @param types the map to sort. 718 /// 719 /// @param sorted the resulted sorted vector. It's set by this 720 /// function with the result of the sorting. 721 void 722 sort_types(const istring_type_base_wptr_map_type& types, 723 vector<type_base_sptr> &sorted) 724 { 725 for (istring_type_base_wptr_map_type::const_iterator i = types.begin(); 726 i != types.end(); 727 ++i) 728 sorted.push_back(type_base_sptr(i->second)); 729 type_ptr_cmp comp(&m_type_id_map); 730 sort(sorted.begin(), sorted.end(), comp); 731 } 732 733 /// Sort the content of a vector of function types into a vector of 734 /// types. 735 /// 736 /// The pointers are sorted by using their string representation as 737 /// the key to sort, lexicographically. 738 /// 739 /// @param types the vector of function types to store. 740 /// 741 /// @param sorted the resulted sorted vector. It's set by this 742 /// function with the result of the sorting. 743 void 744 sort_types(const vector<function_type_sptr>& types, 745 vector<type_base_sptr> &sorted) 746 { 747 for (vector<function_type_sptr>::const_iterator i = types.begin(); 748 i != types.end(); 749 ++i) 750 sorted.push_back(*i); 751 type_ptr_cmp comp(&m_type_id_map); 752 sort(sorted.begin(), sorted.end(), comp); 753 } 754 755 /// Flag a type as having been written out to the XML output. 756 /// 757 /// @param t the type to flag. 758 void 759 record_type_as_emitted(const type_base_sptr &t) 760 {record_type_as_emitted(t.get());} 761 762 /// Flag a type as having been written out to the XML output. 763 /// 764 /// @param t the type to flag. 765 void 766 record_type_as_emitted(const type_base* t) 767 { 768 type_base* c = get_exemplar_type(t); 769 m_emitted_type_set.insert(c); 770 } 771 772 /// Test if a given type has been written out to the XML output. 773 /// 774 /// @param the type to test for. 775 /// 776 /// @return true if the type has already been emitted, false 777 /// otherwise. 778 bool 779 type_is_emitted(const type_base* t) const 780 { 781 type_base* c = get_exemplar_type(t); 782 return (m_emitted_type_set.find(c) != m_emitted_type_set.end()); 783 } 784 785 /// Test if a given type has been written out to the XML output. 786 /// 787 /// @param the type to test for. 788 /// 789 /// @return true if the type has already been emitted, false 790 /// otherwise. 791 bool 792 type_is_emitted(const type_base_sptr& t) const 793 {return type_is_emitted(t.get());} 794 795 /// Test if a given decl has been written out to the XML output. 796 /// 797 /// @param the decl to consider. 798 /// 799 /// @return true if the decl has already been emitted, false 800 /// otherwise. 801 bool 802 decl_is_emitted(const decl_base_sptr& decl) const 803 { 804 ABG_ASSERT(!is_type(decl)); 805 string repr = get_pretty_representation(decl, true); 806 interned_string irepr = decl->get_environment().intern(repr); 807 return m_emitted_decls_set.find(irepr) != m_emitted_decls_set.end(); 808 } 809 810 /// Record a declaration as emitted in the abixml output. 811 /// 812 /// @param decl the decl to consider. 813 void 814 record_decl_as_emitted(const decl_base_sptr& decl) 815 { 816 string repr = get_pretty_representation(decl, true); 817 interned_string irepr = decl->get_environment().intern(repr); 818 m_emitted_decls_set.insert(irepr); 819 } 820 821 /// Get the set of types that have been emitted. 822 /// 823 /// @return the set of types that have been emitted. 824 const type_ptr_set_type& 825 get_emitted_types_set() const 826 {return m_emitted_type_set;} 827 828 /// Clear the map that contains the IDs of the types that has been 829 /// recorded as having been written out to the XML output. 830 void 831 clear_referenced_types() 832 { 833 m_referenced_types_set.clear(); 834 m_referenced_fn_types_set.clear(); 835 } 836 837 const string_elf_symbol_sptr_map_type& 838 get_fun_symbol_map() const 839 {return m_fun_symbol_map;} 840 841 string_elf_symbol_sptr_map_type& 842 get_fun_symbol_map() 843 {return m_fun_symbol_map;} 844 845};//end write_context 846 847static void write_location(const location&, write_context&); 848static void write_location(const decl_base_sptr&, write_context&); 849static bool write_visibility(const decl_base_sptr&, ostream&); 850static bool write_binding(const decl_base_sptr&, ostream&); 851static bool write_is_artificial(const decl_base_sptr&, ostream&); 852static bool write_is_non_reachable(const type_base_sptr&, ostream&); 853static bool write_tracking_non_reachable_types(const corpus_sptr&, ostream&); 854static void write_array_size_and_alignment(const array_type_def_sptr, 855 ostream&); 856static void write_size_and_alignment(const type_base_sptr, ostream&, 857 size_t default_size = 0, 858 size_t default_alignment = 0); 859static void write_access(access_specifier, ostream&); 860static void write_layout_offset(var_decl_sptr, ostream&); 861static void write_layout_offset(class_decl::base_spec_sptr, ostream&); 862static void write_cdtor_const_static(bool, bool, bool, bool, ostream&); 863static void write_voffset(function_decl_sptr, ostream&); 864static void write_elf_symbol_type(elf_symbol::type, ostream&); 865static void write_elf_symbol_binding(elf_symbol::binding, ostream&); 866static bool write_elf_symbol_aliases(const elf_symbol&, ostream&); 867static bool write_elf_symbol_reference(const elf_symbol&, ostream&); 868static bool write_elf_symbol_reference(const elf_symbol_sptr, ostream&); 869static void write_is_declaration_only(const decl_base_sptr&, ostream&); 870static void write_is_struct(const class_decl_sptr&, ostream&); 871static void write_is_anonymous(const decl_base_sptr&, ostream&); 872static void write_naming_typedef(const decl_base_sptr&, write_context&); 873static bool write_decl(const decl_base_sptr&, write_context&, unsigned); 874static void write_decl_in_scope(const decl_base_sptr&, 875 write_context&, unsigned); 876static bool write_type_decl(const type_decl_sptr&, write_context&, unsigned); 877static bool write_namespace_decl(const namespace_decl_sptr&, 878 write_context&, unsigned); 879static bool write_qualified_type_def(const qualified_type_def_sptr&, 880 write_context&, unsigned); 881static bool write_pointer_type_def(const pointer_type_def_sptr&, 882 write_context&, unsigned); 883static bool write_reference_type_def(const reference_type_def_sptr&, 884 write_context&, unsigned); 885static bool write_array_type_def(const array_type_def_sptr&, 886 write_context&, unsigned); 887static bool write_enum_type_decl(const enum_type_decl_sptr&, 888 write_context&, unsigned); 889static bool write_typedef_decl(const typedef_decl_sptr&, 890 write_context&, unsigned); 891static bool write_elf_symbol(const elf_symbol_sptr&, 892 write_context&, unsigned); 893static bool write_elf_symbols_table(const elf_symbols&, 894 write_context&, unsigned); 895static bool write_var_decl(const var_decl_sptr&, 896 write_context&, bool, unsigned); 897static bool write_function_decl(const function_decl_sptr&, 898 write_context&, bool, unsigned); 899static bool write_function_type(const function_type_sptr&, 900 write_context&, unsigned); 901static bool write_member_type_opening_tag(const type_base_sptr&, 902 write_context&, unsigned); 903static bool write_member_type(const type_base_sptr&, 904 write_context&, unsigned); 905static bool write_class_decl_opening_tag(const class_decl_sptr&, const string&, 906 write_context&, unsigned, bool); 907static bool write_class_decl(const class_decl_sptr&, 908 write_context&, unsigned); 909static bool write_union_decl_opening_tag(const union_decl_sptr&, const string&, 910 write_context&, unsigned, bool); 911static bool write_union_decl(const union_decl_sptr&, const string&, 912 write_context&, unsigned); 913static bool write_union_decl(const union_decl_sptr&, write_context&, unsigned); 914static bool write_type_tparameter 915(const shared_ptr<type_tparameter>, write_context&, unsigned); 916static bool write_non_type_tparameter 917(const shared_ptr<non_type_tparameter>, write_context&, unsigned); 918static bool write_template_tparameter 919(const shared_ptr<template_tparameter>, write_context&, unsigned); 920static bool write_type_composition 921(const shared_ptr<type_composition>, write_context&, unsigned); 922static bool write_template_parameter(const shared_ptr<template_parameter>, 923 write_context&, unsigned); 924static void write_template_parameters(const shared_ptr<template_decl>, 925 write_context&, unsigned); 926static bool write_function_tdecl 927(const shared_ptr<function_tdecl>, 928 write_context&, unsigned); 929static bool write_class_tdecl 930(const shared_ptr<class_tdecl>, 931 write_context&, unsigned); 932static void do_indent(ostream&, unsigned); 933static void do_indent_to_level(write_context&, unsigned, unsigned); 934static unsigned get_indent_to_level(write_context&, unsigned, unsigned); 935 936/// Emit nb_whitespaces white spaces into the output stream. 937void 938do_indent(ostream& o, unsigned nb_whitespaces) 939{ 940 for (unsigned i = 0; i < nb_whitespaces; ++i) 941 o << ' '; 942} 943 944/// Indent initial_indent + level number of xml element indentation. 945/// 946/// @param ctxt the context of the parsing. 947/// 948/// @param initial_indent the initial number of white space to indent to. 949/// 950/// @param level the number of indentation level to indent to. 951static void 952do_indent_to_level(write_context& ctxt, 953 unsigned initial_indent, 954 unsigned level) 955{ 956 do_indent(ctxt.get_ostream(), 957 get_indent_to_level(ctxt, initial_indent, level)); 958} 959 960/// Return the number of white space of indentation that 961/// #do_indent_to_level would have used. 962/// 963/// @param ctxt the context of the parsing. 964/// 965/// @param initial_indent the initial number of white space to indent to. 966/// 967/// @param level the number of indentation level to indent to. 968static unsigned 969get_indent_to_level(write_context& ctxt, unsigned initial_indent, 970 unsigned level) 971{ 972 int nb_ws = initial_indent + 973 level * ctxt.get_config().get_xml_element_indent(); 974 return nb_ws; 975} 976 977/// Annotate a declaration in form of an ABIXML comment. 978/// 979/// This function is further specialized for declarations and types 980/// with special requirements. 981/// 982/// @tparam T shall be of type decl_base_sptr or a shared pointer to a 983/// type derived from it, for the instantiation to be syntactically 984/// correct. 985/// 986/// @param decl_sptr the shared pointer to the declaration of type T. 987/// 988/// @param ctxt the context of the parsing. 989/// 990/// @param indent the amount of white space to indent to. 991/// 992/// @return true iff decl is valid. 993template <typename T> 994static bool 995annotate(const T& decl, 996 write_context& ctxt, 997 unsigned indent) 998{ 999 if (!decl) 1000 return false; 1001 1002 if (!ctxt.get_annotate()) 1003 return true; 1004 1005 ostream& o = ctxt.get_ostream(); 1006 1007 do_indent(o, indent); 1008 1009 o << "<!-- " 1010 << xml::escape_xml_comment(decl->get_pretty_representation(/*internal=*/false)) 1011 << " -->\n"; 1012 1013 return true; 1014} 1015 1016/// Annotate an elf symbol in form of an ABIXML comment, effectively 1017/// writing out its demangled form. 1018/// 1019/// @param sym the symbol, whose name should be demangled. 1020/// 1021/// @param ctxt the context of the parsing. 1022/// 1023/// @param indent the amount of white space to indent to. 1024/// 1025/// @return true iff decl is valid 1026template<> 1027bool 1028annotate(const elf_symbol_sptr& sym, 1029 write_context& ctxt, 1030 unsigned indent) 1031{ 1032 if (!sym) 1033 return false; 1034 1035 if (!ctxt.get_annotate()) 1036 return true; 1037 1038 ostream& o = ctxt.get_ostream(); 1039 1040 do_indent(o, indent); 1041 o << "<!-- " 1042 << xml::escape_xml_comment(abigail::ir::demangle_cplus_mangled_name(sym->get_name())) 1043 << " -->\n"; 1044 1045 return true; 1046} 1047 1048/// Annotate a typedef declaration in form of an ABIXML comment. 1049/// 1050/// @param typedef_decl the typedef to annotate. 1051/// 1052/// @param ctxt the context of the parsing. 1053/// 1054/// @param indent the amount of white space to indent to. 1055/// 1056/// @return true iff decl is valid 1057template<> 1058bool 1059annotate(const typedef_decl_sptr& typedef_decl, 1060 write_context& ctxt, 1061 unsigned indent) 1062{ 1063 if (!typedef_decl) 1064 return false; 1065 1066 if (!ctxt.get_annotate()) 1067 return true; 1068 1069 ostream& o = ctxt.get_ostream(); 1070 1071 do_indent(o, indent); 1072 1073 o << "<!-- typedef " 1074 << get_type_name(typedef_decl->get_underlying_type()) 1075 << " " 1076 << get_type_name(typedef_decl) 1077 << " -->\n"; 1078 1079 return true; 1080} 1081 1082/// Annotate a function type in form of an ABIXML comment. 1083/// 1084/// @param function_type the function type to annotate. 1085/// 1086/// @param ctxt the context of the parsing. 1087/// 1088/// @param indent the amount of white space to indent to. 1089/// 1090/// @param skip_first_parm if true, do not serialize the first 1091/// parameter of the function decl. 1092// 1093/// @return true iff decl is valid 1094bool 1095annotate(const function_type_sptr& function_type, 1096 write_context& ctxt, 1097 unsigned indent) 1098{ 1099 if (!function_type) 1100 return false; 1101 1102 if (!ctxt.get_annotate()) 1103 return true; 1104 1105 ostream& o = ctxt.get_ostream(); 1106 1107 do_indent(o, indent); 1108 o << "<!-- " 1109 << xml::escape_xml_comment(get_type_name(function_type->get_return_type())) 1110 << " ("; 1111 1112 vector<shared_ptr<function_decl::parameter> >::const_iterator pi = 1113 function_type->get_first_non_implicit_parm(); 1114 1115 for (; pi != function_type->get_parameters().end(); ++pi) 1116 { 1117 o << xml::escape_xml_comment((*pi)->get_type_name()); 1118 // emit a comma after a param type, unless it's the last one 1119 if (distance(pi, function_type->get_parameters().end()) > 1) 1120 o << ", "; 1121 } 1122 o << ") -->\n"; 1123 1124 return true; 1125} 1126 1127/// Annotate a function declaration in form of an ABIXML comment. 1128/// 1129/// @param fn the function decl to annotate. 1130/// 1131/// @param ctxt the context of the parsing. 1132/// 1133/// @param indent the amount of white space to indent to. 1134/// 1135/// @param skip_first_parm if true, do not serialize the first 1136/// parameter of the function decl. 1137// 1138/// @return true iff decl is valid 1139static bool 1140annotate(const function_decl_sptr& fn, 1141 write_context& ctxt, 1142 unsigned indent) 1143{ 1144 if (!fn) 1145 return false; 1146 1147 if (!ctxt.get_annotate()) 1148 return true; 1149 1150 ostream& o = ctxt.get_ostream(); 1151 1152 do_indent(o, indent); 1153 o << "<!-- "; 1154 1155 if (is_member_function(fn) 1156 && (get_member_function_is_ctor(fn) || get_member_function_is_dtor(fn))) 1157 ; // we don't emit return types for ctor or dtors 1158 else 1159 o << xml::escape_xml_comment(get_type_name(fn->get_return_type())) 1160 << " "; 1161 1162 o << xml::escape_xml_comment(fn->get_qualified_name()) << "("; 1163 1164 vector<function_decl::parameter_sptr>::const_iterator pi = 1165 fn->get_first_non_implicit_parm(); 1166 1167 for (; pi != fn->get_parameters().end(); ++pi) 1168 { 1169 o << xml::escape_xml_comment((*pi)->get_type_name()); 1170 // emit a comma after a param type, unless it's the last one 1171 if (distance(pi, fn->get_parameters().end()) > 1) 1172 o << ", "; 1173 } 1174 o << ") -->\n"; 1175 1176 return true; 1177} 1178 1179/// Annotate a function parameter in form of an ABIXML comment. 1180/// 1181/// @param parm the function parameter to annotate. 1182/// 1183/// @param ctxt the context of the parsing. 1184/// 1185/// @param indent the amount of white space to indent to. 1186/// 1187/// @return true iff decl is valid 1188template<> 1189bool 1190annotate(const function_decl::parameter_sptr& parm, 1191 write_context& ctxt, 1192 unsigned indent) 1193{ 1194 if (!parm) 1195 return false; 1196 1197 if (!ctxt.get_annotate()) 1198 return true; 1199 1200 ostream &o = ctxt.get_ostream(); 1201 1202 do_indent(o, indent); 1203 1204 o << "<!-- "; 1205 1206 if (parm->get_variadic_marker()) 1207 o << "variadic parameter"; 1208 else 1209 { 1210 if (parm->get_is_artificial()) 1211 { 1212 if (parm->get_index() == 0) 1213 o << "implicit "; 1214 else 1215 o << "artificial "; 1216 } 1217 o << "parameter of type '" 1218 << xml::escape_xml_comment(get_pretty_representation(parm->get_type())); 1219 } 1220 1221 o << "' -->\n"; 1222 1223 return true; 1224} 1225 1226/// Write a location to the output stream. 1227/// 1228/// If the location is empty, nothing is written. 1229/// 1230/// @param loc the location to consider. 1231/// 1232/// @param tu the translation unit the location belongs to. 1233/// 1234/// @param ctxt the writer context to use. 1235static void 1236write_location(const location& loc, write_context& ctxt) 1237{ 1238 if (!loc || loc.get_is_artificial()) 1239 return; 1240 1241 if (!ctxt.get_show_locs()) 1242 return; 1243 1244 string filepath; 1245 unsigned line = 0, column = 0; 1246 1247 loc.expand(filepath, line, column); 1248 1249 ostream &o = ctxt.get_ostream(); 1250 1251 if (ctxt.get_short_locs()) 1252 tools_utils::base_name(filepath, filepath); 1253 1254 o << " filepath='" << xml::escape_xml_string(filepath) << "'" 1255 << " line='" << line << "'" 1256 << " column='" << column << "'"; 1257} 1258 1259/// Write the location of a decl to the output stream. 1260/// 1261/// If the location is empty, nothing is written. 1262/// 1263/// @param decl the decl to consider. 1264/// 1265/// @param ctxt the @ref writer_context to use. 1266static void 1267write_location(const decl_base_sptr& decl, 1268 write_context& ctxt) 1269{ 1270 if (!decl) 1271 return; 1272 1273 location loc = decl->get_location(); 1274 if (!loc) 1275 return; 1276 1277 write_location(loc, ctxt); 1278} 1279 1280/// Serialize the visibility property of the current decl as the 1281/// 'visibility' attribute for the current xml element. 1282/// 1283/// @param decl the instance of decl_base to consider. 1284/// 1285/// @param o the output stream to serialize the property to. 1286/// 1287/// @return true upon successful completion, false otherwise. 1288static bool 1289write_visibility(const shared_ptr<decl_base>& decl, ostream& o) 1290{ 1291 if (!decl) 1292 return false; 1293 1294 decl_base::visibility v = decl->get_visibility(); 1295 string str; 1296 1297 switch (v) 1298 { 1299 case decl_base::VISIBILITY_NONE: 1300 return true; 1301 case decl_base::VISIBILITY_DEFAULT: 1302 str = "default"; 1303 break; 1304 case decl_base::VISIBILITY_PROTECTED: 1305 str = "protected"; 1306 break; 1307 case decl_base::VISIBILITY_HIDDEN: 1308 str = "hidden"; 1309 break; 1310 case decl_base::VISIBILITY_INTERNAL: 1311 str = "internal"; 1312 break; 1313 } 1314 1315 if (str.empty()) 1316 return false; 1317 1318 o << " visibility='" << str << "'"; 1319 1320 return true; 1321} 1322 1323/// Serialize the 'binding' property of the current decl. 1324/// 1325/// @param decl the decl to consider. 1326/// 1327/// @param o the output stream to serialize the property to. 1328static bool 1329write_binding(const shared_ptr<decl_base>& decl, ostream& o) 1330{ 1331 if (!decl) 1332 return false; 1333 1334 decl_base::binding bind = decl_base::BINDING_NONE; 1335 1336 shared_ptr<var_decl> var = 1337 dynamic_pointer_cast<var_decl>(decl); 1338 if (var) 1339 bind = var->get_binding(); 1340 else 1341 { 1342 shared_ptr<function_decl> fun = 1343 dynamic_pointer_cast<function_decl>(decl); 1344 if (fun) 1345 bind = fun->get_binding(); 1346 } 1347 1348 string str; 1349 switch (bind) 1350 { 1351 case decl_base::BINDING_NONE: 1352 break; 1353 case decl_base::BINDING_LOCAL: 1354 str = "local"; 1355 break; 1356 case decl_base::BINDING_GLOBAL: 1357 str = "global"; 1358 break; 1359 case decl_base::BINDING_WEAK: 1360 str = "weak"; 1361 break; 1362 } 1363 1364 if (!str.empty()) 1365 o << " binding='" << str << "'"; 1366 1367 return true; 1368} 1369 1370/// Write the "is-artificial" attribute of the @ref decl. 1371/// 1372/// @param decl the declaration to consider. 1373/// 1374/// @param o the output stream to emit the "is-artificial" attribute 1375/// to. 1376/// 1377/// @return true iff the "is-artificial" attribute was emitted. 1378static bool 1379write_is_artificial(const decl_base_sptr& decl, ostream& o) 1380{ 1381 if (!decl) 1382 return false; 1383 1384 if (decl->get_is_artificial()) 1385 o << " is-artificial='yes'"; 1386 1387 return true; 1388} 1389 1390/// Write the 'is-non-reachable' attribute if a given type we are 1391/// looking at is not reachable from global functions and variables 1392/// and if the user asked us to track that information. 1393/// 1394/// @param t the type to consider. 1395/// 1396/// @param o the output stream to write the 'is-non-reachable' 1397/// attribute to. 1398static bool 1399write_is_non_reachable(const type_base_sptr& t, ostream& o) 1400{ 1401 if (!t) 1402 return false; 1403 1404 corpus* c = t->get_corpus(); 1405 if (!c) 1406 return false; 1407 1408 if (!c->recording_types_reachable_from_public_interface_supported() 1409 || c->type_is_reachable_from_public_interfaces(*t)) 1410 return false; 1411 1412 o << " is-non-reachable='yes'"; 1413 1414 return true; 1415} 1416 1417/// Write the 'tracking-non-reachable-types' attribute if for a given 1418/// corpus, the user wants us to track non-reachable types. 1419/// 1420/// @param corpus the ABI corpus to consider. 1421/// 1422/// @param o the output parameter to write the 1423/// 'tracking-non-reachable-types' attribute to. 1424static bool 1425write_tracking_non_reachable_types(const corpus_sptr& corpus, 1426 ostream& o) 1427{ 1428 corpus_group* group = corpus->get_group(); 1429 if (!group) 1430 if (corpus->recording_types_reachable_from_public_interface_supported()) 1431 { 1432 o << " tracking-non-reachable-types='yes'"; 1433 return true; 1434 } 1435 1436 return false; 1437} 1438 1439/// Serialize the size and alignment attributes of a given type. 1440/// 1441/// @param decl the type to consider. 1442/// 1443/// @param o the output stream to serialize to. 1444/// 1445/// @param default_size size in bits that is the default for the type. 1446/// No size-in-bits attribute is written if it 1447/// would be the default value. 1448/// 1449/// @param default_alignment alignment in bits that is the default for 1450/// the type. No alignment-in-bits attribute is 1451/// written if it would be the default value. 1452static void 1453write_size_and_alignment(const shared_ptr<type_base> decl, ostream& o, 1454 size_t default_size, size_t default_alignment) 1455{ 1456 size_t size_in_bits = decl->get_size_in_bits(); 1457 if (size_in_bits != default_size) 1458 o << " size-in-bits='" << size_in_bits << "'"; 1459 1460 size_t alignment_in_bits = decl->get_alignment_in_bits(); 1461 if (alignment_in_bits != default_alignment) 1462 o << " alignment-in-bits='" << alignment_in_bits << "'"; 1463} 1464 1465/// Serialize the size and alignment attributes of a given type. 1466/// @param decl the type to consider. 1467/// 1468/// @param o the output stream to serialize to. 1469static void 1470write_array_size_and_alignment(const shared_ptr<array_type_def> decl, ostream& o) 1471{ 1472 if (decl->is_infinite()) 1473 o << " size-in-bits='" << "infinite" << "'"; 1474 else { 1475 size_t size_in_bits = decl->get_size_in_bits(); 1476 if (size_in_bits) 1477 o << " size-in-bits='" << size_in_bits << "'"; 1478 } 1479 1480 size_t alignment_in_bits = decl->get_alignment_in_bits(); 1481 if (alignment_in_bits) 1482 o << " alignment-in-bits='" << alignment_in_bits << "'"; 1483} 1484/// Serialize the access specifier. 1485/// 1486/// @param a the access specifier to serialize. 1487/// 1488/// @param o the output stream to serialize it to. 1489static void 1490write_access(access_specifier a, ostream& o) 1491{ 1492 string access_str = "private"; 1493 1494 switch (a) 1495 { 1496 case private_access: 1497 access_str = "private"; 1498 break; 1499 1500 case protected_access: 1501 access_str = "protected"; 1502 break; 1503 1504 case public_access: 1505 access_str = "public"; 1506 break; 1507 1508 default: 1509 break; 1510 } 1511 1512 o << " access='" << access_str << "'"; 1513} 1514 1515/// Serialize the layout offset of a data member. 1516static void 1517write_layout_offset(var_decl_sptr member, ostream& o) 1518{ 1519 if (!is_data_member(member)) 1520 return; 1521 1522 if (get_data_member_is_laid_out(member)) 1523 o << " layout-offset-in-bits='" 1524 << get_data_member_offset(member) 1525 << "'"; 1526} 1527 1528/// Serialize the layout offset of a base class 1529static void 1530write_layout_offset(shared_ptr<class_decl::base_spec> base, ostream& o) 1531{ 1532 if (!base) 1533 return; 1534 1535 if (base->get_offset_in_bits() >= 0) 1536 o << " layout-offset-in-bits='" << base->get_offset_in_bits() << "'"; 1537} 1538 1539/// Serialize the access specifier of a class member. 1540/// 1541/// @param member a pointer to the class member to consider. 1542/// 1543/// @param o the ostream to serialize the member to. 1544static void 1545write_access(decl_base_sptr member, ostream& o) 1546{write_access(get_member_access_specifier(member), o);} 1547 1548/// Write the voffset of a member function if it's non-zero 1549/// 1550/// @param fn the member function to consider 1551/// 1552/// @param o the output stream to write to 1553static void 1554write_voffset(function_decl_sptr fn, ostream&o) 1555{ 1556 if (!fn) 1557 return; 1558 1559 if (get_member_function_is_virtual(fn)) 1560 { 1561 ssize_t voffset = get_member_function_vtable_offset(fn); 1562 o << " vtable-offset='" << voffset << "'"; 1563 } 1564} 1565 1566/// Serialize an elf_symbol::type into an XML node attribute named 1567/// 'type'. 1568/// 1569/// @param t the elf_symbol::type to serialize. 1570/// 1571/// @param o the output stream to serialize it to. 1572static void 1573write_elf_symbol_type(elf_symbol::type t, ostream& o) 1574{ 1575 string repr; 1576 1577 switch (t) 1578 { 1579 case elf_symbol::NOTYPE_TYPE: 1580 repr = "no-type"; 1581 break; 1582 case elf_symbol::OBJECT_TYPE: 1583 repr = "object-type"; 1584 break; 1585 case elf_symbol::FUNC_TYPE: 1586 repr = "func-type"; 1587 break; 1588 case elf_symbol::SECTION_TYPE: 1589 repr = "section-type"; 1590 break; 1591 case elf_symbol::FILE_TYPE: 1592 repr = "file-type"; 1593 break; 1594 case elf_symbol::COMMON_TYPE: 1595 repr = "common-type"; 1596 break; 1597 case elf_symbol::TLS_TYPE: 1598 repr = "tls-type"; 1599 break; 1600 case elf_symbol::GNU_IFUNC_TYPE: 1601 repr = "gnu-ifunc-type"; 1602 break; 1603 default: 1604 repr = "no-type"; 1605 break; 1606 } 1607 1608 o << " type='" << repr << "'"; 1609} 1610 1611/// Serialize an elf_symbol::binding into an XML element attribute of 1612/// name 'binding'. 1613/// 1614/// @param b the elf_symbol::binding to serialize. 1615/// 1616/// @param o the output stream to serialize the binding to. 1617static void 1618write_elf_symbol_binding(elf_symbol::binding b, ostream& o) 1619{ 1620 string repr; 1621 1622 switch (b) 1623 { 1624 case elf_symbol::LOCAL_BINDING: 1625 repr = "local-binding"; 1626 break; 1627 case elf_symbol::GLOBAL_BINDING: 1628 repr = "global-binding"; 1629 break; 1630 case elf_symbol::WEAK_BINDING: 1631 repr = "weak-binding"; 1632 break; 1633 case elf_symbol::GNU_UNIQUE_BINDING: 1634 repr = "gnu-unique-binding"; 1635 break; 1636 default: 1637 repr = "no-binding"; 1638 break; 1639 } 1640 1641 o << " binding='" << repr << "'"; 1642} 1643 1644/// Serialize an elf_symbol::binding into an XML element attribute of 1645/// name 'binding'. 1646/// 1647/// @param b the elf_symbol::binding to serialize. 1648/// 1649/// @param o the output stream to serialize the binding to. 1650static void 1651write_elf_symbol_visibility(elf_symbol::visibility v, ostream& o) 1652{ 1653 string repr; 1654 1655 switch (v) 1656 { 1657 case elf_symbol::DEFAULT_VISIBILITY: 1658 repr = "default-visibility"; 1659 break; 1660 case elf_symbol::PROTECTED_VISIBILITY: 1661 repr = "protected-visibility"; 1662 break; 1663 case elf_symbol::HIDDEN_VISIBILITY: 1664 repr = "hidden-visibility"; 1665 break; 1666 case elf_symbol::INTERNAL_VISIBILITY: 1667 repr = "internal-visibility"; 1668 break; 1669 default: 1670 repr = "default-visibility"; 1671 break; 1672 } 1673 1674 o << " visibility='" << repr << "'"; 1675} 1676 1677/// Write alias attributes for the aliases of a given symbol. 1678/// 1679/// @param sym the symbol to write the attributes for. 1680/// 1681/// @param o the output stream to write the attributes to. 1682/// 1683/// @return true upon successful completion. 1684static bool 1685write_elf_symbol_aliases(const elf_symbol& sym, ostream& out) 1686{ 1687 if (!sym.is_main_symbol() || !sym.has_aliases()) 1688 return false; 1689 1690 1691 std::vector<std::string> aliases; 1692 for (elf_symbol_sptr s = sym.get_next_alias(); s && !s->is_main_symbol(); 1693 s = s->get_next_alias()) 1694 { 1695 if (!s->is_public()) 1696 continue; 1697 1698 if (s->is_suppressed()) 1699 continue; 1700 1701 if (sym.is_in_ksymtab() != s->is_in_ksymtab()) 1702 continue; 1703 1704 aliases.push_back(s->get_id_string()); 1705 } 1706 1707 if (!aliases.empty()) 1708 { 1709 out << " alias='"; 1710 std::string separator; 1711 for (const auto& alias : aliases) 1712 { 1713 out << separator << alias; 1714 separator = ","; 1715 } 1716 1717 out << "'"; 1718 return true; 1719 } 1720 1721 return false; 1722} 1723 1724/// Write an XML attribute for the reference to a symbol for the 1725/// current decl. 1726/// 1727/// @param sym the symbol to consider. 1728/// 1729/// @param o the output stream to write the attribute to. 1730/// 1731/// @return true upon successful completion. 1732static bool 1733write_elf_symbol_reference(const elf_symbol& sym, ostream& o) 1734{ 1735 const elf_symbol* main = sym.get_main_symbol().get(); 1736 const elf_symbol* alias = &sym; 1737 bool found = !alias->is_suppressed(); 1738 // If the symbol itself is suppressed, check the alias chain. 1739 if (!found) 1740 { 1741 alias = main; 1742 found = !alias->is_suppressed(); 1743 } 1744 // If the main symbol is suppressed, search the remainder of the chain. 1745 while (!found) 1746 { 1747 alias = alias->get_next_alias().get(); 1748 // Two separate termination conditions at present. 1749 if (!alias || alias == main) 1750 break; 1751 found = !alias->is_suppressed(); 1752 } 1753 // If all aliases are suppressed, just stick with the main symbol. 1754 if (!found) 1755 alias = main; 1756 o << " elf-symbol-id='" 1757 << xml::escape_xml_string(alias->get_id_string()) 1758 << "'"; 1759 return true; 1760} 1761 1762/// Write an XML attribute for the reference to a symbol for the 1763/// current decl. 1764/// 1765/// @param sym the symbol to consider. 1766/// 1767/// @param o the output stream to write the attribute to. 1768/// 1769/// @return true upon successful completion. 1770static bool 1771write_elf_symbol_reference(const elf_symbol_sptr sym, ostream& o) 1772{ 1773 if (!sym) 1774 return false; 1775 1776 return write_elf_symbol_reference(*sym, o); 1777} 1778 1779/// Serialize the attributes "constructor", "destructor" or "static" 1780/// if they have true value. 1781/// 1782/// @param is_ctor if set to true, the "constructor='true'" string is 1783/// emitted. 1784/// 1785/// @param is_dtor if set to true the "destructor='true' string is 1786/// emitted. 1787/// 1788/// @param is_static if set to true the "static='true'" string is 1789/// emitted. 1790/// 1791/// @param o the output stream to use for the serialization. 1792static void 1793write_cdtor_const_static(bool is_ctor, 1794 bool is_dtor, 1795 bool is_const, 1796 bool is_static, 1797 ostream& o) 1798{ 1799 if (is_static) 1800 o << " static='yes'"; 1801 if (is_ctor) 1802 o << " constructor='yes'"; 1803 else if (is_dtor) 1804 o << " destructor='yes'"; 1805 if (is_const) 1806 o << " const='yes'"; 1807} 1808 1809/// Serialize the attribute "is-declaration-only", if the 1810/// decl_base_sptr has its 'is_declaration_only property set. 1811/// 1812/// @param t the pointer to instance of @ref decl_base to consider. 1813/// 1814/// @param o the output stream to serialize to. 1815static void 1816write_is_declaration_only(const decl_base_sptr& d, ostream& o) 1817{ 1818 if (d->get_is_declaration_only()) 1819 o << " is-declaration-only='yes'"; 1820} 1821 1822/// Serialize the attribute "is-struct", if the current instance of 1823/// class_decl is a struct. 1824/// 1825/// @param klass a pointer to the instance of class_decl to consider. 1826/// 1827/// @param o the output stream to serialize to. 1828static void 1829write_is_struct(const class_decl_sptr& klass, ostream& o) 1830{ 1831 if (klass->is_struct()) 1832 o << " is-struct='yes'"; 1833} 1834 1835/// Serialize the attribute "is-anonymous", if the current instance of 1836/// decl is anonymous 1837/// 1838/// @param dcl a pointer to the instance of @ref decl_base to consider. 1839/// 1840/// @param o the output stream to serialize to. 1841static void 1842write_is_anonymous(const decl_base_sptr& decl, ostream& o) 1843{ 1844 if (decl->get_is_anonymous()) 1845 o << " is-anonymous='yes'"; 1846} 1847 1848/// Serialize the "naming-typedef-id" attribute, if the current 1849/// instance of @ref class_decl has a naming typedef. 1850/// 1851/// @param klass the @ref class_decl to consider. 1852/// 1853/// @param ctxt the write context to use. 1854static void 1855write_naming_typedef(const decl_base_sptr& decl, write_context& ctxt) 1856{ 1857 if (!decl) 1858 return; 1859 1860 ostream &o = ctxt.get_ostream(); 1861 1862 if (typedef_decl_sptr typedef_type = decl->get_naming_typedef()) 1863 { 1864 string id = ctxt.get_id_for_type(typedef_type); 1865 o << " naming-typedef-id='" << id << "'"; 1866 ctxt.record_type_as_referenced(typedef_type); 1867 } 1868} 1869 1870/// Helper to serialize a type artifact. 1871/// 1872/// @param type the type to serialize. 1873/// 1874/// @param ctxt the @ref write_context to use. 1875/// 1876/// @param indent the number of white space to use for indentation. 1877/// 1878/// @return true upon successful completion. 1879static bool 1880write_type(const type_base_sptr& type, write_context& ctxt, unsigned indent) 1881{ 1882 if (write_type_decl(dynamic_pointer_cast<type_decl> (type), 1883 ctxt, indent) 1884 || write_qualified_type_def (dynamic_pointer_cast<qualified_type_def> 1885 (type), 1886 ctxt, indent) 1887 || write_pointer_type_def(dynamic_pointer_cast<pointer_type_def>(type), 1888 ctxt, indent) 1889 || write_reference_type_def(dynamic_pointer_cast 1890 <reference_type_def>(type), ctxt, indent) 1891 || write_array_type_def(dynamic_pointer_cast 1892 <array_type_def>(type), ctxt, indent) 1893 || write_enum_type_decl(dynamic_pointer_cast<enum_type_decl>(type), 1894 ctxt, indent) 1895 || write_typedef_decl(dynamic_pointer_cast<typedef_decl>(type), 1896 ctxt, indent) 1897 || write_class_decl(is_class_type(type), ctxt, indent) 1898 || write_union_decl(is_union_type(type), ctxt, indent) 1899 || (write_function_tdecl 1900 (dynamic_pointer_cast<function_tdecl>(type), ctxt, indent)) 1901 || (write_class_tdecl 1902 (dynamic_pointer_cast<class_tdecl>(type), ctxt, indent))) 1903 return true; 1904 1905 return false; 1906} 1907 1908/// Serialize a pointer to an of decl_base into an output stream. 1909/// 1910/// @param decl the pointer to decl_base to serialize 1911/// 1912/// @param ctxt the context of the serialization. It contains e.g, the 1913/// output stream to serialize to. 1914/// 1915/// @param indent how many indentation spaces to use during the 1916/// serialization. 1917/// 1918/// @return true upon successful completion, false otherwise. 1919static bool 1920write_decl(const decl_base_sptr& decl, write_context& ctxt, unsigned indent) 1921{ 1922 if (write_type_decl(dynamic_pointer_cast<type_decl> (decl), 1923 ctxt, indent) 1924 || write_namespace_decl(dynamic_pointer_cast<namespace_decl>(decl), 1925 ctxt, indent) 1926 || write_qualified_type_def (dynamic_pointer_cast<qualified_type_def> 1927 (decl), 1928 ctxt, indent) 1929 || write_pointer_type_def(dynamic_pointer_cast<pointer_type_def>(decl), 1930 ctxt, indent) 1931 || write_reference_type_def(dynamic_pointer_cast 1932 <reference_type_def>(decl), ctxt, indent) 1933 || write_array_type_def(dynamic_pointer_cast 1934 <array_type_def>(decl), ctxt, indent) 1935 || write_enum_type_decl(dynamic_pointer_cast<enum_type_decl>(decl), 1936 ctxt, indent) 1937 || write_typedef_decl(dynamic_pointer_cast<typedef_decl>(decl), 1938 ctxt, indent) 1939 || write_var_decl(dynamic_pointer_cast<var_decl>(decl), ctxt, 1940 /*write_linkage_name=*/true, indent) 1941 || write_function_decl(dynamic_pointer_cast<method_decl> 1942 (decl), ctxt, /*skip_first_parameter=*/true, 1943 indent) 1944 || write_function_decl(dynamic_pointer_cast<function_decl>(decl), 1945 ctxt, /*skip_first_parameter=*/false, indent) 1946 || write_class_decl(is_class_type(decl), ctxt, indent) 1947 || write_union_decl(is_union_type(decl), ctxt, indent) 1948 || (write_function_tdecl 1949 (dynamic_pointer_cast<function_tdecl>(decl), ctxt, indent)) 1950 || (write_class_tdecl 1951 (dynamic_pointer_cast<class_tdecl>(decl), ctxt, indent))) 1952 return true; 1953 1954 return false; 1955} 1956 1957/// Emit a declaration, along with its scope. 1958/// 1959/// This function is called at the end of emitting a translation unit, 1960/// to emit type declarations that were referenced by types that were 1961/// emitted in the TU already, but that were not emitted themselves. 1962/// 1963/// @param decl the decl to emit. 1964/// 1965/// @param ctxt the write context to use. 1966/// 1967/// @param initial_indent the number of indentation spaces to use. 1968static void 1969write_decl_in_scope(const decl_base_sptr& decl, 1970 write_context& ctxt, 1971 unsigned initial_indent) 1972{ 1973 type_base_sptr type = is_type(decl); 1974 ABG_ASSERT(type); 1975 1976 if (ctxt.type_is_emitted(type)) 1977 return; 1978 1979 list<scope_decl*> scopes; 1980 for (scope_decl* s = decl->get_scope(); 1981 s && !is_global_scope(s); 1982 s = s->get_scope()) 1983 scopes.push_front(s); 1984 1985 ostream& o = ctxt.get_ostream(); 1986 const config& c = ctxt.get_config(); 1987 stack<string> closing_tags; 1988 stack<unsigned> closing_indents; 1989 unsigned indent = initial_indent; 1990 for (list<scope_decl*>::const_iterator i = scopes.begin(); 1991 i != scopes.end(); 1992 ++i) 1993 { 1994 ABG_ASSERT(!is_global_scope(*i)); 1995 1996 // A type scope is either a namespace ... 1997 if (namespace_decl* n = is_namespace(*i)) 1998 { 1999 do_indent(o, indent); 2000 o << "<namespace-decl name='" 2001 << xml::escape_xml_string(n->get_name()) 2002 << "'>\n"; 2003 closing_tags.push("</namespace-decl>"); 2004 closing_indents.push(indent); 2005 } 2006 // ... or a class. 2007 else if (class_decl* c = is_class_type(*i)) 2008 { 2009 c = is_class_type(look_through_decl_only_class(c)); 2010 class_decl_sptr class_type(c, noop_deleter()); 2011 write_class_decl_opening_tag(class_type, "", ctxt, indent, 2012 /*prepare_to_handle_empty=*/false); 2013 closing_tags.push("</class-decl>"); 2014 closing_indents.push(indent); 2015 2016 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1); 2017 write_member_type_opening_tag(type, ctxt, nb_ws); 2018 indent = nb_ws; 2019 closing_tags.push("</member-type>"); 2020 closing_indents.push(nb_ws); 2021 } 2022 else if (union_decl *u = is_union_type(*i)) 2023 { 2024 union_decl_sptr union_type(u, noop_deleter()); 2025 write_union_decl_opening_tag(union_type, "", ctxt, indent, 2026 /*prepare_to_handle_empty=*/false); 2027 closing_tags.push("</union-decl>"); 2028 closing_indents.push(indent); 2029 2030 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1); 2031 write_member_type_opening_tag(type, ctxt, nb_ws); 2032 indent = nb_ws; 2033 closing_tags.push("</member-type>"); 2034 closing_indents.push(nb_ws); 2035 } 2036 else 2037 // We should never reach this point. 2038 abort(); 2039 indent += c.get_xml_element_indent(); 2040 } 2041 2042 write_decl(decl, ctxt, indent); 2043 2044 while (!closing_tags.empty()) 2045 { 2046 do_indent(o, closing_indents.top()); 2047 o << closing_tags.top() << "\n"; 2048 closing_tags.pop(); 2049 closing_indents.pop(); 2050 } 2051} 2052 2053/// Create a @ref write_context object that can be used to emit abixml 2054/// files. 2055/// 2056/// @param env the environment for the @ref write_context object to use. 2057/// 2058/// @param default_output_stream the default output stream to use. 2059/// 2060/// @return the new @ref write_context object. 2061write_context_sptr 2062create_write_context(const environment& env, 2063 ostream& default_output_stream) 2064{ 2065 write_context_sptr ctxt(new write_context(env, default_output_stream)); 2066 return ctxt; 2067} 2068 2069/// Set the "show-locs" flag. 2070/// 2071/// When this flag is set then the XML writer emits location (/// 2072/// information (file name, line and column) for the ABI artifacts 2073/// that it emits. 2074/// 2075/// @param ctxt the @ref write_context to set the option for. 2076/// 2077/// @param flag the new value of the option. 2078void 2079set_show_locs(write_context& ctxt, bool flag) 2080{ctxt.set_show_locs(flag);} 2081 2082/// Set the 'annotate' flag. 2083/// 2084/// When this flag is set then the XML writer annotates ABI artifacts 2085/// with a human readable description. 2086/// 2087/// @param ctxt the context to set this flag on to. 2088/// 2089/// @param flag the new value of the 'annotate' flag. 2090void 2091set_annotate(write_context& ctxt, bool flag) 2092{ctxt.set_annotate(flag);} 2093 2094/// Set the new ostream. 2095/// 2096/// The ostream refers to the object, writers should stream new output to. 2097/// 2098/// @param ctxt the context to set this to. 2099/// 2100/// @param os the new ostream 2101void 2102set_ostream(write_context& ctxt, ostream& os) 2103{ctxt.set_ostream(os);} 2104 2105/// Set the 'write-architecture' flag. 2106/// 2107/// When this flag is set then the XML writer will emit architecture 2108/// information 2109/// 2110/// @param ctxt the context to set this flag on to. 2111/// 2112/// @param flag the new value of the 'write-architecture' flag. 2113void 2114set_write_architecture(write_context& ctxt, bool flag) 2115{ctxt.set_write_architecture(flag);} 2116 2117/// Set the 'write-corpus-path' flag. 2118/// 2119/// When this flag is set then the XML writer will emit corpus-path 2120/// information 2121/// 2122/// @param ctxt the context to set this flag on to. 2123/// 2124/// @param flag the new value of the 'write-corpus-path' flag. 2125void 2126set_write_corpus_path(write_context& ctxt, bool flag) 2127{ctxt.set_write_corpus_path(flag);} 2128 2129/// Set the 'write-comp-dir' flag. 2130/// 2131/// When this flag is set then the XML writer will emit compilation dir 2132/// information 2133/// 2134/// @param ctxt the context to set this flag on to. 2135/// 2136/// @param flag the new value of the 'write-comp-dir' flag. 2137void 2138set_write_comp_dir(write_context& ctxt, bool flag) 2139{ctxt.set_write_comp_dir(flag);} 2140 2141/// Set the 'short-locs' flag. 2142/// 2143/// When this flag is set then the XML writer will emit only file names 2144/// rather than full paths. 2145/// 2146/// @param ctxt the context to set this flag on to. 2147/// 2148/// @param flag the new value of the 'short-locs' flag. 2149void 2150set_short_locs(write_context& ctxt, bool flag) 2151{ctxt.set_short_locs(flag);} 2152 2153/// Set the 'parameter-names' flag. 2154/// 2155/// When this flag is set then the XML writer will emit the names of 2156/// function parameters. 2157/// 2158/// @param ctxt the context to set this flag on to. 2159/// 2160/// @param flag the new value of the 'parameter-names' flag. 2161void 2162set_write_parameter_names(write_context& ctxt, bool flag) 2163{ctxt.set_write_parameter_names(flag);} 2164 2165/// Set the 'elf-needed' flag. 2166/// 2167/// When this flag is set then the XML writer will emit corpus 2168/// get_needed() (DT_NEEDED) information. 2169/// 2170/// @param ctxt the context to set this flag on to. 2171/// 2172/// @param flag the new value of the 'elf-needed' flag. 2173void 2174set_write_elf_needed(write_context& ctxt, bool flag) 2175{ctxt.set_write_elf_needed(flag);} 2176 2177/// Set the 'default-sizes' flag. 2178/// 2179/// When this flag is set then the XML writer will emit default 2180/// size-in-bits attributes for pointer type definitions, reference 2181/// type definitions, function declarations and function types even 2182/// when they are equal to the default address size of the translation 2183/// unit. 2184/// 2185/// @param ctxt the context to set this flag on to. 2186/// 2187/// @param flag the new value of the 'default-sizes' flag. 2188void 2189set_write_default_sizes(write_context& ctxt, bool flag) 2190{ctxt.set_write_default_sizes(flag);} 2191 2192/// Set the 'type-id-style' property. 2193/// 2194/// This property controls the kind of type ids used in XML output. 2195/// 2196/// @param ctxt the context to set this property on. 2197/// 2198/// @param style the new value of the 'type-id-style' property. 2199void 2200set_type_id_style(write_context& ctxt, type_id_style_kind style) 2201{ctxt.set_type_id_style(style);} 2202 2203/// Serialize the canonical types of a given scope. 2204/// 2205/// @param scope the scope to consider. 2206/// 2207/// @param ctxt the write context to use. 2208/// 2209/// @param indent the number of white space indentation to use. 2210 // 2211 // @param is_member_type if true, the canonical types are emitted as 2212 // member types (of a class). 2213 // 2214 // return true upon successful completion. 2215static bool 2216write_canonical_types_of_scope(const scope_decl &scope, 2217 write_context &ctxt, 2218 const unsigned indent, 2219 bool is_member_type = false) 2220{ 2221 const type_base_sptrs_type &canonical_types = 2222 scope.get_sorted_canonical_types(); 2223 2224 for (type_base_sptrs_type::const_iterator i = canonical_types.begin(); 2225 i != canonical_types.end(); 2226 ++i) 2227 { 2228 if (is_member_type) 2229 write_member_type(*i, ctxt, indent); 2230 else 2231 write_type(*i, ctxt, indent); 2232 } 2233 2234 return true; 2235} 2236 2237/// Test if a type referenced in a given translation unit should be 2238/// emitted or not. 2239/// 2240/// This is a subroutine of @ref write_translation_unit. 2241/// 2242/// @param t the type to consider. 2243/// 2244/// @param ctxt the write context to consider. 2245/// 2246/// @param tu the translation unit to consider. 2247/// 2248/// @param tu_is_last true if @p tu is the last translation unit being 2249/// emitted. 2250/// 2251/// @return true iff @p t is to be emitted. 2252static bool 2253referenced_type_should_be_emitted(const type_base *t, 2254 const write_context& ctxt, 2255 const translation_unit& tu, 2256 bool tu_is_last) 2257{ 2258 if ((tu_is_last || (t->get_translation_unit() 2259 && (t->get_translation_unit()->get_absolute_path() 2260 == tu.get_absolute_path()))) 2261 && !ctxt.type_is_emitted(t)) 2262 return true; 2263 return false; 2264} 2265 2266/// Emit the types that were referenced by other emitted types. 2267/// 2268/// This is a sub-routine of write_translation_unit. 2269/// 2270/// @param ctxt the write context to use. 2271/// 2272/// @param tu the current translation unit that is being emitted. 2273/// 2274/// @param indent the indentation string. 2275/// 2276/// @param is_last whether @p tu is the last translation unit or not. 2277static void 2278write_referenced_types(write_context & ctxt, 2279 const translation_unit& tu, 2280 const unsigned indent, 2281 bool is_last) 2282{ 2283 const config& c = ctxt.get_config(); 2284 // Now let's handle types that were referenced, but not yet 2285 // emitted because they are either: 2286 // 1/ Types without canonical type 2287 // 2/ or function types (these might have no scope). 2288 2289 // So this map of type -> string is to contain the referenced types 2290 // we need to emit. 2291 type_ptr_set_type referenced_types_to_emit; 2292 2293 // For each referenced type, ensure that it is either emitted in the 2294 // translation unit to which it belongs or in the last translation 2295 // unit as a last resort. 2296 for (type_ptr_set_type::const_iterator i = 2297 ctxt.get_referenced_types().begin(); 2298 i != ctxt.get_referenced_types().end(); 2299 ++i) 2300 if (referenced_type_should_be_emitted(*i, ctxt, tu, is_last)) 2301 referenced_types_to_emit.insert(*i); 2302 2303 for (fn_type_ptr_set_type::const_iterator i = 2304 ctxt.get_referenced_function_types().begin(); 2305 i != ctxt.get_referenced_function_types().end(); 2306 ++i) 2307 if (referenced_type_should_be_emitted(*i, ctxt, tu, is_last)) 2308 referenced_types_to_emit.insert(*i); 2309 2310 // Ok, now let's emit the referenced type for good. 2311 while (!referenced_types_to_emit.empty()) 2312 { 2313 // But first, we need to sort them, otherwise, emitting the ABI 2314 // (in xml) of the same binary twice will yield different 2315 // results, because we'd be walking an *unordered* hash table. 2316 vector<type_base*> sorted_referenced_types; 2317 ctxt.sort_types(referenced_types_to_emit, 2318 sorted_referenced_types); 2319 2320 // Now, emit the referenced decls in a sorted order. 2321 for (vector<type_base*>::const_iterator i = 2322 sorted_referenced_types.begin(); 2323 i != sorted_referenced_types.end(); 2324 ++i) 2325 { 2326 // We handle types which have declarations *and* function 2327 // types here. 2328 type_base* t = *i; 2329 if (!ctxt.type_is_emitted(t)) 2330 { 2331 if (decl_base* d = get_type_declaration(t)) 2332 { 2333 decl_base_sptr decl(d, noop_deleter()); 2334 write_decl_in_scope(decl, ctxt, 2335 indent + c.get_xml_element_indent()); 2336 } 2337 else if (function_type* f = is_function_type(t)) 2338 { 2339 function_type_sptr fn_type(f, noop_deleter()); 2340 write_function_type(fn_type, ctxt, 2341 indent + c.get_xml_element_indent()); 2342 } 2343 else 2344 ABG_ASSERT_NOT_REACHED; 2345 } 2346 } 2347 2348 // So all the (referenced) types that we wanted to emit were 2349 // emitted. 2350 referenced_types_to_emit.clear(); 2351 2352 // But then, while emitting those referenced type, other types 2353 // might have been referenced by those referenced types 2354 // themselves! So let's look at the sets of referenced type 2355 // that are maintained for the entire ABI corpus and see if 2356 // there are still some referenced types in there that are not 2357 // emitted yet. If yes, then we'll emit those again. 2358 2359 // For each referenced type, ensure that it is either emitted in 2360 // the translation unit to which it belongs or in the last 2361 // translation unit as a last resort. 2362 for (type_ptr_set_type::const_iterator i = 2363 ctxt.get_referenced_types().begin(); 2364 i != ctxt.get_referenced_types().end(); 2365 ++i) 2366 if (referenced_type_should_be_emitted(*i, ctxt, tu, is_last)) 2367 referenced_types_to_emit.insert(*i); 2368 } 2369} 2370 2371/// Serialize a translation unit to an output stream. 2372/// 2373/// @param ctxt the context of the serialization. It contains e.g, 2374/// the output stream to serialize to. 2375/// 2376/// @param tu the translation unit to serialize. 2377/// 2378/// @param indent how many indentation spaces to use during the 2379/// serialization. 2380/// 2381/// @param is_last If true, it means the TU to emit is the last one of 2382/// the corpus. If this is the case, all the remaining referenced 2383/// types that were not emitted are going to be emitted here, 2384/// irrespective of if they belong to this TU or not. This is quite a 2385/// hack. Ideally, we should have a pass that walks all the TUs, 2386/// detect their non-emitted referenced types, before hand. Then, 2387/// when we start emitting the TUs, we know for each TU which 2388/// non-emitted referenced type should be emitted. As we don't yet 2389/// have such a pass, we do our best for now. 2390/// 2391/// @return true upon successful completion, false otherwise. 2392bool 2393write_translation_unit(write_context& ctxt, 2394 const translation_unit& tu, 2395 const unsigned indent, 2396 bool is_last) 2397{ 2398 if (tu.is_empty() && !is_last) 2399 return false; 2400 2401 if (is_last 2402 && tu.is_empty() 2403 && ctxt.has_non_emitted_referenced_types()) 2404 return false; 2405 2406 ostream& o = ctxt.get_ostream(); 2407 const config& c = ctxt.get_config(); 2408 2409 do_indent(o, indent); 2410 2411 o << "<abi-instr"; 2412 2413 if (tu.get_address_size() != 0) 2414 o << " address-size='" << static_cast<int>(tu.get_address_size()) << "'"; 2415 2416 std::string tu_path = tu.get_path(); 2417 if (ctxt.get_short_locs()) 2418 tools_utils::base_name(tu_path, tu_path); 2419 if (!tu_path.empty()) 2420 o << " path='" << xml::escape_xml_string(tu_path) << "'"; 2421 2422 if (!tu.get_compilation_dir_path().empty() && ctxt.get_write_comp_dir()) 2423 o << " comp-dir-path='" 2424 << xml::escape_xml_string(tu.get_compilation_dir_path()) << "'"; 2425 2426 if (tu.get_language() != translation_unit::LANG_UNKNOWN) 2427 o << " language='" 2428 << translation_unit_language_to_string(tu.get_language()) 2429 <<"'"; 2430 2431 if (tu.is_empty() && !is_last) 2432 { 2433 o << "/>\n"; 2434 return true; 2435 } 2436 2437 o << ">\n"; 2438 2439 write_canonical_types_of_scope(*tu.get_global_scope(), 2440 ctxt, indent + c.get_xml_element_indent()); 2441 2442 typedef scope_decl::declarations declarations; 2443 const declarations& decls = tu.get_global_scope()->get_sorted_member_decls(); 2444 2445 for (const decl_base_sptr& decl : decls) 2446 { 2447 if (type_base_sptr t = is_type(decl)) 2448 { 2449 // Emit declaration-only classes that are needed. Some of 2450 // these classes can be empty. Those beasts can be classes 2451 // that only contain member types. They can also be classes 2452 // considered "opaque". 2453 if (class_decl_sptr class_type = is_class_type(t)) 2454 if (class_type->get_is_declaration_only() 2455 && !ctxt.type_is_emitted(class_type)) 2456 write_type(class_type, ctxt, 2457 indent + c.get_xml_element_indent()); 2458 2459 if (is_non_canonicalized_type(t) && !ctxt.type_is_emitted(t)) 2460 write_type(t, ctxt, indent + c.get_xml_element_indent()); 2461 } 2462 else 2463 { 2464 if (!ctxt.decl_is_emitted(decl)) 2465 write_decl(decl, ctxt, indent + c.get_xml_element_indent()); 2466 } 2467 } 2468 2469 write_referenced_types(ctxt, tu, indent, is_last); 2470 2471 // Now handle all function types that were not only referenced by 2472 // emitted types. 2473 const vector<function_type_sptr>& t = tu.get_live_fn_types(); 2474 vector<type_base_sptr> sorted_types; 2475 ctxt.sort_types(t, sorted_types); 2476 2477 for (vector<type_base_sptr>::const_iterator i = sorted_types.begin(); 2478 i != sorted_types.end(); 2479 ++i) 2480 { 2481 function_type_sptr fn_type = is_function_type(*i); 2482 2483 if (fn_type->get_is_artificial() || ctxt.type_is_emitted(fn_type)) 2484 // This function type is either already emitted or it's 2485 // artificial (i.e, artificially created just to represent the 2486 // conceptual type of a function), so skip it. 2487 continue; 2488 2489 ABG_ASSERT(fn_type); 2490 write_function_type(fn_type, ctxt, indent + c.get_xml_element_indent()); 2491 } 2492 2493 // After we've written out the live function types, we need to write 2494 // the types they referenced. 2495 write_referenced_types(ctxt, tu, indent, is_last); 2496 2497 do_indent(o, indent); 2498 o << "</abi-instr>\n"; 2499 2500 return true; 2501} 2502 2503/// Serialize a pointer to an instance of basic type declaration, into 2504/// an output stream. 2505/// 2506/// @param d the basic type declaration to serialize. 2507/// 2508/// @param ctxt the context of the serialization. It contains e.g, the 2509/// output stream to serialize to. 2510/// 2511/// @param indent how many indentation spaces to use during the 2512/// serialization. 2513/// 2514/// @return true upon successful completion, false otherwise. 2515static bool 2516write_type_decl(const type_decl_sptr& d, write_context& ctxt, unsigned indent) 2517{ 2518 if (!d) 2519 return false; 2520 2521 ostream& o = ctxt.get_ostream(); 2522 2523 annotate(d, ctxt, indent); 2524 2525 do_indent(o, indent); 2526 2527 o << "<type-decl name='" << xml::escape_xml_string(d->get_name()) << "'"; 2528 2529 write_is_anonymous(d, o); 2530 2531 write_size_and_alignment(d, o); 2532 2533 write_is_declaration_only(d, o); 2534 2535 write_location(d, ctxt); 2536 2537 o << " id='" << ctxt.get_id_for_type(d) << "'" << "/>\n"; 2538 2539 ctxt.record_type_as_emitted(d); 2540 2541 return true; 2542} 2543 2544/// Serialize a namespace declaration int an output stream. 2545/// 2546/// @param decl the namespace declaration to serialize. 2547/// 2548/// @param ctxt the context of the serialization. It contains e.g, the 2549/// output stream to serialize to. 2550/// 2551/// @param indent how many indentation spaces to use during the 2552/// serialization. 2553/// 2554/// @return true upon successful completion, false otherwise. 2555static bool 2556write_namespace_decl(const namespace_decl_sptr& decl, 2557 write_context& ctxt, unsigned indent) 2558{ 2559 if (!decl || decl->is_empty_or_has_empty_sub_namespaces()) 2560 return false; 2561 2562 ostream& o = ctxt.get_ostream(); 2563 const config &c = ctxt.get_config(); 2564 2565 annotate(decl, ctxt, indent); 2566 2567 do_indent(o, indent); 2568 2569 o << "<namespace-decl name='" 2570 << xml::escape_xml_string(decl->get_name()) 2571 << "'>\n"; 2572 2573 typedef scope_decl::declarations declarations; 2574 typedef declarations::const_iterator const_iterator; 2575 const declarations& d = decl->get_sorted_member_decls(); 2576 2577 write_canonical_types_of_scope(*decl, ctxt, 2578 indent + c.get_xml_element_indent()); 2579 2580 for (const_iterator i = d.begin(); i != d.end(); ++i) 2581 { 2582 if (type_base_sptr t = is_type(*i)) 2583 if (ctxt.type_is_emitted(t)) 2584 // This type has already been emitted to the current 2585 // translation unit so do not emit it again. 2586 continue; 2587 write_decl(*i, ctxt, indent + c.get_xml_element_indent()); 2588 } 2589 2590 do_indent(o, indent); 2591 o << "</namespace-decl>\n"; 2592 2593 return true; 2594} 2595 2596/// Serialize a qualified type declaration to an output stream. 2597/// 2598/// @param decl the qualfied type declaration to write. 2599/// 2600/// @param id the type id identitifier to use in the serialized 2601/// output. If this is empty, the function will compute an 2602/// appropriate one. This is useful when this function is called to 2603/// serialize the underlying type of a member type; in that case, the 2604/// caller has already computed the id of the *member type*, and that 2605/// id is the one to be written as the value of the 'id' attribute of 2606/// the XML element of the underlying type. 2607/// 2608/// @param ctxt the write context. 2609/// 2610/// @param indent the number of space to indent to during the 2611/// serialization. 2612/// 2613/// @return true upon successful completion, false otherwise. 2614static bool 2615write_qualified_type_def(const qualified_type_def_sptr& decl, 2616 const string& id, 2617 write_context& ctxt, 2618 unsigned indent) 2619{ 2620 if (!decl) 2621 return false; 2622 2623 ostream& o = ctxt.get_ostream(); 2624 2625 2626 type_base_sptr underlying_type = decl->get_underlying_type(); 2627 2628 annotate(decl, ctxt, indent); 2629 2630 do_indent(o, indent); 2631 o << "<qualified-type-def type-id='" 2632 << ctxt.get_id_for_type(underlying_type) 2633 << "'"; 2634 2635 ctxt.record_type_as_referenced(underlying_type); 2636 2637 if (decl->get_cv_quals() & qualified_type_def::CV_CONST) 2638 o << " const='yes'"; 2639 if (decl->get_cv_quals() & qualified_type_def::CV_VOLATILE) 2640 o << " volatile='yes'"; 2641 if (decl->get_cv_quals() & qualified_type_def::CV_RESTRICT) 2642 o << " restrict='yes'"; 2643 2644 write_location(static_pointer_cast<decl_base>(decl), ctxt); 2645 2646 string i = id; 2647 if (i.empty()) 2648 i = ctxt.get_id_for_type(decl); 2649 2650 o << " id='" << i << "'/>\n"; 2651 2652 ctxt.record_type_as_emitted(decl); 2653 2654 return true; 2655} 2656 2657/// Serialize a qualified type declaration to an output stream. 2658/// 2659/// @param decl the qualfied type declaration to write. 2660/// 2661/// @param ctxt the write context. 2662/// 2663/// @param indent the number of space to indent to during the 2664/// serialization. 2665/// 2666/// @return true upon successful completion, false otherwise. 2667static bool 2668write_qualified_type_def(const qualified_type_def_sptr& decl, 2669 write_context& ctxt, 2670 unsigned indent) 2671{return write_qualified_type_def(decl, "", ctxt, indent);} 2672 2673/// Serialize a pointer to an instance of pointer_type_def. 2674/// 2675/// @param decl the pointer_type_def to serialize. 2676/// 2677/// @param id the type id identitifier to use in the serialized 2678/// output. If this is empty, the function will compute an 2679/// appropriate one. This is useful when this function is called to 2680/// serialize the underlying type of a member type; in that case, the 2681/// caller has already computed the id of the *member type*, and that 2682/// id is the one to be written as the value of the 'id' attribute of 2683/// the XML element of the underlying type. 2684/// 2685/// @param ctxt the context of the serialization. 2686/// 2687/// @param indent the number of indentation white spaces to use. 2688/// 2689/// @return true upon succesful completion, false otherwise. 2690static bool 2691write_pointer_type_def(const pointer_type_def_sptr& decl, 2692 const string& id, 2693 write_context& ctxt, 2694 unsigned indent) 2695{ 2696 if (!decl) 2697 return false; 2698 2699 ostream& o = ctxt.get_ostream(); 2700 2701 2702 type_base_sptr pointed_to_type = decl->get_pointed_to_type(); 2703 2704 annotate(decl->get_canonical_type(), ctxt, indent); 2705 2706 do_indent(o, indent); 2707 o << "<pointer-type-def type-id='" 2708 << ctxt.get_id_for_type(pointed_to_type) 2709 << "'"; 2710 2711 ctxt.record_type_as_referenced(pointed_to_type); 2712 2713 write_size_and_alignment(decl, o, 2714 (ctxt.get_write_default_sizes() 2715 ? 0 2716 : decl->get_translation_unit()->get_address_size()), 2717 0); 2718 2719 string i = id; 2720 if (i.empty()) 2721 i = ctxt.get_id_for_type(decl); 2722 2723 o << " id='" << i << "'"; 2724 2725 write_location(static_pointer_cast<decl_base>(decl), ctxt); 2726 o << "/>\n"; 2727 2728 ctxt.record_type_as_emitted(decl); 2729 2730 return true; 2731} 2732 2733/// Serialize a pointer to an instance of pointer_type_def. 2734/// 2735/// @param decl the pointer_type_def to serialize. 2736/// 2737/// @param ctxt the context of the serialization. 2738/// 2739/// @param indent the number of indentation white spaces to use. 2740/// 2741/// @return true upon succesful completion, false otherwise. 2742static bool 2743write_pointer_type_def(const pointer_type_def_sptr& decl, 2744 write_context& ctxt, 2745 unsigned indent) 2746{return write_pointer_type_def(decl, "", ctxt, indent);} 2747 2748/// Serialize a pointer to an instance of reference_type_def. 2749/// 2750/// @param decl the reference_type_def to serialize. 2751/// 2752/// @param id the type id identitifier to use in the serialized 2753/// output. If this is empty, the function will compute an 2754/// appropriate one. This is useful when this function is called to 2755/// serialize the underlying type of a member type; in that case, the 2756/// caller has already computed the id of the *member type*, and that 2757/// id is the one to be written as the value of the 'id' attribute of 2758/// the XML element of the underlying type. 2759/// 2760/// @param ctxt the context of the serialization. 2761/// 2762/// @param indent the number of indentation white spaces to use. 2763/// 2764/// @return true upon succesful completion, false otherwise. 2765static bool 2766write_reference_type_def(const reference_type_def_sptr& decl, 2767 const string& id, 2768 write_context& ctxt, 2769 unsigned indent) 2770{ 2771 if (!decl) 2772 return false; 2773 2774 annotate(decl->get_canonical_type(), ctxt, indent); 2775 2776 ostream& o = ctxt.get_ostream(); 2777 2778 do_indent(o, indent); 2779 2780 o << "<reference-type-def kind='"; 2781 if (decl->is_lvalue()) 2782 o << "lvalue"; 2783 else 2784 o << "rvalue"; 2785 o << "'"; 2786 2787 type_base_sptr pointed_to_type = decl->get_pointed_to_type(); 2788 o << " type-id='" << ctxt.get_id_for_type(pointed_to_type) << "'"; 2789 2790 ctxt.record_type_as_referenced(pointed_to_type); 2791 2792 if (function_type_sptr f = is_function_type(decl->get_pointed_to_type())) 2793 ctxt.record_type_as_referenced(f); 2794 2795 write_size_and_alignment(decl, o, 2796 (ctxt.get_write_default_sizes() 2797 ? 0 2798 : decl->get_translation_unit()->get_address_size()), 2799 0); 2800 2801 string i = id; 2802 if (i.empty()) 2803 i = ctxt.get_id_for_type(decl); 2804 o << " id='" << i << "'"; 2805 2806 write_location(static_pointer_cast<decl_base>(decl), ctxt); 2807 2808 o << "/>\n"; 2809 2810 ctxt.record_type_as_emitted(decl); 2811 2812 return true; 2813} 2814 2815/// Serialize a pointer to an instance of reference_type_def. 2816/// 2817/// @param decl the reference_type_def to serialize. 2818/// 2819/// @param ctxt the context of the serialization. 2820/// 2821/// @param indent the number of indentation white spaces to use. 2822/// 2823/// @return true upon succesful completion, false otherwise. 2824static bool 2825write_reference_type_def(const reference_type_def_sptr& decl, 2826 write_context& ctxt, 2827 unsigned indent) 2828{return write_reference_type_def(decl, "", ctxt, indent);} 2829 2830/// Serialize an instance of @ref array_type_def::subrange_type. 2831/// 2832/// @param decl the array_type_def::subrange_type to serialize. 2833/// 2834/// @param ctxt the context of the serialization. 2835/// 2836/// @param indent the number of indentation white spaces to use. 2837/// 2838/// return true upon successful completion, false otherwise. 2839static bool 2840write_array_subrange_type(const array_type_def::subrange_sptr& decl, 2841 write_context& ctxt, 2842 unsigned indent) 2843{ 2844 if (!decl) 2845 return false; 2846 2847 annotate(decl, ctxt, indent); 2848 2849 ostream& o = ctxt.get_ostream(); 2850 2851 do_indent(o, indent); 2852 2853 o << "<subrange"; 2854 2855 if (!decl->get_name().empty()) 2856 o << " name='" << decl->get_name() << "'"; 2857 2858 o << " length='"; 2859 if (decl->is_infinite()) 2860 o << "infinite"; 2861 else 2862 o << decl->get_length(); 2863 2864 o << "'"; 2865 2866 if (decl->get_lower_bound()) 2867 { 2868 ABG_ASSERT(decl->is_infinite() 2869 || (decl->get_length() == 2870 (uint64_t) (decl->get_upper_bound() 2871 - decl->get_lower_bound() + 1))); 2872 o << " lower-bound='" << decl->get_lower_bound() << "' upper-bound='" 2873 << decl->get_upper_bound() << "'"; 2874 } 2875 2876 type_base_sptr underlying_type = decl->get_underlying_type(); 2877 if (underlying_type) 2878 { 2879 o << " type-id='" 2880 << ctxt.get_id_for_type(underlying_type) 2881 << "'"; 2882 ctxt.record_type_as_referenced(underlying_type); 2883 } 2884 2885 o << " id='" << ctxt.get_id_for_type(decl) << "'"; 2886 2887 write_location(decl->get_location(), ctxt); 2888 2889 o << "/>\n"; 2890 2891 ctxt.record_type_as_emitted(decl); 2892 2893 return true; 2894} 2895 2896/// Serialize a pointer to an instance of array_type_def. 2897/// 2898/// @param decl the array_type_def to serialize. 2899/// 2900/// @param id the type id identitifier to use in the serialized 2901/// output. If this is empty, the function will compute an 2902/// appropriate one. This is useful when this function is called to 2903/// serialize the underlying type of a member type; in that case, the 2904/// caller has already computed the id of the *member type*, and that 2905/// id is the one to be written as the value of the 'id' attribute of 2906/// the XML element of the underlying type. 2907/// 2908/// @param ctxt the context of the serialization. 2909/// 2910/// @param indent the number of indentation white spaces to use. 2911/// 2912/// @return true upon succesful completion, false otherwise. 2913static bool 2914write_array_type_def(const array_type_def_sptr& decl, 2915 const string& id, 2916 write_context& ctxt, 2917 unsigned indent) 2918{ 2919 if (!decl) 2920 return false; 2921 2922 annotate(decl, ctxt, indent); 2923 2924 ostream& o = ctxt.get_ostream(); 2925 2926 do_indent(o, indent); 2927 o << "<array-type-def"; 2928 2929 o << " dimensions='" << decl->get_dimension_count() << "'"; 2930 2931 type_base_sptr element_type = decl->get_element_type(); 2932 o << " type-id='" << ctxt.get_id_for_type(element_type) << "'"; 2933 2934 ctxt.record_type_as_referenced(element_type); 2935 2936 write_array_size_and_alignment(decl, o); 2937 2938 string i = id; 2939 if (i.empty()) 2940 i = ctxt.get_id_for_type(decl); 2941 o << " id='" << i << "'"; 2942 2943 write_location(static_pointer_cast<decl_base>(decl), ctxt); 2944 2945 if (!decl->get_dimension_count()) 2946 o << "/>\n"; 2947 else 2948 { 2949 o << ">\n"; 2950 2951 vector<array_type_def::subrange_sptr>::const_iterator si; 2952 2953 for (si = decl->get_subranges().begin(); 2954 si != decl->get_subranges().end(); ++si) 2955 { 2956 unsigned local_indent = 2957 indent + ctxt.get_config().get_xml_element_indent(); 2958 write_array_subrange_type(*si, ctxt, local_indent); 2959 } 2960 2961 do_indent(o, indent); 2962 o << "</array-type-def>\n"; 2963 } 2964 2965 ctxt.record_type_as_emitted(decl); 2966 2967 return true; 2968} 2969 2970/// Serialize a pointer to an instance of array_type_def. 2971/// 2972/// @param decl the array_type_def to serialize. 2973/// 2974/// @param ctxt the context of the serialization. 2975/// 2976/// @param indent the number of indentation white spaces to use. 2977/// 2978/// @return true upon succesful completion, false otherwise. 2979static bool 2980write_array_type_def(const array_type_def_sptr& decl, 2981 write_context& ctxt, 2982 unsigned indent) 2983{return write_array_type_def(decl, "", ctxt, indent);} 2984 2985/// Serialize a pointer to an instance of enum_type_decl. 2986/// 2987/// @param decl the enum_type_decl to serialize. 2988/// 2989/// @param id the type id identitifier to use in the serialized 2990/// output. If this is empty, the function will compute an 2991/// appropriate one. This is useful when this function is called to 2992/// serialize the underlying type of a member type; in that case, the 2993/// caller has already computed the id of the *member type*, and that 2994/// id is the one to be written as the value of the 'id' attribute of 2995/// the XML element of the underlying type. 2996/// 2997/// @param ctxt the context of the serialization. 2998/// 2999/// @param indent the number of indentation white spaces to use. 3000/// 3001/// @return true upon succesful completion, false otherwise. 3002static bool 3003write_enum_type_decl(const enum_type_decl_sptr& d, 3004 const string& id, 3005 write_context& ctxt, 3006 unsigned indent) 3007{ 3008 if (!d) 3009 return false; 3010 3011 enum_type_decl_sptr decl = is_enum_type(look_through_decl_only_enum(d)); 3012 3013 annotate(decl->get_canonical_type(), ctxt, indent); 3014 3015 ostream& o = ctxt.get_ostream(); 3016 3017 do_indent(o, indent); 3018 o << "<enum-decl name='" << xml::escape_xml_string(decl->get_name()) << "'"; 3019 3020 write_is_anonymous(decl, o); 3021 write_naming_typedef(decl, ctxt); 3022 write_is_artificial(decl, o); 3023 write_is_non_reachable(is_type(decl), o); 3024 3025 if (!decl->get_linkage_name().empty()) 3026 o << " linkage-name='" 3027 << xml::escape_xml_string(decl->get_linkage_name()) 3028 << "'"; 3029 3030 write_location(decl, ctxt); 3031 write_is_declaration_only(decl, o); 3032 3033 string i = id; 3034 if (i.empty()) 3035 i = ctxt.get_id_for_type(decl); 3036 o << " id='" << i << "'>\n"; 3037 3038 do_indent(o, indent + ctxt.get_config().get_xml_element_indent()); 3039 o << "<underlying-type type-id='" 3040 << ctxt.get_id_for_type(decl->get_underlying_type()) 3041 << "'/>\n"; 3042 3043 for (enum_type_decl::enumerators::const_iterator i = 3044 decl->get_enumerators().begin(); 3045 i != decl->get_enumerators().end(); 3046 ++i) 3047 { 3048 do_indent(o, indent + ctxt.get_config().get_xml_element_indent()); 3049 o << "<enumerator name='" 3050 << i->get_name() 3051 << "' value='" 3052 << i->get_value() 3053 << "'/>\n"; 3054 } 3055 3056 do_indent(o, indent); 3057 o << "</enum-decl>\n"; 3058 3059 ctxt.record_type_as_emitted(decl); 3060 3061 return true; 3062} 3063 3064/// Serialize a pointer to an instance of enum_type_decl. 3065/// 3066/// @param decl the enum_type_decl to serialize. 3067/// 3068/// @param ctxt the context of the serialization. 3069/// 3070/// @param indent the number of indentation white spaces to use. 3071/// 3072/// @return true upon succesful completion, false otherwise. 3073static bool 3074write_enum_type_decl(const enum_type_decl_sptr& decl, 3075 write_context& ctxt, 3076 unsigned indent) 3077{return write_enum_type_decl(decl, "", ctxt, indent);} 3078 3079/// Serialize an @ref elf_symbol to an XML element of name 3080/// 'elf-symbol'. 3081/// 3082/// @param sym the elf symbol to serialize. 3083/// 3084/// @param ctxt the read context to use. 3085/// 3086/// @param indent the number of white spaces to use as indentation. 3087/// 3088/// @return true iff the function completed successfully. 3089static bool 3090write_elf_symbol(const elf_symbol_sptr& sym, 3091 write_context& ctxt, 3092 unsigned indent) 3093{ 3094 if (!sym) 3095 return false; 3096 3097 ostream &o = ctxt.get_ostream(); 3098 3099 annotate(sym, ctxt, indent); 3100 do_indent(o, indent); 3101 o << "<elf-symbol name='" << xml::escape_xml_string(sym->get_name()) << "'"; 3102 if (sym->is_variable() && sym->get_size()) 3103 o << " size='" << sym->get_size() << "'"; 3104 3105 if (!sym->get_version().is_empty()) 3106 { 3107 o << " version='" << sym->get_version().str() << "'"; 3108 o << " is-default-version='"; 3109 if (sym->get_version().is_default()) 3110 o << "yes"; 3111 else 3112 o << "no"; 3113 o << "'"; 3114 } 3115 3116 write_elf_symbol_type(sym->get_type(), o); 3117 3118 write_elf_symbol_binding(sym->get_binding(), o); 3119 3120 write_elf_symbol_visibility(sym->get_visibility(), o); 3121 3122 write_elf_symbol_aliases(*sym, o); 3123 3124 o << " is-defined='"; 3125 if (sym->is_defined()) 3126 o << "yes"; 3127 else 3128 o << "no"; 3129 o << "'"; 3130 3131 if (sym->is_common_symbol()) 3132 o << " is-common='yes'"; 3133 3134 if (sym->get_crc().has_value()) 3135 o << " crc='" 3136 << std::hex << std::showbase << sym->get_crc().value() 3137 << std::dec << std::noshowbase << "'"; 3138 3139 if (sym->get_namespace().has_value()) 3140 o << " namespace='" << sym->get_namespace().value() << "'"; 3141 3142 o << "/>\n"; 3143 3144 return true; 3145} 3146 3147/// Write the elf symbol database to the output associated to the 3148/// current context. 3149/// 3150/// @param syms the sorted elf symbol data to write out. 3151/// 3152/// @param ctxt the context to consider. 3153/// 3154/// @param indent the number of white spaces to use as indentation. 3155/// 3156/// @return true upon successful completion. 3157static bool 3158write_elf_symbols_table(const elf_symbols& syms, 3159 write_context& ctxt, 3160 unsigned indent) 3161{ 3162 if (syms.empty()) 3163 return false; 3164 3165 for (elf_symbols::const_iterator it = syms.begin(); it != syms.end(); ++it) 3166 write_elf_symbol(*it, ctxt, indent); 3167 3168 return true; 3169} 3170 3171/// Write a vector of dependency names for the current corpus we are 3172/// writting. 3173/// 3174/// @param needed the vector of dependency names to write. 3175/// 3176/// @param ctxt the write context to use for the writting. 3177/// 3178/// @param indent the number of indendation spaces to use. 3179/// 3180/// @return true upon successful completion, false otherwise. 3181static bool 3182write_elf_needed(const vector<string>& needed, 3183 write_context& ctxt, 3184 unsigned indent) 3185{ 3186 if (needed.empty()) 3187 return false; 3188 3189 ostream& o = ctxt.get_ostream(); 3190 3191 for (vector<string>::const_iterator i = needed.begin(); 3192 i != needed.end(); 3193 ++i) 3194 { 3195 do_indent(o, indent); 3196 o << "<dependency name='" << *i << "'/>\n"; 3197 } 3198 return true; 3199} 3200 3201/// Serialize a pointer to an instance of typedef_decl. 3202/// 3203/// @param decl the typedef_decl to serialize. 3204/// 3205/// @param id the type id identitifier to use in the serialized 3206/// output. If this is empty, the function will compute an 3207/// appropriate one. This is useful when this function is called to 3208/// serialize the underlying type of a member type; in that case, the 3209/// caller has already computed the id of the *member type*, and that 3210/// id is the one to be written as the value of the 'id' attribute of 3211/// the XML element of the underlying type. 3212/// 3213/// @param ctxt the context of the serialization. 3214/// 3215/// @param indent the number of indentation white spaces to use. 3216/// 3217/// @return true upon succesful completion, false otherwise. 3218static bool 3219write_typedef_decl(const typedef_decl_sptr& decl, 3220 const string& id, 3221 write_context& ctxt, 3222 unsigned indent) 3223{ 3224 if (!decl) 3225 return false; 3226 3227 ostream &o = ctxt.get_ostream(); 3228 3229 annotate(decl, ctxt, indent); 3230 3231 do_indent(o, indent); 3232 3233 o << "<typedef-decl name='" 3234 << xml::escape_xml_string(decl->get_name()) 3235 << "'"; 3236 3237 type_base_sptr underlying_type = decl->get_underlying_type(); 3238 string type_id = ctxt.get_id_for_type(underlying_type); 3239 o << " type-id='" << type_id << "'"; 3240 ctxt.record_type_as_referenced(underlying_type); 3241 3242 write_location(decl, ctxt); 3243 3244 string i = id; 3245 if (i.empty()) 3246 i = ctxt.get_id_for_type(decl); 3247 3248 o << " id='" << i << "'/>\n"; 3249 3250 ctxt.record_type_as_emitted(decl); 3251 3252 return true; 3253} 3254 3255/// Serialize a pointer to an instance of typedef_decl. 3256/// 3257/// @param decl the typedef_decl to serialize. 3258/// 3259/// @param ctxt the context of the serialization. 3260/// 3261/// @param indent the number of indentation white spaces to use. 3262/// 3263/// @return true upon succesful completion, false otherwise. 3264static bool 3265write_typedef_decl(const typedef_decl_sptr& decl, 3266 write_context& ctxt, 3267 unsigned indent) 3268{return write_typedef_decl(decl, "", ctxt, indent);} 3269 3270/// Serialize a pointer to an instances of var_decl. 3271/// 3272/// @param decl the var_decl to serialize. 3273/// 3274/// @param ctxt the context of the serialization. 3275/// 3276/// @param write_linkage_name if true, serialize the mangled name of 3277/// this variable. 3278/// 3279/// @param indent the number of indentation white spaces to use. 3280/// 3281/// @return true upon succesful completion, false otherwise. 3282static bool 3283write_var_decl(const var_decl_sptr& decl, write_context& ctxt, 3284 bool write_linkage_name, unsigned indent) 3285{ 3286 if (!decl) 3287 return false; 3288 3289 annotate(decl, ctxt, indent); 3290 3291 ostream &o = ctxt.get_ostream(); 3292 3293 do_indent(o, indent); 3294 3295 o << "<var-decl name='" << xml::escape_xml_string(decl->get_name()) << "'"; 3296 type_base_sptr var_type = decl->get_type(); 3297 o << " type-id='" << ctxt.get_id_for_type(var_type) << "'"; 3298 ctxt.record_type_as_referenced(var_type); 3299 3300 if (write_linkage_name) 3301 { 3302 const string& linkage_name = decl->get_linkage_name(); 3303 if (!linkage_name.empty()) 3304 o << " mangled-name='" << linkage_name << "'"; 3305 } 3306 3307 write_visibility(decl, o); 3308 3309 write_binding(decl, o); 3310 3311 write_location(decl, ctxt); 3312 3313 write_elf_symbol_reference(decl->get_symbol(), o); 3314 3315 o << "/>\n"; 3316 3317 ctxt.record_decl_as_emitted(decl); 3318 3319 return true; 3320} 3321 3322/// Serialize a pointer to a function_decl. 3323/// 3324/// @param decl the pointer to function_decl to serialize. 3325/// 3326/// @param ctxt the context of the serialization. 3327/// 3328/// @param skip_first_parm if true, do not serialize the first 3329/// parameter of the function decl. 3330/// 3331/// @param indent the number of indentation white spaces to use. 3332/// 3333/// @return true upon succesful completion, false otherwise. 3334static bool 3335write_function_decl(const function_decl_sptr& decl, write_context& ctxt, 3336 bool skip_first_parm, unsigned indent) 3337{ 3338 if (!decl) 3339 return false; 3340 3341 annotate(decl, ctxt, indent); 3342 3343 ostream &o = ctxt.get_ostream(); 3344 3345 do_indent(o, indent); 3346 3347 o << "<function-decl name='" 3348 << xml::escape_xml_string(decl->get_name()) 3349 << "'"; 3350 3351 if (!decl->get_linkage_name().empty()) 3352 o << " mangled-name='" 3353 << xml::escape_xml_string(decl->get_linkage_name()) << "'"; 3354 3355 write_location(decl, ctxt); 3356 3357 if (decl->is_declared_inline()) 3358 o << " declared-inline='yes'"; 3359 3360 write_visibility(decl, o); 3361 3362 write_binding(decl, o); 3363 3364 write_size_and_alignment(decl->get_type(), o, 3365 (ctxt.get_write_default_sizes() 3366 ? 0 3367 : decl->get_translation_unit()->get_address_size()), 3368 0); 3369 write_elf_symbol_reference(decl->get_symbol(), o); 3370 3371 o << ">\n"; 3372 3373 type_base_sptr parm_type; 3374 vector<shared_ptr<function_decl::parameter> >::const_iterator pi = 3375 decl->get_parameters().begin(); 3376 for ((skip_first_parm && pi != decl->get_parameters().end()) ? ++pi: pi; 3377 pi != decl->get_parameters().end(); 3378 ++pi) 3379 { 3380 if ((*pi)->get_variadic_marker()) 3381 { 3382 do_indent(o, indent + ctxt.get_config().get_xml_element_indent()); 3383 o << "<parameter is-variadic='yes'"; 3384 } 3385 else 3386 { 3387 parm_type = (*pi)->get_type(); 3388 3389 annotate(*pi, ctxt, 3390 indent + ctxt.get_config().get_xml_element_indent()); 3391 3392 do_indent(o, indent + ctxt.get_config().get_xml_element_indent()); 3393 3394 o << "<parameter type-id='" 3395 << ctxt.get_id_for_type(parm_type) 3396 << "'"; 3397 ctxt.record_type_as_referenced(parm_type); 3398 3399 if (ctxt.get_write_parameter_names() && !(*pi)->get_name().empty()) 3400 o << " name='" << xml::escape_xml_string((*pi)->get_name()) << "'"; 3401 } 3402 write_is_artificial(*pi, o); 3403 write_location((*pi)->get_location(), ctxt); 3404 o << "/>\n"; 3405 } 3406 3407 if (shared_ptr<type_base> return_type = decl->get_return_type()) 3408 { 3409 annotate(return_type , ctxt, 3410 indent + ctxt.get_config().get_xml_element_indent()); 3411 do_indent(o, indent + ctxt.get_config().get_xml_element_indent()); 3412 o << "<return type-id='" << ctxt.get_id_for_type(return_type) << "'/>\n"; 3413 ctxt.record_type_as_referenced(return_type); 3414 } 3415 3416 do_indent(o, indent); 3417 o << "</function-decl>\n"; 3418 3419 ctxt.record_decl_as_emitted(decl); 3420 3421 return true; 3422} 3423 3424/// Serialize a function_type. 3425/// 3426/// @param decl the pointer to function_type to serialize. 3427/// 3428/// @param ctxt the context of the serialization. 3429/// 3430/// @param indent the number of indentation white spaces to use. 3431/// 3432/// @return true upon succesful completion, false otherwise. 3433static bool 3434write_function_type(const function_type_sptr& fn_type, 3435 write_context& ctxt, unsigned indent) 3436{ 3437 if (!fn_type) 3438 return false; 3439 3440 ostream &o = ctxt.get_ostream(); 3441 3442 annotate(fn_type, ctxt, indent); 3443 3444 do_indent(o, indent); 3445 3446 o << "<function-type"; 3447 3448 write_size_and_alignment(fn_type, o, 3449 (ctxt.get_write_default_sizes() 3450 ? 0 3451 : fn_type->get_translation_unit()->get_address_size()), 3452 0); 3453 3454 if (method_type_sptr method_type = is_method_type(fn_type)) 3455 { 3456 o << " method-class-id='" 3457 << ctxt.get_id_for_type(method_type->get_class_type()) 3458 << "'"; 3459 3460 write_cdtor_const_static(/*is_ctor=*/false, /*is_dtor=*/false, 3461 /*is_const=*/method_type->get_is_const(), 3462 /*is_static=*/false, o); 3463 } 3464 3465 interned_string id = ctxt.get_id_for_type(fn_type); 3466 3467 o << " id='" 3468 << id << "'" 3469 << ">\n"; 3470 3471 type_base_sptr parm_type; 3472 for (vector<function_decl::parameter_sptr>::const_iterator pi = 3473 fn_type->get_parameters().begin(); 3474 pi != fn_type->get_parameters().end(); 3475 ++pi) 3476 { 3477 3478 if ((*pi)->get_variadic_marker()) 3479 { 3480 do_indent(o, indent + ctxt.get_config().get_xml_element_indent()); 3481 o << "<parameter is-variadic='yes'"; 3482 } 3483 else 3484 { 3485 parm_type = (*pi)->get_type(); 3486 3487 annotate(*pi, ctxt, indent + ctxt.get_config().get_xml_element_indent()); 3488 3489 do_indent(o, indent + ctxt.get_config().get_xml_element_indent()); 3490 o << "<parameter type-id='" 3491 << ctxt.get_id_for_type(parm_type) 3492 << "'"; 3493 ctxt.record_type_as_referenced(parm_type); 3494 3495 if (!(*pi)->get_name().empty()) 3496 { 3497 string name = xml::escape_xml_string((*pi)->get_name()); 3498 o << " name='" << name << "'"; 3499 } 3500 } 3501 write_is_artificial(*pi, o); 3502 o << "/>\n"; 3503 } 3504 3505 if (type_base_sptr return_type = fn_type->get_return_type()) 3506 { 3507 annotate(return_type, ctxt, indent + ctxt.get_config().get_xml_element_indent()); 3508 do_indent(o, indent + ctxt.get_config().get_xml_element_indent()); 3509 o << "<return type-id='" << ctxt.get_id_for_type(return_type) << "'/>\n"; 3510 ctxt.record_type_as_referenced(return_type); 3511 } 3512 3513 do_indent(o, indent); 3514 o << "</function-type>\n"; 3515 3516 ctxt.record_type_as_emitted(fn_type); 3517 return true; 3518} 3519 3520/// Write the opening tag of a 'class-decl' element. 3521/// 3522/// @param decl the class declaration to serialize. 3523/// 3524/// @param the type ID to use for the 'class-decl' element,, or empty 3525/// if we need to build a new one. 3526/// 3527/// @param ctxt the write context to use. 3528/// 3529/// @param indent the number of white space to use for indentation. 3530/// 3531/// @param prepare_to_handle_empty if set to true, then this function 3532/// figures out if the opening tag should be for an empty element or 3533/// not. If set to false, then the opening tag is unconditionnaly for 3534/// a non-empty element. 3535/// 3536/// @return true upon successful completion. 3537static bool 3538write_class_decl_opening_tag(const class_decl_sptr& decl, 3539 const string& id, 3540 write_context& ctxt, 3541 unsigned indent, 3542 bool prepare_to_handle_empty) 3543{ 3544 if (!decl) 3545 return false; 3546 3547 ostream& o = ctxt.get_ostream(); 3548 3549 do_indent_to_level(ctxt, indent, 0); 3550 3551 o << "<class-decl name='" << xml::escape_xml_string(decl->get_name()) << "'"; 3552 3553 write_size_and_alignment(decl, o); 3554 3555 write_is_struct(decl, o); 3556 3557 write_is_anonymous(decl, o); 3558 3559 write_is_artificial(decl, o); 3560 3561 write_is_non_reachable(is_type(decl), o); 3562 3563 write_naming_typedef(decl, ctxt); 3564 3565 write_visibility(decl, o); 3566 3567 write_location(decl, ctxt); 3568 3569 write_is_declaration_only(decl, o); 3570 3571 if (decl->get_earlier_declaration()) 3572 { 3573 // This instance is the definition of an earlier declaration. 3574 o << " def-of-decl-id='" 3575 << ctxt.get_id_for_type(is_type(decl->get_earlier_declaration())) 3576 << "'"; 3577 } 3578 3579 string i = id; 3580 if (i.empty()) 3581 i = ctxt.get_id_for_type(decl); 3582 o << " id='" << i << "'"; 3583 3584 if (prepare_to_handle_empty && decl->has_no_base_nor_member()) 3585 o << "/>\n"; 3586 else 3587 o << ">\n"; 3588 3589 return true; 3590} 3591 3592/// Write the opening tag of a 'union-decl' element. 3593/// 3594/// @param decl the union declaration to serialize. 3595/// 3596/// @param the type ID to use for the 'union-decl' element, or empty 3597/// if we need to build a new one. 3598/// 3599/// @param ctxt the write context to use. 3600/// 3601/// @param indent the number of white space to use for indentation. 3602/// 3603/// @param prepare_to_handle_empty if set to true, then this function 3604/// figures out if the opening tag should be for an empty element or 3605/// not. If set to false, then the opening tag is unconditionnaly for 3606/// a non-empty element. 3607/// 3608/// @return true upon successful completion. 3609static bool 3610write_union_decl_opening_tag(const union_decl_sptr& decl, 3611 const string& id, 3612 write_context& ctxt, 3613 unsigned indent, 3614 bool prepare_to_handle_empty) 3615{ 3616 if (!decl) 3617 return false; 3618 3619 ostream& o = ctxt.get_ostream(); 3620 3621 do_indent_to_level(ctxt, indent, 0); 3622 3623 o << "<union-decl name='" << xml::escape_xml_string(decl->get_name()) << "'"; 3624 3625 if (!decl->get_is_declaration_only()) 3626 write_size_and_alignment(decl, o); 3627 3628 write_is_anonymous(decl, o); 3629 3630 write_naming_typedef(decl, ctxt); 3631 3632 write_visibility(decl, o); 3633 3634 write_is_artificial(decl, o); 3635 3636 write_is_non_reachable(is_type(decl), o); 3637 3638 write_location(decl, ctxt); 3639 3640 write_is_declaration_only(decl, o); 3641 3642 string i = id; 3643 if (i.empty()) 3644 i = ctxt.get_id_for_type(decl); 3645 o << " id='" << i << "'"; 3646 3647 if (prepare_to_handle_empty && decl->has_no_member()) 3648 o << "/>\n"; 3649 else 3650 o << ">\n"; 3651 3652 return true; 3653} 3654 3655/// Serialize a class_decl type. 3656/// 3657/// @param d the pointer to class_decl to serialize. 3658/// 3659/// @param id the type id identitifier to use in the serialized 3660/// output. If this is empty, the function will compute an 3661/// appropriate one. This is useful when this function is called to 3662/// serialize the underlying type of a member type; in that case, the 3663/// caller has already computed the id of the *member type*, and that 3664/// id is the one to be written as the value of the 'id' attribute of 3665/// the XML element of the underlying type. 3666/// 3667/// @param ctxt the context of the serialization. 3668/// 3669/// @param indent the initial indentation to use. 3670static bool 3671write_class_decl(const class_decl_sptr& d, 3672 const string& id, 3673 write_context& ctxt, 3674 unsigned indent) 3675{ 3676 if (!d) 3677 return false; 3678 3679 class_decl_sptr decl = is_class_type(look_through_decl_only_class(d)); 3680 3681 annotate(decl, ctxt, indent); 3682 3683 ostream& o = ctxt.get_ostream(); 3684 3685 if (decl->get_is_declaration_only()) 3686 { 3687 type_base_wptrs_type result; 3688 canonical_type_sptr_set_type member_types; 3689 const environment& env = ctxt.get_environment(); 3690 3691 // We are looking at a decl-only class. All decl-only classes 3692 // of a given name are equal. But then the problem is that a 3693 // decl-only class can still have member types. So we might 3694 // have other decl-only classes of the same name as this one, 3695 // but that have been defined in a namespace definition 3696 // somewhere else in a different translation-unit, for exemple. 3697 // Those other decl-only classes of the same name might have a 3698 // number of different member-types. So depending on the 3699 // decl-only class that is seen first, "different" ones might be 3700 // emitted here, even though they compare equal from the 3701 // library's point of view. This might lead to an instability 3702 // of the abixml output. 3703 // 3704 // So let's gather all the member-types of all the decl-only 3705 // classes of the fully-qualified name and emit them here. 3706 if (lookup_decl_only_class_types(env.intern(decl->get_qualified_name()), 3707 *decl->get_corpus(), 3708 result)) 3709 { 3710 for (auto t : result) 3711 { 3712 type_base_sptr type(t); 3713 class_decl_sptr c = is_class_type(type); 3714 for (auto m : c->get_member_types()) 3715 if (member_types.find(m) != member_types.end()) 3716 member_types.insert(m); 3717 } 3718 } 3719 3720 if (!member_types.empty()) 3721 { 3722 // So we now have a hand on the member types of the current 3723 // decl-only class we are looking at, so let's emit them in 3724 // a sorted manner. 3725 3726 write_class_decl_opening_tag(decl, id, ctxt, indent, 3727 /*prepare_to_handle_empty=*/ 3728 member_types.empty()); 3729 3730 vector<type_base_sptr> sorted_types; 3731 sort_types(member_types, sorted_types); 3732 3733 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1); 3734 // Really emit the member types now. 3735 for (auto t : sorted_types) 3736 if (!ctxt.type_is_emitted(t)) 3737 write_member_type(t, ctxt, nb_ws); 3738 3739 if (!member_types.empty()) 3740 o << indent << "</class-decl>\n"; 3741 3742 // Mark all the decl-only classes as emitted, even if just 3743 // marking one of them should be enough. We are doing this 3744 // for logical consistency. 3745 for (auto t : result) 3746 ctxt.record_type_as_emitted(type_base_sptr(t)); 3747 return true; 3748 } 3749 } 3750 3751 write_class_decl_opening_tag(decl, id, ctxt, indent, 3752 /*prepare_to_handle_empty=*/true); 3753 3754 if (!decl->has_no_base_nor_member()) 3755 { 3756 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1); 3757 type_base_sptr base_type; 3758 for (class_decl::base_specs::const_iterator base = 3759 decl->get_base_specifiers().begin(); 3760 base != decl->get_base_specifiers().end(); 3761 ++base) 3762 { 3763 annotate((*base)->get_base_class(), ctxt, nb_ws); 3764 do_indent(o, nb_ws); 3765 o << "<base-class"; 3766 3767 write_access((*base)->get_access_specifier(), o); 3768 3769 write_layout_offset (*base, o); 3770 3771 if ((*base)->get_is_virtual ()) 3772 o << " is-virtual='yes'"; 3773 3774 base_type = (*base)->get_base_class(); 3775 o << " type-id='" 3776 << ctxt.get_id_for_type(base_type) 3777 << "'/>\n"; 3778 3779 ctxt.record_type_as_referenced(base_type); 3780 } 3781 3782 write_canonical_types_of_scope(*decl, ctxt, nb_ws, 3783 /*is_member_type=*/true); 3784 3785 for (class_decl::member_types::const_iterator ti = 3786 decl->get_sorted_member_types().begin(); 3787 ti != decl->get_sorted_member_types().end(); 3788 ++ti) 3789 if (!(*ti)->get_naked_canonical_type()) 3790 write_member_type(*ti, ctxt, nb_ws); 3791 3792 for (class_decl::data_members::const_iterator data = 3793 decl->get_data_members().begin(); 3794 data != decl->get_data_members().end(); 3795 ++data) 3796 { 3797 do_indent(o, nb_ws); 3798 o << "<data-member"; 3799 write_access(get_member_access_specifier(*data), o); 3800 3801 bool is_static = get_member_is_static(*data); 3802 write_cdtor_const_static(/*is_ctor=*/false, 3803 /*is_dtor=*/false, 3804 /*is_const=*/false, 3805 /*is_static=*/is_static, 3806 o); 3807 write_layout_offset(*data, o); 3808 o << ">\n"; 3809 3810 write_var_decl(*data, ctxt, is_static, 3811 get_indent_to_level(ctxt, indent, 2)); 3812 3813 do_indent_to_level(ctxt, indent, 1); 3814 o << "</data-member>\n"; 3815 } 3816 3817 for (class_decl::member_functions::const_iterator f = 3818 decl->get_member_functions().begin(); 3819 f != decl->get_member_functions().end(); 3820 ++f) 3821 { 3822 function_decl_sptr fn = *f; 3823 if (get_member_function_is_virtual(fn)) 3824 // All virtual member functions are emitted together, 3825 // later. 3826 continue; 3827 3828 ABG_ASSERT(!get_member_function_is_virtual(fn)); 3829 3830 do_indent(o, nb_ws); 3831 o << "<member-function"; 3832 write_access(get_member_access_specifier(fn), o); 3833 write_cdtor_const_static( get_member_function_is_ctor(fn), 3834 get_member_function_is_dtor(fn), 3835 get_member_function_is_const(fn), 3836 get_member_is_static(fn), 3837 o); 3838 o << ">\n"; 3839 3840 write_function_decl(fn, ctxt, 3841 /*skip_first_parameter=*/false, 3842 get_indent_to_level(ctxt, indent, 2)); 3843 3844 do_indent_to_level(ctxt, indent, 1); 3845 o << "</member-function>\n"; 3846 } 3847 3848 for (class_decl::member_functions::const_iterator f = 3849 decl->get_virtual_mem_fns().begin(); 3850 f != decl->get_virtual_mem_fns().end(); 3851 ++f) 3852 { 3853 function_decl_sptr fn = *f; 3854 3855 ABG_ASSERT(get_member_function_is_virtual(fn)); 3856 3857 do_indent(o, nb_ws); 3858 o << "<member-function"; 3859 write_access(get_member_access_specifier(fn), o); 3860 write_cdtor_const_static( get_member_function_is_ctor(fn), 3861 get_member_function_is_dtor(fn), 3862 get_member_function_is_const(fn), 3863 get_member_is_static(fn), 3864 o); 3865 write_voffset(fn, o); 3866 o << ">\n"; 3867 3868 write_function_decl(fn, ctxt, 3869 /*skip_first_parameter=*/false, 3870 get_indent_to_level(ctxt, indent, 2)); 3871 3872 do_indent_to_level(ctxt, indent, 1); 3873 o << "</member-function>\n"; 3874 } 3875 3876 for (member_function_templates::const_iterator fn = 3877 decl->get_member_function_templates().begin(); 3878 fn != decl->get_member_function_templates().end(); 3879 ++fn) 3880 { 3881 do_indent(o, nb_ws); 3882 o << "<member-template"; 3883 write_access((*fn)->get_access_specifier(), o); 3884 write_cdtor_const_static((*fn)->is_constructor(), 3885 /*is_dtor=*/false, 3886 (*fn)->is_const(), 3887 (*fn)->get_is_static(), o); 3888 o << ">\n"; 3889 write_function_tdecl((*fn)->as_function_tdecl(), ctxt, 3890 get_indent_to_level(ctxt, indent, 2)); 3891 do_indent(o, nb_ws); 3892 o << "</member-template>\n"; 3893 } 3894 3895 for (member_class_templates::const_iterator cl = 3896 decl->get_member_class_templates().begin(); 3897 cl != decl->get_member_class_templates().end(); 3898 ++cl) 3899 { 3900 do_indent(o, nb_ws); 3901 o << "<member-template"; 3902 write_access((*cl)->get_access_specifier(), o); 3903 write_cdtor_const_static(false, false, false, 3904 (*cl)->get_is_static(), o); 3905 o << ">\n"; 3906 write_class_tdecl((*cl)->as_class_tdecl(), ctxt, 3907 get_indent_to_level(ctxt, indent, 2)); 3908 do_indent(o, nb_ws); 3909 o << "</member-template>\n"; 3910 } 3911 3912 do_indent_to_level(ctxt, indent, 0); 3913 3914 o << "</class-decl>\n"; 3915 } 3916 3917 ctxt.record_type_as_emitted(decl); 3918 3919 return true; 3920} 3921 3922/// Serialize a class_decl type. 3923/// 3924/// @param decl the pointer to class_decl to serialize. 3925/// 3926/// @param ctxt the context of the serialization. 3927/// 3928/// @param indent the initial indentation to use. 3929/// 3930/// @return true upon successful completion. 3931static bool 3932write_class_decl(const class_decl_sptr& decl, 3933 write_context& ctxt, 3934 unsigned indent) 3935{return write_class_decl(decl, "", ctxt, indent);} 3936 3937/// Serialize a @ref union_decl type. 3938/// 3939/// @param d the pointer to @ref union_decl to serialize. 3940/// 3941/// @param ctxt the context of the serialization. 3942/// 3943/// @param indent the initial indentation to use. 3944/// 3945/// @return true upon successful completion. 3946static bool 3947write_union_decl(const union_decl_sptr& d, 3948 const string& id, 3949 write_context& ctxt, 3950 unsigned indent) 3951{ 3952 if (!d) 3953 return false; 3954 3955 union_decl_sptr decl = is_union_type(look_through_decl_only_class(d)); 3956 3957 annotate(decl, ctxt, indent); 3958 3959 ostream& o = ctxt.get_ostream(); 3960 3961 write_union_decl_opening_tag(decl, id, ctxt, indent, 3962 /*prepare_to_handle_empty=*/true); 3963 if (!decl->has_no_member()) 3964 { 3965 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1); 3966 for (class_decl::member_types::const_iterator ti = 3967 decl->get_member_types().begin(); 3968 ti != decl->get_member_types().end(); 3969 ++ti) 3970 if (!(*ti)->get_naked_canonical_type()) 3971 write_member_type(*ti, ctxt, nb_ws); 3972 3973 write_canonical_types_of_scope(*decl, ctxt, nb_ws, 3974 /*is_member_type=*/true); 3975 3976 for (union_decl::data_members::const_iterator data = 3977 decl->get_data_members().begin(); 3978 data != decl->get_data_members().end(); 3979 ++data) 3980 { 3981 do_indent(o, nb_ws); 3982 o << "<data-member"; 3983 write_access(get_member_access_specifier(*data), o); 3984 3985 bool is_static = get_member_is_static(*data); 3986 write_cdtor_const_static(/*is_ctor=*/false, 3987 /*is_dtor=*/false, 3988 /*is_const=*/false, 3989 /*is_static=*/is_static, 3990 o); 3991 o << ">\n"; 3992 3993 write_var_decl(*data, ctxt, is_static, 3994 get_indent_to_level(ctxt, indent, 2)); 3995 3996 do_indent_to_level(ctxt, indent, 1); 3997 o << "</data-member>\n"; 3998 } 3999 4000 for (union_decl::member_functions::const_iterator f = 4001 decl->get_member_functions().begin(); 4002 f != decl->get_member_functions().end(); 4003 ++f) 4004 { 4005 function_decl_sptr fn = *f; 4006 if (get_member_function_is_virtual(fn)) 4007 // All virtual member functions are emitted together, 4008 // later. 4009 continue; 4010 4011 ABG_ASSERT(!get_member_function_is_virtual(fn)); 4012 4013 do_indent(o, nb_ws); 4014 o << "<member-function"; 4015 write_access(get_member_access_specifier(fn), o); 4016 write_cdtor_const_static( get_member_function_is_ctor(fn), 4017 get_member_function_is_dtor(fn), 4018 get_member_function_is_const(fn), 4019 get_member_is_static(fn), 4020 o); 4021 o << ">\n"; 4022 4023 write_function_decl(fn, ctxt, 4024 /*skip_first_parameter=*/false, 4025 get_indent_to_level(ctxt, indent, 2)); 4026 4027 do_indent_to_level(ctxt, indent, 1); 4028 o << "</member-function>\n"; 4029 } 4030 4031 for (member_function_templates::const_iterator fn = 4032 decl->get_member_function_templates().begin(); 4033 fn != decl->get_member_function_templates().end(); 4034 ++fn) 4035 { 4036 do_indent(o, nb_ws); 4037 o << "<member-template"; 4038 write_access((*fn)->get_access_specifier(), o); 4039 write_cdtor_const_static((*fn)->is_constructor(), 4040 /*is_dtor=*/false, 4041 (*fn)->is_const(), 4042 (*fn)->get_is_static(), o); 4043 o << ">\n"; 4044 write_function_tdecl((*fn)->as_function_tdecl(), ctxt, 4045 get_indent_to_level(ctxt, indent, 2)); 4046 do_indent(o, nb_ws); 4047 o << "</member-template>\n"; 4048 } 4049 4050 for (member_class_templates::const_iterator cl = 4051 decl->get_member_class_templates().begin(); 4052 cl != decl->get_member_class_templates().end(); 4053 ++cl) 4054 { 4055 do_indent(o, nb_ws); 4056 o << "<member-template"; 4057 write_access((*cl)->get_access_specifier(), o); 4058 write_cdtor_const_static(false, false, false, 4059 (*cl)->get_is_static(), o); 4060 o << ">\n"; 4061 write_class_tdecl((*cl)->as_class_tdecl(), ctxt, 4062 get_indent_to_level(ctxt, indent, 2)); 4063 do_indent(o, nb_ws); 4064 o << "</member-template>\n"; 4065 } 4066 4067 do_indent_to_level(ctxt, indent, 0); 4068 4069 o << "</union-decl>\n"; 4070 } 4071 4072 ctxt.record_type_as_emitted(decl); 4073 4074 return true; 4075} 4076 4077static bool 4078write_union_decl(const union_decl_sptr& decl, 4079 write_context& ctxt, 4080 unsigned indent) 4081{return write_union_decl(decl, "", ctxt, indent);} 4082 4083/// Write the opening tag for a 'member-type' element. 4084/// 4085/// @param t the member type to consider. 4086/// 4087/// @param ctxt the write context to use. 4088/// 4089/// @param indent the number of white spaces to use for indentation. 4090/// 4091/// @return true upon successful completion. 4092static bool 4093write_member_type_opening_tag(const type_base_sptr& t, 4094 write_context& ctxt, 4095 unsigned indent) 4096{ 4097 ostream& o = ctxt.get_ostream(); 4098 4099 do_indent_to_level(ctxt, indent, 0); 4100 4101 decl_base_sptr decl = get_type_declaration(t); 4102 ABG_ASSERT(decl); 4103 4104 o << "<member-type"; 4105 write_access(decl, o); 4106 o << ">\n"; 4107 4108 return true; 4109} 4110 4111/// Serialize a member type. 4112/// 4113/// Note that the id written as the value of the 'id' attribute of the 4114/// underlying type is actually the id of the member type, not the one 4115/// for the underying type. That id takes in account, the access 4116/// specifier and the qualified name of the member type. 4117/// 4118/// @param decl the declaration of the member type to serialize. 4119/// 4120/// @param ctxt the write context to use. 4121/// 4122/// @param indent the number of levels to use for indentation 4123static bool 4124write_member_type(const type_base_sptr& t, write_context& ctxt, unsigned indent) 4125{ 4126 if (!t) 4127 return false; 4128 4129 ostream& o = ctxt.get_ostream(); 4130 4131 write_member_type_opening_tag(t, ctxt, indent); 4132 4133 string id = ctxt.get_id_for_type(t); 4134 4135 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1); 4136 ABG_ASSERT(write_qualified_type_def(dynamic_pointer_cast<qualified_type_def>(t), 4137 id, ctxt, nb_ws) 4138 || write_pointer_type_def(dynamic_pointer_cast<pointer_type_def>(t), 4139 id, ctxt, nb_ws) 4140 || write_reference_type_def(dynamic_pointer_cast<reference_type_def>(t), 4141 id, ctxt, nb_ws) 4142 || write_array_type_def(dynamic_pointer_cast<array_type_def>(t), 4143 id, ctxt, nb_ws) 4144 || write_enum_type_decl(dynamic_pointer_cast<enum_type_decl>(t), 4145 id, ctxt, nb_ws) 4146 || write_typedef_decl(dynamic_pointer_cast<typedef_decl>(t), 4147 id, ctxt, nb_ws) 4148 || write_union_decl(dynamic_pointer_cast<union_decl>(t), 4149 id, ctxt, nb_ws) 4150 || write_class_decl(dynamic_pointer_cast<class_decl>(t), 4151 id, ctxt, nb_ws)); 4152 4153 do_indent_to_level(ctxt, indent, 0); 4154 o << "</member-type>\n"; 4155 4156 return true; 4157} 4158 4159/// Serialize an instance of type_tparameter. 4160/// 4161/// @param decl the instance to serialize. 4162/// 4163/// @param ctxt the context of the serialization. 4164/// 4165/// @param indent the initial indentation to use. 4166/// 4167/// @return true upon successful completion, false otherwise. 4168static bool 4169write_type_tparameter(const type_tparameter_sptr decl, 4170 write_context& ctxt, 4171 unsigned indent) 4172{ 4173 if (!decl) 4174 return false; 4175 4176 ostream &o = ctxt.get_ostream(); 4177 do_indent_to_level(ctxt, indent, 0); 4178 4179 string id_attr_name; 4180 if (ctxt.type_has_existing_id(decl)) 4181 id_attr_name = "type-id"; 4182 else 4183 id_attr_name = "id"; 4184 4185 o << "<template-type-parameter " 4186 << id_attr_name << "='" << ctxt.get_id_for_type(decl) << "'"; 4187 4188 std::string name = xml::escape_xml_string(decl->get_name ()); 4189 if (!name.empty()) 4190 o << " name='" << name << "'"; 4191 4192 write_location(decl, ctxt); 4193 4194 o << "/>\n"; 4195 4196 ctxt.record_type_as_emitted(decl); 4197 4198 return true; 4199} 4200 4201/// Serialize an instance of non_type_tparameter. 4202/// 4203/// @param decl the instance to serialize. 4204/// 4205/// @param ctxt the context of the serialization. 4206/// 4207/// @param indent the intial indentation to use. 4208/// 4209/// @return true open successful completion, false otherwise. 4210static bool 4211write_non_type_tparameter( 4212 const shared_ptr<non_type_tparameter> decl, 4213 write_context& ctxt, unsigned indent) 4214{ 4215 if (!decl) 4216 return false; 4217 4218 ostream &o = ctxt.get_ostream(); 4219 do_indent_to_level(ctxt, indent, 0); 4220 4221 o << "<template-non-type-parameter type-id='" 4222 << ctxt.get_id_for_type(decl->get_type()) 4223 << "'"; 4224 4225 string name = xml::escape_xml_string(decl->get_name()); 4226 if (!name.empty()) 4227 o << " name='" << name << "'"; 4228 4229 write_location(decl, ctxt); 4230 4231 o << "/>\n"; 4232 4233 return true; 4234} 4235 4236/// Serialize an instance of template template parameter. 4237/// 4238/// @param decl the instance to serialize. 4239/// 4240/// @param ctxt the context of the serialization. 4241/// 4242/// @param indent the initial indentation to use. 4243/// 4244/// @return true upon successful completion, false otherwise. 4245 4246static bool 4247write_template_tparameter (const template_tparameter_sptr decl, 4248 write_context& ctxt, 4249 unsigned indent) 4250{ 4251 if (!decl) 4252 return false; 4253 4254 ostream& o = ctxt.get_ostream(); 4255 do_indent_to_level(ctxt, indent, 0); 4256 4257 string id_attr_name = "id"; 4258 if (ctxt.type_has_existing_id(decl)) 4259 id_attr_name = "type-id"; 4260 4261 o << "<template-template-parameter " << id_attr_name << "='" 4262 << ctxt.get_id_for_type(decl) << "'"; 4263 4264 string name = xml::escape_xml_string(decl->get_name()); 4265 if (!name.empty()) 4266 o << " name='" << name << "'"; 4267 4268 o << ">\n"; 4269 4270 unsigned nb_spaces = get_indent_to_level(ctxt, indent, 1); 4271 for (list<shared_ptr<template_parameter> >::const_iterator p = 4272 decl->get_template_parameters().begin(); 4273 p != decl->get_template_parameters().end(); 4274 ++p) 4275 write_template_parameter(decl, ctxt, nb_spaces); 4276 4277 do_indent_to_level(ctxt, indent, 0); 4278 o << "</template-template-parameter>\n"; 4279 4280 ctxt.record_type_as_emitted(decl); 4281 4282 return true; 4283} 4284 4285/// Serialize an instance of type_composition. 4286/// 4287/// @param decl the decl to serialize. 4288/// 4289/// @param ctxt the context of the serialization. 4290/// 4291/// @param indent the initial indentation to use. 4292/// 4293/// @return true upon successful completion, false otherwise. 4294static bool 4295write_type_composition 4296(const shared_ptr<type_composition> decl, 4297 write_context& ctxt, unsigned indent) 4298{ 4299 if (!decl) 4300 return false; 4301 4302 ostream& o = ctxt.get_ostream(); 4303 4304 do_indent_to_level(ctxt, indent, 0); 4305 4306 o << "<template-parameter-type-composition>\n"; 4307 4308 unsigned nb_spaces = get_indent_to_level(ctxt, indent, 1); 4309 (write_pointer_type_def 4310 (dynamic_pointer_cast<pointer_type_def>(decl->get_composed_type()), 4311 ctxt, nb_spaces) 4312 || write_reference_type_def 4313 (dynamic_pointer_cast<reference_type_def>(decl->get_composed_type()), 4314 ctxt, nb_spaces) 4315 || write_array_type_def 4316 (dynamic_pointer_cast<array_type_def>(decl->get_composed_type()), 4317 ctxt, nb_spaces) 4318 || write_qualified_type_def 4319 (dynamic_pointer_cast<qualified_type_def>(decl->get_composed_type()), 4320 ctxt, nb_spaces)); 4321 4322 do_indent_to_level(ctxt, indent, 0); 4323 o << "</template-parameter-type-composition>\n"; 4324 4325 return true; 4326} 4327 4328/// Serialize an instance of template_parameter. 4329/// 4330/// @param decl the instance to serialize. 4331/// 4332/// @param ctxt the context of the serialization. 4333/// 4334/// @param indent the initial indentation to use. 4335/// 4336/// @return true upon successful completion, false otherwise. 4337static bool 4338write_template_parameter(const shared_ptr<template_parameter> decl, 4339 write_context& ctxt, unsigned indent) 4340{ 4341 if ((!write_type_tparameter 4342 (dynamic_pointer_cast<type_tparameter>(decl), ctxt, indent)) 4343 && (!write_non_type_tparameter 4344 (dynamic_pointer_cast<non_type_tparameter>(decl), 4345 ctxt, indent)) 4346 && (!write_template_tparameter 4347 (dynamic_pointer_cast<template_tparameter>(decl), 4348 ctxt, indent)) 4349 && (!write_type_composition 4350 (dynamic_pointer_cast<type_composition>(decl), 4351 ctxt, indent))) 4352 return false; 4353 4354 return true; 4355} 4356 4357/// Serialize the template parameters of the a given template. 4358/// 4359/// @param tmpl the template for which to emit the template parameters. 4360static void 4361write_template_parameters(const shared_ptr<template_decl> tmpl, 4362 write_context& ctxt, unsigned indent) 4363{ 4364 if (!tmpl) 4365 return; 4366 4367 unsigned nb_spaces = get_indent_to_level(ctxt, indent, 1); 4368 for (list<shared_ptr<template_parameter> >::const_iterator p = 4369 tmpl->get_template_parameters().begin(); 4370 p != tmpl->get_template_parameters().end(); 4371 ++p) 4372 write_template_parameter(*p, ctxt, nb_spaces); 4373} 4374 4375/// Serialize an instance of function_tdecl. 4376/// 4377/// @param decl the instance to serialize. 4378/// 4379/// @param ctxt the context of the serialization 4380/// 4381/// @param indent the initial indentation. 4382static bool 4383write_function_tdecl(const shared_ptr<function_tdecl> decl, 4384 write_context& ctxt, unsigned indent) 4385{ 4386 if (!decl) 4387 return false; 4388 4389 ostream& o = ctxt.get_ostream(); 4390 4391 do_indent_to_level(ctxt, indent, 0); 4392 4393 o << "<function-template-decl id='" << ctxt.get_id_for_fn_tmpl(decl) << "'"; 4394 4395 write_location(decl, ctxt); 4396 4397 write_visibility(decl, o); 4398 4399 write_binding(decl, o); 4400 4401 o << ">\n"; 4402 4403 write_template_parameters(decl, ctxt, indent); 4404 4405 write_function_decl(decl->get_pattern(), ctxt, 4406 /*skip_first_parameter=*/false, 4407 get_indent_to_level(ctxt, indent, 1)); 4408 4409 do_indent_to_level(ctxt, indent, 0); 4410 4411 o << "</function-template-decl>\n"; 4412 4413 return true; 4414} 4415 4416 4417/// Serialize an instance of class_tdecl 4418/// 4419/// @param decl a pointer to the instance of class_tdecl to serialize. 4420/// 4421/// @param ctxt the context of the serializtion. 4422/// 4423/// @param indent the initial number of white space to use for 4424/// indentation. 4425/// 4426/// @return true upon successful completion, false otherwise. 4427static bool 4428write_class_tdecl(const shared_ptr<class_tdecl> decl, 4429 write_context& ctxt, unsigned indent) 4430{ 4431 if (!decl) 4432 return false; 4433 4434 ostream& o = ctxt.get_ostream(); 4435 4436 do_indent_to_level(ctxt, indent, 0); 4437 4438 o << "<class-template-decl id='" << ctxt.get_id_for_class_tmpl(decl) << "'"; 4439 4440 write_location(decl, ctxt); 4441 4442 write_visibility(decl, o); 4443 4444 o << ">\n"; 4445 4446 write_template_parameters(decl, ctxt, indent); 4447 4448 write_class_decl(decl->get_pattern(), ctxt, 4449 get_indent_to_level(ctxt, indent, 1)); 4450 4451 do_indent_to_level(ctxt, indent, 0); 4452 4453 o << "</class-template-decl>\n"; 4454 4455 return true; 4456} 4457 4458/// Serialize the current version number of the ABIXML format. 4459/// 4460/// @param ctxt the writing context to use. 4461static void 4462write_version_info(write_context& ctxt) 4463{ 4464 ostream& o = ctxt.get_ostream(); 4465 const config& c = ctxt.get_config(); 4466 4467 o << "version='" 4468 << c.get_format_major_version_number() 4469 << "." << c.get_format_minor_version_number() 4470 << "'"; 4471} 4472 4473/// Serialize an ABI corpus to a single native xml document. The root 4474/// note of the resulting XML document is 'abi-corpus'. 4475/// 4476/// Note: If either corpus is null or corpus does not contain serializable 4477/// content (i.e. corpus.is_empty()), nothing is emitted to the ctxt's 4478/// output stream. 4479/// 4480/// @param ctxt the write context to use. 4481/// 4482/// @param corpus the corpus to serialize. 4483/// 4484/// @param indent the number of white space indentation to use. 4485/// 4486/// @return true upon successful completion, false otherwise. 4487bool 4488write_corpus(write_context& ctxt, 4489 const corpus_sptr& corpus, 4490 unsigned indent, 4491 bool member_of_group) 4492{ 4493 if (!corpus) 4494 return false; 4495 4496 if (corpus->is_empty()) 4497 return true; 4498 4499 do_indent_to_level(ctxt, indent, 0); 4500 4501 std::ostream& out = ctxt.get_ostream(); 4502 4503 out << "<abi-corpus "; 4504 4505 write_version_info(ctxt); 4506 4507 // For an abi-corpus as part of an abi-corpus group, only omit the path, but 4508 // keep the filename. 4509 std::string corpus_path = corpus->get_path(); 4510 if (!ctxt.get_write_corpus_path()) 4511 { 4512 if (member_of_group) 4513 tools_utils::base_name(corpus_path, corpus_path); 4514 else 4515 corpus_path.clear(); 4516 } 4517 else 4518 { 4519 if (ctxt.get_short_locs()) 4520 tools_utils::base_name(corpus_path, corpus_path); 4521 } 4522 if (!corpus_path.empty()) 4523 out << " path='" << xml::escape_xml_string(corpus_path) << "'"; 4524 4525 if (!corpus->get_architecture_name().empty() 4526 && ctxt.get_write_architecture()) 4527 out << " architecture='" << corpus->get_architecture_name()<< "'"; 4528 4529 if (!corpus->get_soname().empty()) 4530 out << " soname='" << corpus->get_soname()<< "'"; 4531 4532 write_tracking_non_reachable_types(corpus, out); 4533 4534 out << ">\n"; 4535 4536 // Write the list of needed corpora. 4537 4538 if (ctxt.get_write_elf_needed () && !corpus->get_needed().empty()) 4539 { 4540 do_indent_to_level(ctxt, indent, 1); 4541 out << "<elf-needed>\n"; 4542 write_elf_needed(corpus->get_needed(), ctxt, 4543 get_indent_to_level(ctxt, indent, 2)); 4544 do_indent_to_level(ctxt, indent, 1); 4545 out << "</elf-needed>\n"; 4546 } 4547 4548 // Write the function symbols data base. 4549 if (!corpus->get_fun_symbol_map().empty()) 4550 { 4551 do_indent_to_level(ctxt, indent, 1); 4552 out << "<elf-function-symbols>\n"; 4553 4554 write_elf_symbols_table(corpus->get_sorted_fun_symbols(), ctxt, 4555 get_indent_to_level(ctxt, indent, 2)); 4556 4557 do_indent_to_level(ctxt, indent, 1); 4558 out << "</elf-function-symbols>\n"; 4559 } 4560 4561 // Write the variable symbols data base. 4562 if (!corpus->get_var_symbol_map().empty()) 4563 { 4564 do_indent_to_level(ctxt, indent, 1); 4565 out << "<elf-variable-symbols>\n"; 4566 4567 write_elf_symbols_table(corpus->get_sorted_var_symbols(), ctxt, 4568 get_indent_to_level(ctxt, indent, 2)); 4569 4570 do_indent_to_level(ctxt, indent, 1); 4571 out << "</elf-variable-symbols>\n"; 4572 } 4573 4574 // Now write the translation units. 4575 unsigned nb_tus = corpus->get_translation_units().size(), n = 0; 4576 for (translation_units::const_iterator i = 4577 corpus->get_translation_units().begin(); 4578 i != corpus->get_translation_units().end(); 4579 ++i, ++n) 4580 { 4581 translation_unit& tu = **i; 4582 write_translation_unit(ctxt, tu, 4583 get_indent_to_level(ctxt, indent, 1), 4584 n == nb_tus - 1); 4585 } 4586 4587 do_indent_to_level(ctxt, indent, 0); 4588 out << "</abi-corpus>\n"; 4589 4590 ctxt.clear_referenced_types(); 4591 4592 return true; 4593} 4594 4595/// Serialize an ABI corpus group to a single native xml document. 4596/// The root note of the resulting XML document is 'abi-corpus-group'. 4597/// 4598/// @param ctxt the write context to use. 4599/// 4600/// @param group the corpus group to serialize. 4601/// 4602/// @param indent the number of white space indentation to use. 4603/// 4604/// @return true upon successful completion, false otherwise. 4605bool 4606write_corpus_group(write_context& ctxt, 4607 const corpus_group_sptr& group, 4608 unsigned indent) 4609 4610{ 4611 if (!group) 4612 return false; 4613 4614 do_indent_to_level(ctxt, indent, 0); 4615 4616std::ostream& out = ctxt.get_ostream(); 4617 4618 out << "<abi-corpus-group "; 4619 write_version_info(ctxt); 4620 4621 if (!group->get_path().empty() && ctxt.get_write_corpus_path()) 4622 out << " path='" << xml::escape_xml_string(group->get_path()) << "'"; 4623 4624 if (!group->get_architecture_name().empty() && ctxt.get_write_architecture()) 4625 out << " architecture='" << group->get_architecture_name()<< "'"; 4626 4627 write_tracking_non_reachable_types(group, out); 4628 4629 if (group->is_empty()) 4630 { 4631 out << "/>\n"; 4632 return true; 4633 } 4634 4635 out << ">\n"; 4636 4637 // Write the list of corpora 4638 for (corpus_group::corpora_type::const_iterator c = 4639 group->get_corpora().begin(); 4640 c != group->get_corpora().end(); 4641 ++c) 4642 write_corpus(ctxt, *c, get_indent_to_level(ctxt, indent, 1), true); 4643 4644 do_indent_to_level(ctxt, indent, 0); 4645 out << "</abi-corpus-group>\n"; 4646 4647 return true; 4648} 4649 4650} //end namespace xml_writer 4651 4652// <Debugging routines> 4653 4654using namespace abigail::ir; 4655 4656/// Serialize a pointer to decl_base to an output stream. 4657/// 4658/// @param d the pointer to decl_base to serialize. 4659/// 4660/// @param o the output stream to consider. 4661/// 4662/// @param annotate whether ABIXML output should be annotated. 4663void 4664dump(const decl_base_sptr d, std::ostream& o, const bool annotate) 4665{ 4666 xml_writer::write_context ctxt(d->get_environment(), o); 4667 xml_writer::set_annotate(ctxt, annotate); 4668 write_decl(d, ctxt, /*indent=*/0); 4669} 4670 4671/// Serialize a pointer to decl_base to stderr. 4672/// 4673/// @param d the pointer to decl_base to serialize. 4674/// 4675/// @param annotate whether ABIXML output should be annotated. 4676void 4677dump(const decl_base_sptr d, const bool annotate) 4678{dump(d, cerr, annotate);} 4679 4680/// Serialize a pointer to type_base to an output stream. 4681/// 4682/// @param t the pointer to type_base to serialize. 4683/// 4684/// @param o the output stream to serialize the @ref type_base to. 4685/// 4686/// @param annotate whether ABIXML output should be annotated. 4687void 4688dump(const type_base_sptr t, std::ostream& o, const bool annotate) 4689{dump(get_type_declaration(t), o, annotate);} 4690 4691/// Serialize a pointer to type_base to stderr. 4692/// 4693/// @param t the pointer to type_base to serialize. 4694/// 4695/// @param annotate whether ABIXML output should be annotated. 4696void 4697dump(const type_base_sptr t, const bool annotate) 4698{dump(t, cerr, annotate);} 4699 4700/// Serialize a pointer to var_decl to an output stream. 4701/// 4702/// @param v the pointer to var_decl to serialize. 4703/// 4704/// @param o the output stream to serialize the @ref var_decl to. 4705/// 4706/// @param annotate whether ABIXML output should be annotated. 4707void 4708dump(const var_decl_sptr v, std::ostream& o, const bool annotate) 4709{ 4710 xml_writer::write_context ctxt(v->get_environment(), o); 4711 xml_writer::set_annotate(ctxt, annotate); 4712 write_var_decl(v, ctxt, /*linkage_name*/true, /*indent=*/0); 4713} 4714 4715/// Serialize a pointer to var_decl to stderr. 4716/// 4717/// @param v the pointer to var_decl to serialize. 4718/// 4719/// @param annotate whether ABIXML output should be annotated. 4720void 4721dump(const var_decl_sptr v, const bool annotate) 4722{dump(v, cerr, annotate);} 4723 4724/// Serialize a @ref translation_unit to an output stream. 4725/// 4726/// @param t the translation_unit to serialize. 4727/// 4728/// @param o the outpout stream to serialize the translation_unit to. 4729/// 4730/// @param annotate whether ABIXML output should be annotated. 4731void 4732dump(const translation_unit& t, std::ostream& o, const bool annotate) 4733{ 4734 xml_writer::write_context ctxt(t.get_environment(), o); 4735 xml_writer::set_annotate(ctxt, annotate); 4736 write_translation_unit(ctxt, t, /*indent=*/0); 4737} 4738 4739/// Serialize an instance of @ref translation_unit to stderr. 4740/// 4741/// @param t the translation_unit to serialize. 4742void 4743dump(const translation_unit& t, const bool annotate) 4744{dump(t, cerr, annotate);} 4745 4746/// Serialize a pointer to @ref translation_unit to an output stream. 4747/// 4748/// @param t the @ref translation_unit_sptr to serialize. 4749/// 4750/// @param o the output stream to serialize the translation unit to. 4751/// 4752/// @param annotate whether ABIXML output should be annotated. 4753void 4754dump(const translation_unit_sptr t, std::ostream& o, const bool annotate) 4755{ 4756 if (t) 4757 dump(*t, o, annotate); 4758} 4759 4760/// Serialize a pointer to @ref translation_unit to stderr. 4761/// 4762/// @param t the translation_unit_sptr to serialize. 4763/// 4764/// @param annotate whether ABIXML output should be annotated. 4765void 4766dump(const translation_unit_sptr t, const bool annotate) 4767{ 4768 if (t) 4769 dump(*t, annotate); 4770} 4771 4772/// Serialize a source location to an output stream. 4773/// 4774/// @param l the declaration to consider. 4775/// 4776/// @param o the output stream to serialize to. 4777void 4778dump_location(const location& l, ostream& o) 4779{ 4780 string path; 4781 unsigned line = 0, col = 0; 4782 4783 l.expand(path, line, col); 4784 o << path << ":" << line << "," << col << "\n"; 4785} 4786 4787/// Serialize a source location for debugging purposes. 4788/// 4789/// The location is serialized to the standard error output stream. 4790/// 4791/// @param l the declaration to consider. 4792/// 4793void 4794dump_location(const location& l) 4795{dump_location(l, cerr);} 4796 4797/// Serialize the source location of a decl to an output stream for 4798/// debugging purposes. 4799/// 4800/// @param d the declaration to consider. 4801/// 4802/// @param o the output stream to serizalize the location to. 4803void 4804dump_decl_location(const decl_base& d, ostream& o) 4805{dump_location(d.get_location(), o);} 4806 4807/// Serialize the source location of a decl to stderr for debugging 4808/// purposes. 4809/// 4810/// @param d the declaration to consider. 4811void 4812dump_decl_location(const decl_base& d) 4813{dump_decl_location(d, cerr);} 4814 4815/// Serialize the source location of a dcl to stderr for debugging 4816/// purposes. 4817/// 4818/// @param d the declaration to consider. 4819void 4820dump_decl_location(const decl_base* d) 4821{ 4822 if (d) 4823 dump_decl_location(*d); 4824} 4825 4826/// Serialize the source location of a decl to stderr for debugging 4827/// purposes. 4828/// 4829/// @param d the declaration to consider. 4830void 4831dump_decl_location(const decl_base_sptr d) 4832{dump_decl_location(d.get());} 4833 4834#ifdef WITH_DEBUG_SELF_COMPARISON 4835/// Write one of the records of the "type-ids" debugging file. 4836/// 4837/// This is a sub-routine of write_canonical_type_ids. 4838/// 4839/// @param ctxt the context to use. 4840/// 4841/// @param type the type which canonical type pointer value to emit. 4842/// 4843/// @param o the output stream to write to. 4844static void 4845write_type_record(xml_writer::write_context& ctxt, 4846 const type_base* type, 4847 ostream& o) 4848{ 4849 // We want to serialize a type record which content looks like: 4850 // 4851 // <type> 4852 // <id>type-id-573</id> 4853 // <c>0x262ee28</c> 4854 // </type> 4855 // <type> 4856 // <id>type-id-569</id> 4857 // <c>0x2628298</c> 4858 // </type> 4859 // <type> 4860 // <id>type-id-575</id> 4861 // <c>0x25f9ba8</c> 4862 // </type> 4863 4864 string id = ctxt.get_id_for_type (const_cast<type_base*>(type)); 4865 o << " <type>\n" 4866 << " <id>" << id << "</id>\n" 4867 << " <c>" 4868 << std::hex 4869 << (type->get_canonical_type() 4870 ? reinterpret_cast<uintptr_t>(type->get_canonical_type().get()) 4871 : 0xdeadbabe) 4872 << "</c>\n" 4873 << " </type>\n"; 4874} 4875 4876/// Serialize the map that is stored at 4877/// environment::get_type_id_canonical_type_map() to an output stream. 4878/// 4879/// This is for debugging purposes and is triggered ultimately by 4880/// invoking the command 'abidw --debug-abidiff <binary>'. 4881/// 4882/// @param ctxt the write context. 4883/// 4884/// @param o the output stream to serialize the map to. 4885void 4886write_canonical_type_ids(xml_writer::write_context& ctxt, ostream& o) 4887{ 4888 // We want to serialize a file which content looks like: 4889 // 4890 // <abixml-types-check> 4891 // <type> 4892 // <id>type-id-573</id> 4893 // <c>0x262ee28</c> 4894 // </type> 4895 // <type> 4896 // <id>type-id-569</id> 4897 // <c>0x2628298</c> 4898 // </type> 4899 // <type> 4900 // <id>type-id-575</id> 4901 // <c>0x25f9ba8</c> 4902 // </type> 4903 // <abixml-types-check> 4904 4905 o << "<abixml-types-check>\n"; 4906 4907 for (const auto &type : ctxt.get_emitted_types_set()) 4908 write_type_record(ctxt, type, o); 4909 4910 o << "</abixml-types-check>\n"; 4911} 4912 4913/// Serialize the map that is stored at 4914/// environment::get_type_id_canonical_type_map() to a file. 4915/// 4916/// This is for debugging purposes and is triggered ultimately by 4917/// invoking the command 'abidw --debug-abidiff <binary>'. 4918/// 4919/// @param ctxt the write context. 4920/// 4921/// @param file_path the file to serialize the map to. 4922bool 4923write_canonical_type_ids(xml_writer::write_context& ctxt, 4924 const string &file_path) 4925{ 4926 std:: ofstream o (file_path); 4927 4928 if (!o.is_open()) 4929 return true; 4930 write_canonical_type_ids(ctxt, o); 4931 o.close(); 4932 return true; 4933} 4934#endif 4935// </Debugging routines> 4936} //end namespace abigail 4937