3 // Copyright (C) 2013-2019 Red Hat, Inc.
5 // This file is part of the GNU Application Binary Interface Generic
6 // Analysis and Instrumentation Library (libabigail). This library is
7 // free software; you can redistribute it and/or modify it under the
8 // terms of the GNU Lesser General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option) any
12 // This library is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Lesser Public License for more details.
17 // You should have received a copy of the GNU Lesser General Public
18 // License along with this program; see the file COPYING-LGPLV3. If
19 // not, see <http://www.gnu.org/licenses/>.
23 /// This file contains the definitions of the entry points to
24 /// de-serialize an instance of @ref abigail::translation_unit to an
25 /// ABI Instrumentation file in libabigail native XML format. This
26 /// native XML format is named "abixml".
36 #include <tr1/unordered_map>
38 #include "abg-tools-utils.h"
40 #include "abg-internal.h"
41 // <headers defining libabigail's API go under here>
42 ABG_BEGIN_EXPORT_DECLARATIONS
44 #include "abg-config.h"
45 #include "abg-corpus.h"
46 #include "abg-diff-utils.h"
47 #include "abg-sptr-utils.h"
50 #include "abg-libzip-utils.h"
53 #include "abg-writer.h"
54 #include "abg-libxml-utils.h"
56 ABG_END_EXPORT_DECLARATIONS
57 // </headers defining libabigail's API>
62 using std::tr1::shared_ptr;
63 using std::tr1::dynamic_pointer_cast;
64 using std::tr1::static_pointer_cast;
67 using std::ostringstream;
71 using std::tr1::unordered_map;
72 using abigail::sptr_utils::noop_deleter;
75 using zip_utils::zip_sptr;
76 using zip_utils::zip_file_sptr;
77 using zip_utils::open_archive;
78 using zip_utils::open_file_in_archive;
79 #endif // WITH_ZIP_ARCHIVE
81 /// The namespace for the native XML file format writer.
83 /// It contains utilities to serialize ABI artifacts from the @ref ir
84 /// namespace into the native XML format.
90 const environment* m_env;
91 mutable unsigned long long m_cur_id;
95 { return ++m_cur_id; }
98 id_manager(const environment* env)
103 get_environment() const
106 /// Return a unique string representing a numerical id.
112 const environment* env = get_environment();
114 return env->intern(o.str());
117 /// Return a unique string representing a numerical ID, prefixed by
120 /// @param prefix the prefix of the returned unique id.
122 get_id_with_prefix(const string& prefix) const
125 o << prefix << get_new_id();
126 const environment* env = get_environment();
128 return env->intern(o.str());
132 /// A hashing functor that should be as fast as possible.
136 operator()(const type_base* t) const
137 {return hash_type_or_decl(t);}
138 }; // end struct type_hasher
140 /// A convenience typedef for a map that associates a pointer to type
141 /// to a string. The pointer to type is hashed as fast as possible.
142 typedef unordered_map<type_base*,
145 abigail::diff_utils::deep_ptr_eq_functor> type_ptr_map;
147 // A convenience typedef for a set of type_base*.
148 typedef unordered_set<const type_base*, type_hasher,
149 abigail::diff_utils::deep_ptr_eq_functor>
152 typedef unordered_map<shared_ptr<function_tdecl>,
154 function_tdecl::shared_ptr_hash> fn_tmpl_shared_ptr_map;
156 typedef unordered_map<shared_ptr<class_tdecl>,
158 class_tdecl::shared_ptr_hash> class_tmpl_shared_ptr_map;
162 const environment* m_env;
163 id_manager m_id_manager;
168 mutable type_ptr_map m_type_id_map;
169 mutable type_ptr_set_type m_emitted_type_set;
170 type_ptr_set_type m_emitted_decl_only_set;
171 // A map of types that are referenced by emitted pointers,
172 // references or typedefs
173 type_ptr_map m_referenced_types_map;
174 fn_tmpl_shared_ptr_map m_fn_tmpl_id_map;
175 class_tmpl_shared_ptr_map m_class_tmpl_id_map;
176 string_elf_symbol_sptr_map_type m_fun_symbol_map;
177 string_elf_symbol_sptr_map_type m_var_symbol_map;
178 mutable unordered_map<interned_string,
180 hash_interned_string> m_emitted_decls_map;
188 /// @param env the enviroment we are operating from.
190 /// @param os the output stream to write to.
191 write_context(const environment* env, ostream& os)
199 /// Getter of the environment we are operating from.
201 /// @return the environment we are operating from.
203 get_environment() const
214 /// Getter of the annotation option.
216 /// @return true iff ABIXML annotations are turned on
221 /// Setter of the annotation option.
223 /// @param f the new value of the flag.
228 /// Getter of the "show-locs" option.
230 /// When this option is true then the XML writer emits location
231 /// information for emitted ABI artifacts.
233 /// @return the value of the "show-locs" option.
235 get_show_locs() const
236 {return m_show_locs;}
238 /// Setter of the "show-locs" option.
240 /// When this option is true then the XML writer emits location
241 /// information for emitted ABI artifacts.
243 /// @param f the new value of the "show-locs" option.
245 set_show_locs(bool f)
248 /// Getter of the @ref id_manager.
250 /// @return the @ref id_manager used by the current instance of @ref
253 get_id_manager() const
254 {return m_id_manager;}
258 {return m_id_manager;}
260 /// @return true iff type has already been assigned an ID.
262 type_has_existing_id(type_base_sptr type) const
263 {return type_has_existing_id(type.get());}
265 /// @return true iff type has already been assigned an ID.
267 type_has_existing_id(type_base* type) const
269 type_base *c = type->get_naked_canonical_type();
271 c = const_cast<type_base*>(type);
272 return (m_type_id_map.find(c) != m_type_id_map.end());
275 /// Associate a unique id to a given type. For that, put the type
276 /// in a hash table, hashing the type. So if the type has no id
277 /// associated to it, create a new one and return it. Otherwise,
278 /// return the existing id for that type.
280 get_id_for_type(const type_base_sptr& t)
281 {return get_id_for_type(t.get());}
283 /// Associate a unique id to a given type. For that, put the type
284 /// in a hash table, hashing the type. So if the type has no id
285 /// associated to it, create a new one and return it. Otherwise,
286 /// return the existing id for that type.
288 get_id_for_type(const type_base* t) const
290 type_base *c = t->get_naked_canonical_type();
292 c = const_cast<type_base*>(t);
294 type_ptr_map::const_iterator it = m_type_id_map.find(c);
295 if (it == m_type_id_map.end())
298 get_id_manager().get_id_with_prefix("type-id-");
299 m_type_id_map[c] = id;
306 get_id_for_fn_tmpl(const function_tdecl_sptr& f)
308 fn_tmpl_shared_ptr_map::const_iterator it = m_fn_tmpl_id_map.find(f);
309 if (it == m_fn_tmpl_id_map.end())
311 string id = get_id_manager().get_id_with_prefix("fn-tmpl-id-");
312 m_fn_tmpl_id_map[f] = id;
315 return m_fn_tmpl_id_map[f];
319 get_id_for_class_tmpl(const class_tdecl_sptr& c)
321 class_tmpl_shared_ptr_map::const_iterator it = m_class_tmpl_id_map.find(c);
322 if (it == m_class_tmpl_id_map.end())
324 string id = get_id_manager().get_id_with_prefix("class-tmpl-id-");
325 m_class_tmpl_id_map[c] = id;
328 return m_class_tmpl_id_map[c];
333 {m_type_id_map.clear();}
336 /// Getter of the map of types that were referenced by a pointer,
337 /// reference or typedef.
339 /// @return the map of types that were referenced.
341 get_referenced_types() const
342 {return m_referenced_types_map;}
344 /// Record a given type as being referenced by a pointer, a
345 /// reference or a typedef type that is being emitted to the XML
348 /// @param t a shared pointer to a type
350 record_type_as_referenced(const type_base_sptr& t)
351 {m_referenced_types_map[t.get()] = interned_string();}
353 /// Test if a given type has been referenced by a pointer, a
354 /// reference or a typedef type that was emitted to the XML output.
356 /// @param f a shared pointer to a type
358 /// @return true if the type has been referenced, false
361 type_is_referenced(const type_base_sptr& t)
363 return m_referenced_types_map.find
364 (t.get()) != m_referenced_types_map.end();
367 /// A comparison functor to compare pointers to @ref type_base.
369 /// What is compared is the string representation of the pointed-to
374 type_ptr_cmp(type_ptr_map *m)
378 /// The comparison operator of the functor.
380 /// @param l the first type to consider.
382 /// @param r the second type to consider.
384 /// @return true if the string representation of type @p l is
385 /// considered to be "less than" the string representation of the
388 /// But when the two string representations are equal (for
389 /// instance, for typedefs that have the same string
390 /// representation), this function compares the type-ids of the
391 /// types. This allows for a stable result.
393 operator()(const type_base* l, const type_base* r) const
402 string r1 = ir::get_pretty_representation(l),
403 r2 = ir::get_pretty_representation(r);
407 type_ptr_map::const_iterator i =
408 map->find(const_cast<type_base*>(l));
411 i = map->find(const_cast<type_base*>(r));
419 /// The comparison operator of the functor.
421 /// @param l the first type to consider.
423 /// @param r the second type to consider.
425 /// @return true if the string representation of type @p l is
426 /// considered to be "less than" the string representation of the
429 /// But when the two string representations are equal (for
430 /// instance, for typedefs that have the same string
431 /// representation), this function compares the type-ids of the
432 /// types. This allows for a stable result.
434 operator()(const type_base_sptr& l, const type_base_sptr& r) const
435 {return operator()(l.get(), r.get());}
436 }; // end struct type_ptr_cmp
438 /// Sort the content of a map of type pointers into a vector.
440 /// The pointers are sorted by using their string representation as
441 /// the key to sort, lexicographically.
443 /// @param types the map to sort.
445 /// @param sorted the resulted sorted vector. It's set by this
446 /// function with the result of the sorting.
448 sort_types(type_ptr_map& types,
449 vector<type_base*>& sorted)
452 for (type_ptr_map::const_iterator i = types.begin();
455 sorted.push_back(i->first);
456 type_ptr_cmp comp(&m_type_id_map);
457 sort(sorted.begin(), sorted.end(), comp);
460 /// Sort the content of a map of type pointers into a vector.
462 /// The pointers are sorted by using their string representation as
463 /// the key to sort, lexicographically.
465 /// @param types the map to sort.
467 /// @param sorted the resulted sorted vector. It's set by this
468 /// function with the result of the sorting.
470 sort_types(const istring_type_base_wptr_map_type& types,
471 vector<type_base_sptr> &sorted)
473 for (istring_type_base_wptr_map_type::const_iterator i = types.begin();
476 sorted.push_back(type_base_sptr(i->second));
477 type_ptr_cmp comp(&m_type_id_map);
478 sort(sorted.begin(), sorted.end(), comp);
481 /// Sort the content of a vector of function types into a vector of
484 /// The pointers are sorted by using their string representation as
485 /// the key to sort, lexicographically.
487 /// @param types the vector of function types to store.
489 /// @param sorted the resulted sorted vector. It's set by this
490 /// function with the result of the sorting.
492 sort_types(const vector<function_type_sptr>& types,
493 vector<type_base_sptr> &sorted)
495 for (vector<function_type_sptr>::const_iterator i = types.begin();
498 sorted.push_back(*i);
499 type_ptr_cmp comp(&m_type_id_map);
500 sort(sorted.begin(), sorted.end(), comp);
503 /// Flag a type as having been written out to the XML output.
505 /// @param t the type to flag.
507 record_type_as_emitted(const type_base_sptr &t)
508 {record_type_as_emitted(t.get());}
510 /// Flag a type as having been written out to the XML output.
512 /// @param t the type to flag.
514 record_type_as_emitted(const type_base *t)
516 type_base *c = t->get_naked_canonical_type();
518 c = const_cast<type_base*>(t);
519 m_emitted_type_set.insert(c);
522 /// Test if a given type has been written out to the XML output.
524 /// @param the type to test for.
526 /// @return true if the type has already been emitted, false
529 type_is_emitted(const type_base *t)
531 type_base *c = t->get_naked_canonical_type();
533 c = const_cast<type_base*>(t);
534 return m_emitted_type_set.find(c) != m_emitted_type_set.end();
537 /// Test if a given type has been written out to the XML output.
539 /// @param the type to test for.
541 /// @return true if the type has already been emitted, false
544 type_is_emitted(const type_base_sptr& t)
545 {return type_is_emitted(t.get());}
547 /// Test if the name of a given decl has been written out to the XML
550 /// @param the decl to consider.
552 /// @return true if the decl has already been emitted, false
555 decl_name_is_emitted(const interned_string& name) const
556 {return m_emitted_decls_map.find(name) != m_emitted_decls_map.end();}
558 /// Test if a given decl has been written out to the XML output.
560 /// @param the decl to consider.
562 /// @return true if the decl has already been emitted, false
565 decl_is_emitted(decl_base_sptr& decl) const
570 string repr = get_pretty_representation(decl, true);
571 interned_string irepr = decl->get_environment()->intern(repr);
572 bool is_emitted = decl_name_is_emitted(irepr);
576 /// Record a declaration-only class as being emitted.
578 /// For now, this function expects a declaration-only class,
579 /// otherwise, it aborts.
581 /// @param t the declaration-only class to report as emitted.
583 record_decl_only_type_as_emitted(type_base* t)
585 class_or_union* cl = is_class_or_union_type(t);
586 ABG_ASSERT(cl && cl->get_is_declaration_only());
587 m_emitted_decl_only_set.insert(t);
590 /// Record a declaration-only class as being emitted.
592 /// For now, this function expects a declaration-only class,
593 /// otherwise, it aborts.
595 /// @param t the declaration-only class to report as emitted.
597 record_decl_only_type_as_emitted(const type_base_sptr& t)
598 {record_decl_only_type_as_emitted(t.get());}
600 /// Test if a declaration-only class has been emitted.
602 /// @param t the declaration-only class to test for.
604 /// @return true iff the declaration-only class @p t has been
607 decl_only_type_is_emitted(type_base* t)
609 type_ptr_set_type::const_iterator i = m_emitted_decl_only_set.find(t);
610 if (i == m_emitted_decl_only_set.end())
615 /// Test if a declaration-only class has been emitted.
617 /// @param t the declaration-only class to test for.
619 /// @return true iff the declaration-only class @p t has been
622 decl_only_type_is_emitted(const type_base_sptr& t)
623 {return decl_only_type_is_emitted(t.get());}
625 /// Record a declaration as emitted in the abixml output.
627 /// @param decl the decl to consider.
629 record_decl_as_emitted(const decl_base_sptr &decl)const
631 string repr = get_pretty_representation(decl, true);
632 interned_string irepr = decl->get_environment()->intern(repr);
633 m_emitted_decls_map[irepr] = true;
636 /// Clear the map that contains the IDs of the types that has been
637 /// recorded as having been written out to the XML output.
639 clear_referenced_types_map()
640 {m_referenced_types_map.clear();}
642 const string_elf_symbol_sptr_map_type&
643 get_fun_symbol_map() const
644 {return m_fun_symbol_map;}
646 string_elf_symbol_sptr_map_type&
648 {return m_fun_symbol_map;}
650 };//end write_context
652 static void write_location(const location&, write_context&);
653 static void write_location(const decl_base_sptr&, write_context&);
654 static bool write_visibility(const decl_base_sptr&, ostream&);
655 static bool write_binding(const decl_base_sptr&, ostream&);
656 static void write_array_size_and_alignment(const array_type_def_sptr,
658 static void write_size_and_alignment(const type_base_sptr, ostream&);
659 static void write_access(access_specifier, ostream&);
660 static void write_layout_offset(var_decl_sptr, ostream&);
661 static void write_layout_offset(class_decl::base_spec_sptr, ostream&);
662 static void write_cdtor_const_static(bool, bool, bool, bool, ostream&);
663 static void write_voffset(function_decl_sptr, ostream&);
664 static void write_elf_symbol_type(elf_symbol::type, ostream&);
665 static void write_elf_symbol_binding(elf_symbol::binding, ostream&);
666 static bool write_elf_symbol_aliases(const elf_symbol&, ostream&);
667 static bool write_elf_symbol_reference(const elf_symbol&, ostream&);
668 static bool write_elf_symbol_reference(const elf_symbol_sptr, ostream&);
669 static void write_class_or_union_is_declaration_only(const class_or_union_sptr&,
671 static void write_is_struct(const class_decl_sptr&, ostream&);
672 static void write_is_anonymous(const decl_base_sptr&, ostream&);
673 static void write_naming_typedef(const class_decl_sptr&, write_context&);
674 static bool write_decl(const decl_base_sptr&, write_context&, unsigned);
675 static void write_decl_in_scope(const decl_base_sptr&,
676 write_context&, unsigned);
677 static bool write_type_decl(const type_decl_sptr&, write_context&, unsigned);
678 static bool write_namespace_decl(const namespace_decl_sptr&,
679 write_context&, unsigned);
680 static bool write_qualified_type_def(const qualified_type_def_sptr&,
681 write_context&, unsigned);
682 static bool write_pointer_type_def(const pointer_type_def_sptr&,
683 write_context&, unsigned);
684 static bool write_reference_type_def(const reference_type_def_sptr&,
685 write_context&, unsigned);
686 static bool write_array_type_def(const array_type_def_sptr&,
687 write_context&, unsigned);
688 static bool write_enum_type_decl(const enum_type_decl_sptr&,
689 write_context&, unsigned);
690 static bool write_typedef_decl(const typedef_decl_sptr&,
691 write_context&, unsigned);
692 static bool write_elf_symbol(const elf_symbol_sptr&,
693 write_context&, unsigned);
694 static bool write_elf_symbols_table(const elf_symbols&,
695 write_context&, unsigned);
696 static bool write_var_decl(const var_decl_sptr&,
697 write_context&, bool, unsigned);
698 static bool write_function_decl(const function_decl_sptr&,
699 write_context&, bool, unsigned);
700 static bool write_function_type(const function_type_sptr&,
701 write_context&, unsigned);
702 static bool write_member_type_opening_tag(const type_base_sptr&,
703 write_context&, unsigned);
704 static bool write_member_type(const type_base_sptr&,
705 write_context&, unsigned);
706 static bool write_class_decl_opening_tag(const class_decl_sptr&, const string&,
707 write_context&, unsigned, bool);
708 static bool write_class_decl(const class_decl_sptr&,
709 write_context&, unsigned);
710 static bool write_union_decl_opening_tag(const union_decl_sptr&, const string&,
711 write_context&, unsigned, bool);
712 static bool write_union_decl(const union_decl_sptr&, const string&,
713 write_context&, unsigned);
714 static bool write_union_decl(const union_decl_sptr&, write_context&, unsigned);
715 static bool write_type_tparameter
716 (const shared_ptr<type_tparameter>, write_context&, unsigned);
717 static bool write_non_type_tparameter
718 (const shared_ptr<non_type_tparameter>, write_context&, unsigned);
719 static bool write_template_tparameter
720 (const shared_ptr<template_tparameter>, write_context&, unsigned);
721 static bool write_type_composition
722 (const shared_ptr<type_composition>, write_context&, unsigned);
723 static bool write_template_parameter(const shared_ptr<template_parameter>,
724 write_context&, unsigned);
725 static void write_template_parameters(const shared_ptr<template_decl>,
726 write_context&, unsigned);
727 static bool write_function_tdecl
728 (const shared_ptr<function_tdecl>,
729 write_context&, unsigned);
730 static bool write_class_tdecl
731 (const shared_ptr<class_tdecl>,
732 write_context&, unsigned);
733 static void do_indent(ostream&, unsigned);
734 static void do_indent_to_level(write_context&, unsigned, unsigned);
735 static unsigned get_indent_to_level(write_context&, unsigned, unsigned);
737 /// Emit nb_whitespaces white spaces into the output stream.
739 do_indent(ostream& o, unsigned nb_whitespaces)
741 for (unsigned i = 0; i < nb_whitespaces; ++i)
745 /// Indent initial_indent + level number of xml element indentation.
747 /// @param ctxt the context of the parsing.
749 /// @param initial_indent the initial number of white space to indent to.
751 /// @param level the number of indentation level to indent to.
753 do_indent_to_level(write_context& ctxt,
754 unsigned initial_indent,
757 do_indent(ctxt.get_ostream(),
758 get_indent_to_level(ctxt, initial_indent, level));
761 /// Return the number of white space of indentation that
762 /// #do_indent_to_level would have used.
764 /// @param ctxt the context of the parsing.
766 /// @param initial_indent the initial number of white space to indent to.
768 /// @param level the number of indentation level to indent to.
770 get_indent_to_level(write_context& ctxt, unsigned initial_indent,
773 int nb_ws = initial_indent +
774 level * ctxt.get_config().get_xml_element_indent();
778 /// Annotate a declaration in form of an ABIXML comment.
780 /// This function is further specialized for declarations and types
781 /// with special requirements.
783 /// @tparam T shall be of type decl_base_sptr or a shared pointer to a
784 /// type derived from it, for the instantiation to be syntactically
787 /// @param decl_sptr the shared pointer to the declaration of type T.
789 /// @param ctxt the context of the parsing.
791 /// @param indent the amount of white space to indent to.
793 /// @return true iff decl is valid.
794 template <typename T>
796 annotate(const T& decl,
803 if (!ctxt.get_annotate())
806 ostream& o = ctxt.get_ostream();
808 do_indent(o, indent);
811 << xml::escape_xml_comment(decl->get_pretty_representation())
817 /// Annotate an elf symbol in form of an ABIXML comment, effectively
818 /// writing out its demangled form.
820 /// @param sym the symbol, whose name should be demangled.
822 /// @param ctxt the context of the parsing.
824 /// @param indent the amount of white space to indent to.
826 /// @return true iff decl is valid
829 annotate(const elf_symbol_sptr& sym,
836 if (!ctxt.get_annotate())
839 ostream& o = ctxt.get_ostream();
841 do_indent(o, indent);
843 << xml::escape_xml_comment(abigail::ir::demangle_cplus_mangled_name(sym->get_name()))
849 /// Annotate a typedef declaration in form of an ABIXML comment.
851 /// @param typedef_decl the typedef to annotate.
853 /// @param ctxt the context of the parsing.
855 /// @param indent the amount of white space to indent to.
857 /// @return true iff decl is valid
860 annotate(const typedef_decl_sptr& typedef_decl,
867 if (!ctxt.get_annotate())
870 ostream& o = ctxt.get_ostream();
872 do_indent(o, indent);
875 << get_type_name(typedef_decl->get_underlying_type())
877 << get_type_name(typedef_decl)
883 /// Annotate a function type in form of an ABIXML comment.
885 /// @param function_type the function type to annotate.
887 /// @param ctxt the context of the parsing.
889 /// @param indent the amount of white space to indent to.
891 /// @param skip_first_parm if true, do not serialize the first
892 /// parameter of the function decl.
894 /// @return true iff decl is valid
896 annotate(const function_type_sptr& function_type,
903 if (!ctxt.get_annotate())
906 ostream& o = ctxt.get_ostream();
908 do_indent(o, indent);
910 << xml::escape_xml_comment(get_type_name(function_type->get_return_type()))
913 vector<shared_ptr<function_decl::parameter> >::const_iterator pi =
914 function_type->get_first_non_implicit_parm();
916 for (; pi != function_type->get_parameters().end(); ++pi)
918 o << xml::escape_xml_comment((*pi)->get_type_name());
919 // emit a comma after a param type, unless it's the last one
920 if (distance(pi, function_type->get_parameters().end()) > 1)
928 /// Annotate a function declaration in form of an ABIXML comment.
930 /// @param fn the function decl to annotate.
932 /// @param ctxt the context of the parsing.
934 /// @param indent the amount of white space to indent to.
936 /// @param skip_first_parm if true, do not serialize the first
937 /// parameter of the function decl.
939 /// @return true iff decl is valid
941 annotate(const function_decl_sptr& fn,
948 if (!ctxt.get_annotate())
951 ostream& o = ctxt.get_ostream();
953 do_indent(o, indent);
956 if (is_member_function(fn)
957 && (get_member_function_is_ctor(fn) || get_member_function_is_dtor(fn)))
958 ; // we don't emit return types for ctor or dtors
960 o << xml::escape_xml_comment(get_type_name(fn->get_return_type()))
963 o << xml::escape_xml_comment(fn->get_qualified_name()) << "(";
965 vector<function_decl::parameter_sptr>::const_iterator pi =
966 fn->get_first_non_implicit_parm();
968 for (; pi != fn->get_parameters().end(); ++pi)
970 o << xml::escape_xml_comment((*pi)->get_type_name());
971 // emit a comma after a param type, unless it's the last one
972 if (distance(pi, fn->get_parameters().end()) > 1)
980 /// Annotate a function parameter in form of an ABIXML comment.
982 /// @param parm the function parameter to annotate.
984 /// @param ctxt the context of the parsing.
986 /// @param indent the amount of white space to indent to.
988 /// @return true iff decl is valid
991 annotate(const function_decl::parameter_sptr& parm,
998 if (!ctxt.get_annotate())
1001 ostream &o = ctxt.get_ostream();
1003 do_indent(o, indent);
1007 if (parm->get_variadic_marker())
1008 o << "variadic parameter";
1011 if (parm->get_artificial())
1013 if (parm->get_index() == 0)
1018 o << "parameter of type '"
1019 << xml::escape_xml_comment(get_pretty_representation(parm->get_type()));
1027 /// Write a location to the output stream.
1029 /// If the location is empty, nothing is written.
1031 /// @param loc the location to consider.
1033 /// @param tu the translation unit the location belongs to.
1035 /// @param ctxt the writer context to use.
1037 write_location(const location& loc, write_context& ctxt)
1042 if (!ctxt.get_show_locs())
1046 unsigned line = 0, column = 0;
1048 loc.expand(filepath, line, column);
1050 ostream &o = ctxt.get_ostream();
1052 o << " filepath='" << xml::escape_xml_string(filepath) << "'"
1053 << " line='" << line << "'"
1054 << " column='" << column << "'";
1057 /// Write the location of a decl to the output stream.
1059 /// If the location is empty, nothing is written.
1061 /// @param decl the decl to consider.
1063 /// @param ctxt the @ref writer_context to use.
1065 write_location(const decl_base_sptr& decl,
1066 write_context& ctxt)
1071 location loc = decl->get_location();
1075 write_location(loc, ctxt);
1078 /// Serialize the visibility property of the current decl as the
1079 /// 'visibility' attribute for the current xml element.
1081 /// @param decl the instance of decl_base to consider.
1083 /// @param o the output stream to serialize the property to.
1085 /// @return true upon successful completion, false otherwise.
1087 write_visibility(const shared_ptr<decl_base>& decl, ostream& o)
1092 decl_base::visibility v = decl->get_visibility();
1097 case decl_base::VISIBILITY_NONE:
1099 case decl_base::VISIBILITY_DEFAULT:
1102 case decl_base::VISIBILITY_PROTECTED:
1105 case decl_base::VISIBILITY_HIDDEN:
1108 case decl_base::VISIBILITY_INTERNAL:
1116 o << " visibility='" << str << "'";
1121 /// Serialize the 'binding' property of the current decl.
1123 /// @param decl the decl to consider.
1125 /// @param o the output stream to serialize the property to.
1127 write_binding(const shared_ptr<decl_base>& decl, ostream& o)
1132 decl_base::binding bind = decl_base::BINDING_NONE;
1134 shared_ptr<var_decl> var =
1135 dynamic_pointer_cast<var_decl>(decl);
1137 bind = var->get_binding();
1140 shared_ptr<function_decl> fun =
1141 dynamic_pointer_cast<function_decl>(decl);
1143 bind = fun->get_binding();
1149 case decl_base::BINDING_NONE:
1151 case decl_base::BINDING_LOCAL:
1154 case decl_base::BINDING_GLOBAL:
1157 case decl_base::BINDING_WEAK:
1163 o << " binding='" << str << "'";
1168 /// Serialize the size and alignment attributes of a given type.
1170 /// @param decl the type to consider.
1172 /// @param o the output stream to serialize to.
1174 write_size_and_alignment(const shared_ptr<type_base> decl, ostream& o)
1176 size_t size_in_bits = decl->get_size_in_bits();
1178 o << " size-in-bits='" << size_in_bits << "'";
1180 size_t alignment_in_bits = decl->get_alignment_in_bits();
1181 if (alignment_in_bits)
1182 o << " alignment-in-bits='" << alignment_in_bits << "'";
1185 /// Serialize the size and alignment attributes of a given type.
1186 /// @param decl the type to consider.
1188 /// @param o the output stream to serialize to.
1190 write_array_size_and_alignment(const shared_ptr<array_type_def> decl, ostream& o)
1192 if (decl->is_infinite())
1193 o << " size-in-bits='" << "infinite" << "'";
1195 size_t size_in_bits = decl->get_size_in_bits();
1197 o << " size-in-bits='" << size_in_bits << "'";
1200 size_t alignment_in_bits = decl->get_alignment_in_bits();
1201 if (alignment_in_bits)
1202 o << " alignment-in-bits='" << alignment_in_bits << "'";
1204 /// Serialize the access specifier.
1206 /// @param a the access specifier to serialize.
1208 /// @param o the output stream to serialize it to.
1210 write_access(access_specifier a, ostream& o)
1212 string access_str = "private";
1216 case private_access:
1217 access_str = "private";
1220 case protected_access:
1221 access_str = "protected";
1225 access_str = "public";
1232 o << " access='" << access_str << "'";
1235 /// Serialize the layout offset of a data member.
1237 write_layout_offset(var_decl_sptr member, ostream& o)
1239 if (!is_data_member(member))
1242 if (get_data_member_is_laid_out(member))
1243 o << " layout-offset-in-bits='"
1244 << get_data_member_offset(member)
1248 /// Serialize the layout offset of a base class
1250 write_layout_offset(shared_ptr<class_decl::base_spec> base, ostream& o)
1255 if (base->get_offset_in_bits() >= 0)
1256 o << " layout-offset-in-bits='" << base->get_offset_in_bits() << "'";
1259 /// Serialize the access specifier of a class member.
1261 /// @param member a pointer to the class member to consider.
1263 /// @param o the ostream to serialize the member to.
1265 write_access(decl_base_sptr member, ostream& o)
1266 {write_access(get_member_access_specifier(member), o);}
1268 /// Write the voffset of a member function if it's non-zero
1270 /// @param fn the member function to consider
1272 /// @param o the output stream to write to
1274 write_voffset(function_decl_sptr fn, ostream&o)
1279 if (get_member_function_is_virtual(fn))
1281 ssize_t voffset = get_member_function_vtable_offset(fn);
1282 o << " vtable-offset='" << voffset << "'";
1286 /// Serialize an elf_symbol::type into an XML node attribute named
1289 /// @param t the elf_symbol::type to serialize.
1291 /// @param o the output stream to serialize it to.
1293 write_elf_symbol_type(elf_symbol::type t, ostream& o)
1299 case elf_symbol::NOTYPE_TYPE:
1302 case elf_symbol::OBJECT_TYPE:
1303 repr = "object-type";
1305 case elf_symbol::FUNC_TYPE:
1308 case elf_symbol::SECTION_TYPE:
1309 repr = "section-type";
1311 case elf_symbol::FILE_TYPE:
1314 case elf_symbol::COMMON_TYPE:
1315 repr = "common-type";
1317 case elf_symbol::TLS_TYPE:
1320 case elf_symbol::GNU_IFUNC_TYPE:
1321 repr = "gnu-ifunc-type";
1328 o << " type='" << repr << "'";
1331 /// Serialize an elf_symbol::binding into an XML element attribute of
1334 /// @param b the elf_symbol::binding to serialize.
1336 /// @param o the output stream to serialize the binding to.
1338 write_elf_symbol_binding(elf_symbol::binding b, ostream& o)
1344 case elf_symbol::LOCAL_BINDING:
1345 repr = "local-binding";
1347 case elf_symbol::GLOBAL_BINDING:
1348 repr = "global-binding";
1350 case elf_symbol::WEAK_BINDING:
1351 repr = "weak-binding";
1353 case elf_symbol::GNU_UNIQUE_BINDING:
1354 repr = "gnu-unique-binding";
1357 repr = "no-binding";
1361 o << " binding='" << repr << "'";
1364 /// Serialize an elf_symbol::binding into an XML element attribute of
1367 /// @param b the elf_symbol::binding to serialize.
1369 /// @param o the output stream to serialize the binding to.
1371 write_elf_symbol_visibility(elf_symbol::visibility v, ostream& o)
1377 case elf_symbol::DEFAULT_VISIBILITY:
1378 repr = "default-visibility";
1380 case elf_symbol::PROTECTED_VISIBILITY:
1381 repr = "protected-visibility";
1383 case elf_symbol::HIDDEN_VISIBILITY:
1384 repr = "hidden-visibility";
1386 case elf_symbol::INTERNAL_VISIBILITY:
1387 repr = "internal-visibility";
1390 repr = "default-visibility";
1394 o << " visibility='" << repr << "'";
1397 /// Write alias attributes for the aliases of a given symbol.
1399 /// @param sym the symbol to write the attributes for.
1401 /// @param o the output stream to write the attributes to.
1403 /// @return true upon successful completion.
1405 write_elf_symbol_aliases(const elf_symbol& sym, ostream& o)
1407 if (!sym.is_main_symbol() || !sym.has_aliases())
1410 bool emitted = false;
1412 for (elf_symbol_sptr s = sym.get_next_alias();
1413 !s->is_main_symbol();
1414 s = s->get_next_alias())
1416 if (s->get_next_alias()->is_main_symbol())
1417 o << s->get_id_string() << "'";
1419 o << s->get_id_string() << ",";
1427 /// Write an XML attribute for the reference to a symbol for the
1430 /// @param sym the symbol to consider.
1432 /// @param o the output stream to write the attribute to.
1434 /// @return true upon successful completion.
1436 write_elf_symbol_reference(const elf_symbol& sym, ostream& o)
1438 o << " elf-symbol-id='" << sym.get_id_string() << "'";
1442 /// Write an XML attribute for the reference to a symbol for the
1445 /// @param sym the symbol to consider.
1447 /// @param o the output stream to write the attribute to.
1449 /// @return true upon successful completion.
1451 write_elf_symbol_reference(const elf_symbol_sptr sym, ostream& o)
1456 return write_elf_symbol_reference(*sym, o);
1459 /// Serialize the attributes "constructor", "destructor" or "static"
1460 /// if they have true value.
1462 /// @param is_ctor if set to true, the "constructor='true'" string is
1465 /// @param is_dtor if set to true the "destructor='true' string is
1468 /// @param is_static if set to true the "static='true'" string is
1471 /// @param o the output stream to use for the serialization.
1473 write_cdtor_const_static(bool is_ctor,
1480 o << " static='yes'";
1482 o << " constructor='yes'";
1484 o << " destructor='yes'";
1486 o << " const='yes'";
1489 /// Serialize the attribute "is-declaration-only", if the class or
1490 /// union has its 'is_declaration_only property set.
1492 /// @param t the pointer to instance of @ref class_or_union to
1495 /// @param o the output stream to serialize to.
1497 write_class_or_union_is_declaration_only(const class_or_union_sptr& t,
1500 if (t->get_is_declaration_only())
1501 o << " is-declaration-only='yes'";
1504 /// Serialize the attribute "is-struct", if the current instance of
1505 /// class_decl is a struct.
1507 /// @param klass a pointer to the instance of class_decl to consider.
1509 /// @param o the output stream to serialize to.
1511 write_is_struct(const class_decl_sptr& klass, ostream& o)
1513 if (klass->is_struct())
1514 o << " is-struct='yes'";
1517 /// Serialize the attribute "is-anonymous", if the current instance of
1518 /// decl is anonymous
1520 /// @param dcl a pointer to the instance of @ref decl_base to consider.
1522 /// @param o the output stream to serialize to.
1524 write_is_anonymous(const decl_base_sptr& decl, ostream& o)
1526 if (decl->get_is_anonymous())
1527 o << " is-anonymous='yes'";
1530 /// Serialize the "naming-typedef-id" attribute, if the current
1531 /// instance of @ref class_decl has a naming typedef.
1533 /// @param klass the @ref class_decl to consider.
1535 /// @param ctxt the write context to use.
1537 write_naming_typedef(const class_decl_sptr& klass, write_context& ctxt)
1542 ostream &o = ctxt.get_ostream();
1544 if (typedef_decl_sptr typedef_type = klass->get_naming_typedef())
1546 string id = ctxt.get_id_for_type(typedef_type);
1547 o << " naming-typedef-id='" << id << "'";
1551 /// Serialize a pointer to an of decl_base into an output stream.
1553 /// @param decl the pointer to decl_base to serialize
1555 /// @param ctxt the context of the serialization. It contains e.g, the
1556 /// output stream to serialize to.
1558 /// @param indent how many indentation spaces to use during the
1561 /// @return true upon successful completion, false otherwise.
1563 write_decl(const decl_base_sptr& decl, write_context& ctxt, unsigned indent)
1565 if (write_type_decl(dynamic_pointer_cast<type_decl> (decl),
1567 || write_namespace_decl(dynamic_pointer_cast<namespace_decl>(decl),
1569 || write_qualified_type_def (dynamic_pointer_cast<qualified_type_def>
1572 || write_pointer_type_def(dynamic_pointer_cast<pointer_type_def>(decl),
1574 || write_reference_type_def(dynamic_pointer_cast
1575 <reference_type_def>(decl), ctxt, indent)
1576 || write_array_type_def(dynamic_pointer_cast
1577 <array_type_def>(decl), ctxt, indent)
1578 || write_enum_type_decl(dynamic_pointer_cast<enum_type_decl>(decl),
1580 || write_typedef_decl(dynamic_pointer_cast<typedef_decl>(decl),
1582 || write_var_decl(dynamic_pointer_cast<var_decl>(decl), ctxt,
1583 /*write_linkage_name=*/true, indent)
1584 || write_function_decl(dynamic_pointer_cast<method_decl>
1585 (decl), ctxt, /*skip_first_parameter=*/true,
1587 || write_function_decl(dynamic_pointer_cast<function_decl>(decl),
1588 ctxt, /*skip_first_parameter=*/false, indent)
1589 || write_class_decl(is_class_type(decl), ctxt, indent)
1590 || write_union_decl(is_union_type(decl), ctxt, indent)
1591 || (write_function_tdecl
1592 (dynamic_pointer_cast<function_tdecl>(decl), ctxt, indent))
1593 || (write_class_tdecl
1594 (dynamic_pointer_cast<class_tdecl>(decl), ctxt, indent)))
1600 /// Emit a declaration, along with its scope.
1602 /// This function is called at the end of emitting a translation unit,
1603 /// to emit type declarations that were referenced by types that were
1604 /// emitted in the TU already, but that were not emitted themselves.
1606 /// @param decl the decl to emit.
1608 /// @param ctxt the write context to use.
1610 /// @param initial_indent the number of indentation spaces to use.
1612 write_decl_in_scope(const decl_base_sptr& decl,
1613 write_context& ctxt,
1614 unsigned initial_indent)
1616 type_base_sptr type = is_type(decl);
1619 if (ctxt.type_is_emitted(type))
1622 list<scope_decl*> scopes;
1623 for (scope_decl* s = decl->get_scope();
1624 s && !is_global_scope(s);
1626 scopes.push_front(s);
1628 ostream& o = ctxt.get_ostream();
1629 const config& c = ctxt.get_config();
1630 stack<string> closing_tags;
1631 stack<unsigned> closing_indents;
1632 unsigned indent = initial_indent;
1633 bool wrote_context = false;
1634 for (list<scope_decl*>::const_iterator i = scopes.begin();
1638 ABG_ASSERT(!is_global_scope(*i));
1640 if (i != scopes.begin())
1643 // A type scope is either a namespace ...
1644 if (namespace_decl* n = is_namespace(*i))
1646 do_indent(o, indent);
1647 o << "<namespace-decl name='"
1648 << xml::escape_xml_string(n->get_name())
1650 closing_tags.push("</namespace-decl>");
1651 closing_indents.push(indent);
1654 else if (class_decl* c = is_class_type(*i))
1656 class_decl_sptr class_type(c, noop_deleter());
1657 write_class_decl_opening_tag(class_type, "", ctxt, indent,
1658 /*prepare_to_handle_members=*/false);
1659 closing_tags.push("</class-decl>");
1660 closing_indents.push(indent);
1662 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1);
1663 write_member_type_opening_tag(type, ctxt, nb_ws);
1665 closing_tags.push("</member-type>");
1666 closing_indents.push(nb_ws);
1668 else if (union_decl *u = is_union_type(*i))
1670 union_decl_sptr union_type(u, noop_deleter());
1671 write_union_decl_opening_tag(union_type, "", ctxt, indent,
1672 /*prepare_to_handle_members=*/false);
1673 closing_tags.push("</union-decl>");
1674 closing_indents.push(indent);
1676 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1);
1677 write_member_type_opening_tag(type, ctxt, nb_ws);
1679 closing_tags.push("</member-type>");
1680 closing_indents.push(nb_ws);
1683 // We should never reach this point.
1685 indent += c.get_xml_element_indent();
1686 wrote_context = true;
1692 write_decl(decl, ctxt, indent);
1694 while (!closing_tags.empty())
1697 do_indent(o, closing_indents.top());
1698 o << closing_tags.top();
1700 closing_indents.pop();
1704 /// Create a @ref write_context object that can be used to emit abixml
1707 /// @param env the environment for the @ref write_context object to use.
1709 /// @param default_output_stream the default output stream to use.
1711 /// @return the new @ref write_context object.
1713 create_write_context(const environment *env,
1714 ostream& default_output_stream)
1716 write_context_sptr ctxt(new write_context(env, default_output_stream));
1720 /// Set the "show-locs" flag.
1722 /// When this flag is set then the XML writer emits location (///
1723 /// information (file name, line and column) for the ABI artifacts
1726 /// @param ctxt the @ref write_context to set the option for.
1728 /// @param flag the new value of the option.
1730 set_show_locs(write_context& ctxt, bool flag)
1731 {ctxt.set_show_locs(flag);}
1733 /// Set the 'annotate' flag.
1735 /// When this flag is set then the XML writer annotates ABI artifacts
1736 /// with a human readable description.
1738 /// @param ctxt the context to set this flag on to.
1740 /// @param flag the new value of the 'annotate' flag.
1742 set_annotate(write_context& ctxt, bool flag)
1743 {ctxt.set_annotate(flag);}
1745 /// Serialize a translation unit to an output stream.
1747 /// @param ctxt the context of the serialization. It contains e.g,
1748 /// the output stream to serialize to.
1750 /// @param tu the translation unit to serialize.
1752 /// @param indent how many indentation spaces to use during the
1755 /// @return true upon successful completion, false otherwise.
1757 write_translation_unit(write_context& ctxt,
1758 const translation_unit& tu,
1759 const unsigned indent)
1761 ostream& o = ctxt.get_ostream();
1762 const config& c = ctxt.get_config();
1764 do_indent(o, indent);
1766 o << "<abi-instr version='"
1767 << c.get_format_major_version_number()
1768 << "." << c.get_format_minor_version_number()
1771 if (tu.get_address_size() != 0)
1772 o << " address-size='" << static_cast<int>(tu.get_address_size()) << "'";
1774 if (!tu.get_path().empty())
1775 o << " path='" << xml::escape_xml_string(tu.get_path()) << "'";
1777 if (!tu.get_compilation_dir_path().empty())
1778 o << " comp-dir-path='"
1779 << xml::escape_xml_string(tu.get_compilation_dir_path()) << "'";
1781 if (tu.get_language() != translation_unit::LANG_UNKNOWN)
1783 << translation_unit_language_to_string(tu.get_language())
1794 typedef scope_decl::declarations declarations;
1795 typedef declarations::const_iterator const_iterator;
1796 const declarations& d = tu.get_global_scope()->get_member_decls();
1798 for (const_iterator i = d.begin(); i != d.end(); ++i)
1800 if (type_base_sptr t = is_type(*i))
1801 if (ctxt.type_is_emitted(t))
1802 // This type has already been written out to the current
1803 // translation unit, so do not emit it again.
1806 if (decl_base_sptr d = is_decl(*i))
1807 if (ctxt.decl_is_emitted(d))
1811 write_decl(*i, ctxt, indent + c.get_xml_element_indent());
1814 // Now let's handle types that were referenced, but not yet
1815 // emitted. We must emit those, along with their scope.
1817 // So this map of type -> string is to contain the referenced types
1819 type_ptr_map referenced_types_to_emit;
1821 for (type_ptr_map::const_iterator i = ctxt.get_referenced_types().begin();
1822 i != ctxt.get_referenced_types().end();
1825 type_base_sptr type(i->first, noop_deleter());
1826 if (!ctxt.type_is_emitted(type)
1827 && !ctxt.decl_only_type_is_emitted(type))
1828 // A referenced type that was not emitted at all must be
1830 referenced_types_to_emit[type.get()] = interned_string();
1833 // Ok, now let's emit the referenced type for good.
1834 while (!referenced_types_to_emit.empty())
1836 // But first, we need to sort them, otherwise, emitting the ABI
1837 // (in xml) of the same binary twice will yield different
1838 // results, because we'd be walking an *unordered* hash table.
1839 vector<type_base*> sorted_referenced_types;
1840 ctxt.sort_types(referenced_types_to_emit,
1841 sorted_referenced_types);
1843 // Now, emit the referenced decls in a sorted order.
1844 for (vector<type_base*>::const_iterator i =
1845 sorted_referenced_types.begin();
1846 i != sorted_referenced_types.end();
1849 // We handle types which have declarations *and* function
1851 type_base_sptr t(*i, noop_deleter());
1852 if (!ctxt.type_is_emitted(t))
1854 if (decl_base* d = get_type_declaration(*i))
1856 decl_base_sptr decl(d, noop_deleter());
1858 write_decl_in_scope(decl, ctxt,
1859 indent + c.get_xml_element_indent());
1861 else if (function_type_sptr fn_type = is_function_type(t))
1864 write_function_type(fn_type, ctxt,
1865 indent + c.get_xml_element_indent());
1868 ABG_ASSERT_NOT_REACHED;
1872 // So all referenced types that we wanted to emit were emitted.
1873 referenced_types_to_emit.clear();
1875 // But then, while emitting those referenced type, other types
1876 // might have been referenced by those referenced types
1877 // themselves! So let's look at the map of referenced type that
1878 // is maintained for the entire ABI corpus and see if there are
1879 // still some referenced types in there that are not emitted
1880 // yet. If yes, then we'll emit those again.
1881 for (type_ptr_map::const_iterator i =
1882 ctxt.get_referenced_types().begin();
1883 i != ctxt.get_referenced_types().end();
1886 type_base_sptr type(i->first, noop_deleter());
1887 if (!ctxt.type_is_emitted(type)
1888 && !ctxt.decl_only_type_is_emitted(type))
1889 referenced_types_to_emit[type.get()] = interned_string();
1893 // Now handle all function types that were not only referenced by
1895 const vector<function_type_sptr>& t = tu.get_live_fn_types();
1896 vector<type_base_sptr> sorted_types;
1897 ctxt.sort_types(t, sorted_types);
1899 for (vector<type_base_sptr>::const_iterator i = sorted_types.begin();
1900 i != sorted_types.end();
1903 function_type_sptr fn_type = is_function_type(*i);
1905 if (!ctxt.type_is_referenced(fn_type) || ctxt.type_is_emitted(fn_type))
1906 // This function type is either not referenced by any emitted
1907 // pointer or reference type, or has already been emitted, so skip it.
1910 ABG_ASSERT(fn_type);
1912 write_function_type(fn_type, ctxt, indent + c.get_xml_element_indent());
1916 do_indent(o, indent);
1917 o << "</abi-instr>\n";
1922 /// Serialize a translation unit to an output stream.
1924 /// @param tu the translation unit to serialize.
1926 /// @param indent how many indentation spaces to use during the
1929 /// @param out the output stream to serialize the translation unit to.
1931 /// @param annotate whether to annotate the output with debug information
1933 /// @deprecated use write_translation_unit(ctct, tu, indent)
1935 /// @return true upon successful completion, false otherwise.
1937 write_translation_unit(const translation_unit& tu,
1940 const bool annotate)
1942 write_context ctxt(tu.get_environment(), out);
1943 set_annotate(ctxt, annotate);
1944 return write_translation_unit(ctxt, tu, indent);
1947 /// Serialize a translation unit to a file.
1949 /// @param tu the translation unit to serialize.
1951 /// @param indent how many indentation spaces to use during the
1954 /// @param path the file to serialize the translation unit to.
1956 /// @param annotate whether to annotate the output with debug information
1958 /// @deprecated use write_translation_unit(ctct, tu, indent)
1960 /// @return true upon successful completion, false otherwise.
1962 write_translation_unit(const translation_unit& tu,
1965 const bool annotate)
1971 ofstream of(path.c_str(), std::ios_base::trunc);
1974 cerr << "failed to access " << path << "\n";
1978 write_context ctxt(tu.get_environment(), of);
1979 set_annotate(ctxt, annotate);
1980 if (!write_translation_unit(ctxt, tu, indent))
1982 cerr << "failed to access " << path << "\n";
1990 cerr << "failed to write to " << path << "\n";
1998 /// Serialize a pointer to an instance of basic type declaration, into
1999 /// an output stream.
2001 /// @param d the basic type declaration to serialize.
2003 /// @param ctxt the context of the serialization. It contains e.g, the
2004 /// output stream to serialize to.
2006 /// @param indent how many indentation spaces to use during the
2009 /// @return true upon successful completion, false otherwise.
2011 write_type_decl(const type_decl_sptr& d, write_context& ctxt, unsigned indent)
2016 ostream& o = ctxt.get_ostream();
2018 annotate(d, ctxt, indent);
2020 do_indent(o, indent);
2022 o << "<type-decl name='" << xml::escape_xml_string(d->get_name()) << "'";
2024 write_is_anonymous(d, o);
2026 write_size_and_alignment(d, o);
2028 write_location(d, ctxt);
2030 o << " id='" << ctxt.get_id_for_type(d) << "'" << "/>";
2032 ctxt.record_type_as_emitted(d);
2037 /// Serialize a namespace declaration int an output stream.
2039 /// @param decl the namespace declaration to serialize.
2041 /// @param ctxt the context of the serialization. It contains e.g, the
2042 /// output stream to serialize to.
2044 /// @param indent how many indentation spaces to use during the
2047 /// @return true upon successful completion, false otherwise.
2049 write_namespace_decl(const namespace_decl_sptr& decl,
2050 write_context& ctxt, unsigned indent)
2052 if (!decl || decl->is_empty_or_has_empty_sub_namespaces())
2055 ostream& o = ctxt.get_ostream();
2056 const config &c = ctxt.get_config();
2058 annotate(decl, ctxt, indent);
2060 do_indent(o, indent);
2062 o << "<namespace-decl name='"
2063 << xml::escape_xml_string(decl->get_name())
2066 typedef scope_decl::declarations declarations;
2067 typedef declarations::const_iterator const_iterator;
2068 const declarations& d = decl->get_member_decls();
2070 for (const_iterator i = d.begin(); i != d.end(); ++i)
2072 if (type_base_sptr t = is_type(*i))
2073 if (ctxt.type_is_emitted(t))
2074 // This type has already been emitted to the current
2075 // translation unit so do not emit it again.
2078 write_decl(*i, ctxt, indent + c.get_xml_element_indent());
2082 do_indent(o, indent);
2083 o << "</namespace-decl>";
2088 /// Serialize a qualified type declaration to an output stream.
2090 /// @param decl the qualfied type declaration to write.
2092 /// @param id the type id identitifier to use in the serialized
2093 /// output. If this is empty, the function will compute an
2094 /// appropriate one. This is useful when this function is called to
2095 /// serialize the underlying type of a member type; in that case, the
2096 /// caller has already computed the id of the *member type*, and that
2097 /// id is the one to be written as the value of the 'id' attribute of
2098 /// the XML element of the underlying type.
2100 /// @param ctxt the write context.
2102 /// @param indent the number of space to indent to during the
2105 /// @return true upon successful completion, false otherwise.
2107 write_qualified_type_def(const qualified_type_def_sptr& decl,
2109 write_context& ctxt,
2115 ostream& o = ctxt.get_ostream();
2118 type_base_sptr underlying_type = decl->get_underlying_type();
2120 annotate(decl, ctxt, indent);
2122 do_indent(o, indent);
2123 o << "<qualified-type-def type-id='"
2124 << ctxt.get_id_for_type(underlying_type)
2127 ctxt.record_type_as_referenced(underlying_type);
2129 if (decl->get_cv_quals() & qualified_type_def::CV_CONST)
2130 o << " const='yes'";
2131 if (decl->get_cv_quals() & qualified_type_def::CV_VOLATILE)
2132 o << " volatile='yes'";
2133 if (decl->get_cv_quals() & qualified_type_def::CV_RESTRICT)
2134 o << " restrict='yes'";
2136 write_location(static_pointer_cast<decl_base>(decl), ctxt);
2140 i = ctxt.get_id_for_type(decl);
2142 o<< " id='" << i << "'/>";
2144 ctxt.record_type_as_emitted(decl);
2149 /// Serialize a qualified type declaration to an output stream.
2151 /// @param decl the qualfied type declaration to write.
2153 /// @param ctxt the write context.
2155 /// @param indent the number of space to indent to during the
2158 /// @return true upon successful completion, false otherwise.
2160 write_qualified_type_def(const qualified_type_def_sptr& decl,
2161 write_context& ctxt,
2163 {return write_qualified_type_def(decl, "", ctxt, indent);}
2165 /// Serialize a pointer to an instance of pointer_type_def.
2167 /// @param decl the pointer_type_def to serialize.
2169 /// @param id the type id identitifier to use in the serialized
2170 /// output. If this is empty, the function will compute an
2171 /// appropriate one. This is useful when this function is called to
2172 /// serialize the underlying type of a member type; in that case, the
2173 /// caller has already computed the id of the *member type*, and that
2174 /// id is the one to be written as the value of the 'id' attribute of
2175 /// the XML element of the underlying type.
2177 /// @param ctxt the context of the serialization.
2179 /// @param indent the number of indentation white spaces to use.
2181 /// @return true upon succesful completion, false otherwise.
2183 write_pointer_type_def(const pointer_type_def_sptr& decl,
2185 write_context& ctxt,
2191 ostream& o = ctxt.get_ostream();
2194 type_base_sptr pointed_to_type = decl->get_pointed_to_type();
2196 annotate(decl->get_canonical_type(), ctxt, indent);
2198 do_indent(o, indent);
2199 o << "<pointer-type-def type-id='"
2200 << ctxt.get_id_for_type(pointed_to_type)
2203 ctxt.record_type_as_referenced(pointed_to_type);
2205 write_size_and_alignment(decl, o);
2209 i = ctxt.get_id_for_type(decl);
2211 o << " id='" << i << "'";
2213 write_location(static_pointer_cast<decl_base>(decl), ctxt);
2216 ctxt.record_type_as_emitted(decl);
2221 /// Serialize a pointer to an instance of pointer_type_def.
2223 /// @param decl the pointer_type_def to serialize.
2225 /// @param ctxt the context of the serialization.
2227 /// @param indent the number of indentation white spaces to use.
2229 /// @return true upon succesful completion, false otherwise.
2231 write_pointer_type_def(const pointer_type_def_sptr& decl,
2232 write_context& ctxt,
2234 {return write_pointer_type_def(decl, "", ctxt, indent);}
2236 /// Serialize a pointer to an instance of reference_type_def.
2238 /// @param decl the reference_type_def to serialize.
2240 /// @param id the type id identitifier to use in the serialized
2241 /// output. If this is empty, the function will compute an
2242 /// appropriate one. This is useful when this function is called to
2243 /// serialize the underlying type of a member type; in that case, the
2244 /// caller has already computed the id of the *member type*, and that
2245 /// id is the one to be written as the value of the 'id' attribute of
2246 /// the XML element of the underlying type.
2248 /// @param ctxt the context of the serialization.
2250 /// @param indent the number of indentation white spaces to use.
2252 /// @return true upon succesful completion, false otherwise.
2254 write_reference_type_def(const reference_type_def_sptr& decl,
2256 write_context& ctxt,
2262 annotate(decl->get_canonical_type(), ctxt, indent);
2264 ostream& o = ctxt.get_ostream();
2266 do_indent(o, indent);
2268 o << "<reference-type-def kind='";
2269 if (decl->is_lvalue())
2275 type_base_sptr pointed_to_type = decl->get_pointed_to_type();
2276 o << " type-id='" << ctxt.get_id_for_type(pointed_to_type) << "'";
2278 ctxt.record_type_as_referenced(pointed_to_type);
2280 if (function_type_sptr f = is_function_type(decl->get_pointed_to_type()))
2281 ctxt.record_type_as_referenced(f);
2283 write_size_and_alignment(decl, o);
2287 i = ctxt.get_id_for_type(decl);
2288 o << " id='" << i << "'";
2290 write_location(static_pointer_cast<decl_base>(decl), ctxt);
2294 ctxt.record_type_as_emitted(decl);
2299 /// Serialize a pointer to an instance of reference_type_def.
2301 /// @param decl the reference_type_def to serialize.
2303 /// @param ctxt the context of the serialization.
2305 /// @param indent the number of indentation white spaces to use.
2307 /// @return true upon succesful completion, false otherwise.
2309 write_reference_type_def(const reference_type_def_sptr& decl,
2310 write_context& ctxt,
2312 {return write_reference_type_def(decl, "", ctxt, indent);}
2314 /// Serialize an instance of @ref array_type_def::subrange_type.
2316 /// @param decl the array_type_def::subrange_type to serialize.
2318 /// @param ctxt the context of the serialization.
2320 /// @param indent the number of indentation white spaces to use.
2322 /// return true upon successful completion, false otherwise.
2324 write_array_subrange_type(const array_type_def::subrange_sptr& decl,
2325 write_context& ctxt,
2331 annotate(decl, ctxt, indent);
2333 ostream& o = ctxt.get_ostream();
2335 do_indent(o, indent);
2339 if (!decl->get_name().empty())
2340 o << " name='" << decl->get_name() << "'";
2343 if (decl->is_infinite())
2346 o << decl->get_length();
2350 type_base_sptr underlying_type = decl->get_underlying_type();
2351 if (underlying_type)
2354 << ctxt.get_id_for_type(underlying_type)
2356 ctxt.record_type_as_referenced(underlying_type);
2359 o << " id='" << ctxt.get_id_for_type(decl) << "'";
2361 write_location(decl->get_location(), ctxt);
2368 /// Serialize a pointer to an instance of array_type_def.
2370 /// @param decl the array_type_def to serialize.
2372 /// @param id the type id identitifier to use in the serialized
2373 /// output. If this is empty, the function will compute an
2374 /// appropriate one. This is useful when this function is called to
2375 /// serialize the underlying type of a member type; in that case, the
2376 /// caller has already computed the id of the *member type*, and that
2377 /// id is the one to be written as the value of the 'id' attribute of
2378 /// the XML element of the underlying type.
2380 /// @param ctxt the context of the serialization.
2382 /// @param indent the number of indentation white spaces to use.
2384 /// @return true upon succesful completion, false otherwise.
2386 write_array_type_def(const array_type_def_sptr& decl,
2388 write_context& ctxt,
2394 annotate(decl, ctxt, indent);
2396 ostream& o = ctxt.get_ostream();
2398 do_indent(o, indent);
2399 o << "<array-type-def";
2401 o << " dimensions='" << decl->get_dimension_count() << "'";
2403 type_base_sptr element_type = decl->get_element_type();
2404 o << " type-id='" << ctxt.get_id_for_type(element_type) << "'";
2406 ctxt.record_type_as_referenced(element_type);
2408 write_array_size_and_alignment(decl, o);
2412 i = ctxt.get_id_for_type(decl);
2413 o << " id='" << i << "'";
2415 write_location(static_pointer_cast<decl_base>(decl), ctxt);
2417 if (!decl->get_dimension_count())
2423 vector<array_type_def::subrange_sptr>::const_iterator si;
2425 for (si = decl->get_subranges().begin();
2426 si != decl->get_subranges().end(); ++si)
2428 unsigned local_indent =
2429 indent + ctxt.get_config().get_xml_element_indent();
2430 write_array_subrange_type(*si, ctxt, local_indent);
2434 do_indent(o, indent);
2435 o << "</array-type-def>";
2438 ctxt.record_type_as_emitted(decl);
2443 /// Serialize a pointer to an instance of array_type_def.
2445 /// @param decl the array_type_def to serialize.
2447 /// @param ctxt the context of the serialization.
2449 /// @param indent the number of indentation white spaces to use.
2451 /// @return true upon succesful completion, false otherwise.
2453 write_array_type_def(const array_type_def_sptr& decl,
2454 write_context& ctxt,
2456 {return write_array_type_def(decl, "", ctxt, indent);}
2458 /// Serialize a pointer to an instance of enum_type_decl.
2460 /// @param decl the enum_type_decl to serialize.
2462 /// @param id the type id identitifier to use in the serialized
2463 /// output. If this is empty, the function will compute an
2464 /// appropriate one. This is useful when this function is called to
2465 /// serialize the underlying type of a member type; in that case, the
2466 /// caller has already computed the id of the *member type*, and that
2467 /// id is the one to be written as the value of the 'id' attribute of
2468 /// the XML element of the underlying type.
2470 /// @param ctxt the context of the serialization.
2472 /// @param indent the number of indentation white spaces to use.
2474 /// @return true upon succesful completion, false otherwise.
2476 write_enum_type_decl(const enum_type_decl_sptr& decl,
2478 write_context& ctxt,
2484 annotate(decl->get_canonical_type(), ctxt, indent);
2486 ostream& o = ctxt.get_ostream();
2488 do_indent(o, indent);
2489 o << "<enum-decl name='" << xml::escape_xml_string(decl->get_name()) << "'";
2491 write_is_anonymous(decl, o);
2493 if (!decl->get_linkage_name().empty())
2494 o << " linkage-name='" << decl->get_linkage_name() << "'";
2496 write_location(decl, ctxt);
2500 i = ctxt.get_id_for_type(decl);
2501 o << " id='" << i << "'>\n";
2503 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
2504 o << "<underlying-type type-id='"
2505 << ctxt.get_id_for_type(decl->get_underlying_type())
2508 for (enum_type_decl::enumerators::const_iterator i =
2509 decl->get_enumerators().begin();
2510 i != decl->get_enumerators().end();
2513 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
2514 o << "<enumerator name='"
2521 do_indent(o, indent);
2522 o << "</enum-decl>";
2524 ctxt.record_type_as_emitted(decl);
2529 /// Serialize a pointer to an instance of enum_type_decl.
2531 /// @param decl the enum_type_decl to serialize.
2533 /// @param ctxt the context of the serialization.
2535 /// @param indent the number of indentation white spaces to use.
2537 /// @return true upon succesful completion, false otherwise.
2539 write_enum_type_decl(const enum_type_decl_sptr& decl,
2540 write_context& ctxt,
2542 {return write_enum_type_decl(decl, "", ctxt, indent);}
2544 /// Serialize an @ref elf_symbol to an XML element of name
2547 /// @param sym the elf symbol to serialize.
2549 /// @param ctxt the read context to use.
2551 /// @param indent the number of white spaces to use as indentation.
2553 /// @return true iff the function completed successfully.
2555 write_elf_symbol(const elf_symbol_sptr& sym,
2556 write_context& ctxt,
2562 ostream &o = ctxt.get_ostream();
2564 annotate(sym, ctxt, indent);
2565 do_indent(o, indent);
2566 o << "<elf-symbol name='" << sym->get_name() << "'";
2567 if (sym->is_variable() && sym->get_size())
2568 o << " size='" << sym->get_size() << "'";
2570 if (!sym->get_version().is_empty())
2572 o << " version='" << sym->get_version().str() << "'";
2573 o << " is-default-version='";
2574 if (sym->get_version().is_default())
2581 write_elf_symbol_type(sym->get_type(), o);
2583 write_elf_symbol_binding(sym->get_binding(), o);
2585 write_elf_symbol_visibility(sym->get_visibility(), o);
2587 write_elf_symbol_aliases(*sym, o);
2589 o << " is-defined='";
2590 if (sym->is_defined())
2596 if (sym->is_common_symbol())
2597 o << " is-common='yes'";
2604 /// Write the elf symbol database to the output associated to the
2605 /// current context.
2607 /// @param syms the sorted elf symbol data to write out.
2609 /// @param ctxt the context to consider.
2611 /// @param indent the number of white spaces to use as indentation.
2613 /// @return true upon successful completion.
2615 write_elf_symbols_table(const elf_symbols& syms,
2616 write_context& ctxt,
2622 ostream& o = ctxt.get_ostream();
2624 unordered_map<string, bool> emitted_syms;
2625 for (elf_symbols::const_iterator it = syms.begin(); it != syms.end(); ++it)
2627 write_elf_symbol(*it, ctxt, indent);
2634 /// Write a vector of dependency names for the current corpus we are
2637 /// @param needed the vector of dependency names to write.
2639 /// @param ctxt the write context to use for the writting.
2641 /// @param indent the number of indendation spaces to use.
2643 /// @return true upon successful completion, false otherwise.
2645 write_elf_needed(const vector<string>& needed,
2646 write_context& ctxt,
2652 ostream& o = ctxt.get_ostream();
2654 for (vector<string>::const_iterator i = needed.begin();
2658 if (i != needed.begin())
2660 do_indent(o, indent);
2661 o << "<dependency name='" << *i << "'/>";
2666 /// Serialize a pointer to an instance of typedef_decl.
2668 /// @param decl the typedef_decl to serialize.
2670 /// @param id the type id identitifier to use in the serialized
2671 /// output. If this is empty, the function will compute an
2672 /// appropriate one. This is useful when this function is called to
2673 /// serialize the underlying type of a member type; in that case, the
2674 /// caller has already computed the id of the *member type*, and that
2675 /// id is the one to be written as the value of the 'id' attribute of
2676 /// the XML element of the underlying type.
2678 /// @param ctxt the context of the serialization.
2680 /// @param indent the number of indentation white spaces to use.
2682 /// @return true upon succesful completion, false otherwise.
2684 write_typedef_decl(const typedef_decl_sptr& decl,
2686 write_context& ctxt,
2692 ostream &o = ctxt.get_ostream();
2694 annotate(decl, ctxt, indent);
2696 do_indent(o, indent);
2698 o << "<typedef-decl name='"
2699 << xml::escape_xml_string(decl->get_name())
2702 type_base_sptr underlying_type = decl->get_underlying_type();
2703 string type_id = ctxt.get_id_for_type(underlying_type);
2704 o << " type-id='" << type_id << "'";
2705 ctxt.record_type_as_referenced(underlying_type);
2707 write_location(decl, ctxt);
2711 i = ctxt.get_id_for_type(decl);
2713 o << " id='" << i << "'/>";
2715 ctxt.record_type_as_emitted(decl);
2720 /// Serialize a pointer to an instance of typedef_decl.
2722 /// @param decl the typedef_decl to serialize.
2724 /// @param ctxt the context of the serialization.
2726 /// @param indent the number of indentation white spaces to use.
2728 /// @return true upon succesful completion, false otherwise.
2730 write_typedef_decl(const typedef_decl_sptr& decl,
2731 write_context& ctxt,
2733 {return write_typedef_decl(decl, "", ctxt, indent);}
2735 /// Serialize a pointer to an instances of var_decl.
2737 /// @param decl the var_decl to serialize.
2739 /// @param ctxt the context of the serialization.
2741 /// @param write_linkage_name if true, serialize the mangled name of
2744 /// @param indent the number of indentation white spaces to use.
2746 /// @return true upon succesful completion, false otherwise.
2748 write_var_decl(const var_decl_sptr& decl, write_context& ctxt,
2749 bool write_linkage_name, unsigned indent)
2754 annotate(decl, ctxt, indent);
2756 ostream &o = ctxt.get_ostream();
2758 do_indent(o, indent);
2760 o << "<var-decl name='" << xml::escape_xml_string(decl->get_name()) << "'";
2761 type_base_sptr var_type = decl->get_type();
2762 o << " type-id='" << ctxt.get_id_for_type(var_type) << "'";
2763 ctxt.record_type_as_referenced(var_type);
2765 if (write_linkage_name)
2767 const string& linkage_name = decl->get_linkage_name();
2768 if (!linkage_name.empty())
2769 o << " mangled-name='" << linkage_name << "'";
2772 write_visibility(decl, o);
2774 write_binding(decl, o);
2776 write_location(decl, ctxt);
2778 write_elf_symbol_reference(decl->get_symbol(), o);
2782 ctxt.record_decl_as_emitted(decl);
2787 /// Serialize a pointer to a function_decl.
2789 /// @param decl the pointer to function_decl to serialize.
2791 /// @param ctxt the context of the serialization.
2793 /// @param skip_first_parm if true, do not serialize the first
2794 /// parameter of the function decl.
2796 /// @param indent the number of indentation white spaces to use.
2798 /// @return true upon succesful completion, false otherwise.
2800 write_function_decl(const function_decl_sptr& decl, write_context& ctxt,
2801 bool skip_first_parm, unsigned indent)
2806 annotate(decl, ctxt, indent);
2808 ostream &o = ctxt.get_ostream();
2810 do_indent(o, indent);
2812 o << "<function-decl name='"
2813 << xml::escape_xml_string(decl->get_name())
2816 if (!decl->get_linkage_name().empty())
2817 o << " mangled-name='"
2818 << xml::escape_xml_string(decl->get_linkage_name()) << "'";
2820 write_location(decl, ctxt);
2822 if (decl->is_declared_inline())
2823 o << " declared-inline='yes'";
2825 write_visibility(decl, o);
2827 write_binding(decl, o);
2829 write_size_and_alignment(decl->get_type(), o);
2830 write_elf_symbol_reference(decl->get_symbol(), o);
2834 type_base_sptr parm_type;
2835 vector<shared_ptr<function_decl::parameter> >::const_iterator pi =
2836 decl->get_parameters().begin();
2837 for ((skip_first_parm && pi != decl->get_parameters().end()) ? ++pi: pi;
2838 pi != decl->get_parameters().end();
2841 if ((*pi)->get_variadic_marker())
2843 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
2844 o << "<parameter is-variadic='yes'";
2848 parm_type = (*pi)->get_type();
2851 indent + ctxt.get_config().get_xml_element_indent());
2853 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
2855 o << "<parameter type-id='"
2856 << ctxt.get_id_for_type(parm_type)
2858 ctxt.record_type_as_referenced(parm_type);
2860 if (!(*pi)->get_name().empty())
2861 o << " name='" << (*pi)->get_name() << "'";
2863 if ((*pi)->get_artificial())
2864 o << " is-artificial='yes'";
2865 write_location((*pi)->get_location(), ctxt);
2869 if (shared_ptr<type_base> return_type = decl->get_return_type())
2871 annotate(return_type , ctxt,
2872 indent + ctxt.get_config().get_xml_element_indent());
2873 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
2874 o << "<return type-id='" << ctxt.get_id_for_type(return_type) << "'/>\n";
2875 ctxt.record_type_as_referenced(return_type);
2878 do_indent(o, indent);
2879 o << "</function-decl>";
2881 ctxt.record_decl_as_emitted(decl);
2886 /// Serialize a function_type.
2888 /// @param decl the pointer to function_type to serialize.
2890 /// @param ctxt the context of the serialization.
2892 /// @param indent the number of indentation white spaces to use.
2894 /// @return true upon succesful completion, false otherwise.
2896 write_function_type(const function_type_sptr& fn_type,
2897 write_context& ctxt, unsigned indent)
2902 ostream &o = ctxt.get_ostream();
2904 annotate(fn_type, ctxt, indent);
2906 do_indent(o, indent);
2908 o << "<function-type";
2910 write_size_and_alignment(fn_type, o);
2912 if (method_type_sptr method_type = is_method_type(fn_type))
2914 o << " method-class-id='"
2915 << ctxt.get_id_for_type(method_type->get_class_type())
2918 write_cdtor_const_static(/*is_ctor=*/false, /*is_dtor=*/false,
2919 /*is_const=*/method_type->get_is_const(),
2920 /*is_static=*/false, o);
2923 interned_string id = ctxt.get_id_for_type(fn_type);
2929 type_base_sptr parm_type;
2930 for (vector<function_decl::parameter_sptr>::const_iterator pi =
2931 fn_type->get_parameters().begin();
2932 pi != fn_type->get_parameters().end();
2936 if ((*pi)->get_variadic_marker())
2938 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
2939 o << "<parameter is-variadic='yes'";
2943 parm_type = (*pi)->get_type();
2945 annotate(*pi, ctxt, indent + ctxt.get_config().get_xml_element_indent());
2947 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
2948 o << "<parameter type-id='"
2949 << ctxt.get_id_for_type(parm_type)
2951 ctxt.record_type_as_referenced(parm_type);
2953 if (!(*pi)->get_name().empty())
2955 string name = xml::escape_xml_string((*pi)->get_name());
2956 o << " name='" << name << "'";
2959 if ((*pi)->get_artificial())
2960 o << " is-artificial='yes'";
2964 if (type_base_sptr return_type = fn_type->get_return_type())
2966 annotate(return_type, ctxt, indent + ctxt.get_config().get_xml_element_indent());
2967 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
2968 o << "<return type-id='" << ctxt.get_id_for_type(return_type) << "'/>\n";
2969 ctxt.record_type_as_referenced(return_type);
2972 do_indent(o, indent);
2973 o << "</function-type>";
2975 ctxt.record_type_as_emitted(fn_type);
2979 /// Write the opening tag of a 'class-decl' element.
2981 /// @param decl the class declaration to serialize.
2983 /// @param the type ID to use for the 'class-decl' element,, or empty
2984 /// if we need to build a new one.
2986 /// @param ctxt the write context to use.
2988 /// @param indent the number of white space to use for indentation.
2990 /// @param prepare_to_handle_members if set to true, then this function
2991 /// figures out if the opening tag should be for an empty element or
2992 /// not. If set to false, then the opening tag is unconditionnaly for
2993 /// a non-empty element.
2995 /// @return true upon successful completion.
2997 write_class_decl_opening_tag(const class_decl_sptr& decl,
2999 write_context& ctxt,
3001 bool prepare_to_handle_members)
3006 ostream& o = ctxt.get_ostream();
3008 do_indent_to_level(ctxt, indent, 0);
3010 o << "<class-decl name='" << xml::escape_xml_string(decl->get_name()) << "'";
3012 write_size_and_alignment(decl, o);
3014 write_is_struct(decl, o);
3016 write_is_anonymous(decl, o);
3018 write_naming_typedef(decl, ctxt);
3020 write_visibility(decl, o);
3022 write_location(decl, ctxt);
3024 write_class_or_union_is_declaration_only(decl, o);
3026 if (decl->get_earlier_declaration())
3028 // This instance is the definition of an earlier declaration.
3029 o << " def-of-decl-id='"
3030 << ctxt.get_id_for_type(is_type(decl->get_earlier_declaration()))
3036 i = ctxt.get_id_for_type(decl);
3037 o << " id='" << i << "'";
3039 if (!prepare_to_handle_members)
3043 if (decl->has_no_base_nor_member())
3052 /// Write the opening tag of a 'union-decl' element.
3054 /// @param decl the union declaration to serialize.
3056 /// @param the type ID to use for the 'union-decl' element, or empty
3057 /// if we need to build a new one.
3059 /// @param ctxt the write context to use.
3061 /// @param indent the number of white space to use for indentation.
3063 /// @param prepare_to_handle_members if set to true, then this function
3064 /// figures out if the opening tag should be for an empty element or
3065 /// not. If set to false, then the opening tag is unconditionnaly for
3066 /// a non-empty element.
3068 /// @return true upon successful completion.
3070 write_union_decl_opening_tag(const union_decl_sptr& decl,
3072 write_context& ctxt,
3074 bool prepare_to_handle_members)
3079 ostream& o = ctxt.get_ostream();
3081 do_indent_to_level(ctxt, indent, 0);
3083 o << "<union-decl name='" << xml::escape_xml_string(decl->get_name()) << "'";
3085 if (!decl->get_is_declaration_only())
3086 write_size_and_alignment(decl, o);
3088 write_is_anonymous(decl, o);
3090 write_visibility(decl, o);
3092 write_location(decl, ctxt);
3094 write_class_or_union_is_declaration_only(decl, o);
3098 i = ctxt.get_id_for_type(decl);
3099 o << " id='" << i << "'";
3101 if (!prepare_to_handle_members)
3105 if (decl->has_no_member())
3114 /// Serialize a class_decl type.
3116 /// @param decl the pointer to class_decl to serialize.
3118 /// @param id the type id identitifier to use in the serialized
3119 /// output. If this is empty, the function will compute an
3120 /// appropriate one. This is useful when this function is called to
3121 /// serialize the underlying type of a member type; in that case, the
3122 /// caller has already computed the id of the *member type*, and that
3123 /// id is the one to be written as the value of the 'id' attribute of
3124 /// the XML element of the underlying type.
3126 /// @param ctxt the context of the serialization.
3128 /// @param indent the initial indentation to use.
3130 write_class_decl(const class_decl_sptr& decl,
3132 write_context& ctxt,
3138 annotate(decl, ctxt, indent);
3140 ostream& o = ctxt.get_ostream();
3142 write_class_decl_opening_tag(decl, id, ctxt, indent,
3143 /*prepare_to_handle_members=*/true);
3145 if (!decl->has_no_base_nor_member())
3147 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1);
3148 type_base_sptr base_type;
3149 for (class_decl::base_specs::const_iterator base =
3150 decl->get_base_specifiers().begin();
3151 base != decl->get_base_specifiers().end();
3154 annotate((*base)->get_base_class(), ctxt, indent);
3155 do_indent(o, nb_ws);
3158 write_access((*base)->get_access_specifier(), o);
3160 write_layout_offset (*base, o);
3162 if ((*base)->get_is_virtual ())
3163 o << " is-virtual='yes'";
3165 base_type = (*base)->get_base_class();
3167 << ctxt.get_id_for_type(base_type)
3170 ctxt.record_type_as_referenced(base_type);
3173 for (class_decl::member_types::const_iterator ti =
3174 decl->get_member_types().begin();
3175 ti != decl->get_member_types().end();
3177 write_member_type(*ti, ctxt, nb_ws);
3179 for (class_decl::data_members::const_iterator data =
3180 decl->get_data_members().begin();
3181 data != decl->get_data_members().end();
3184 do_indent(o, nb_ws);
3185 o << "<data-member";
3186 write_access(get_member_access_specifier(*data), o);
3188 bool is_static = get_member_is_static(*data);
3189 write_cdtor_const_static(/*is_ctor=*/false,
3192 /*is_static=*/is_static,
3194 write_layout_offset(*data, o);
3197 write_var_decl(*data, ctxt, is_static,
3198 get_indent_to_level(ctxt, indent, 2));
3201 do_indent_to_level(ctxt, indent, 1);
3202 o << "</data-member>\n";
3205 for (class_decl::member_functions::const_iterator f =
3206 decl->get_member_functions().begin();
3207 f != decl->get_member_functions().end();
3210 function_decl_sptr fn = *f;
3211 if (get_member_function_is_virtual(fn))
3212 // All virtual member functions are emitted together,
3216 ABG_ASSERT(!get_member_function_is_virtual(fn));
3218 do_indent(o, nb_ws);
3219 o << "<member-function";
3220 write_access(get_member_access_specifier(fn), o);
3221 write_cdtor_const_static( get_member_function_is_ctor(fn),
3222 get_member_function_is_dtor(fn),
3223 get_member_function_is_const(fn),
3224 get_member_is_static(fn),
3228 write_function_decl(fn, ctxt,
3229 /*skip_first_parameter=*/false,
3230 get_indent_to_level(ctxt, indent, 2));
3233 do_indent_to_level(ctxt, indent, 1);
3234 o << "</member-function>\n";
3237 for (class_decl::member_functions::const_iterator f =
3238 decl->get_virtual_mem_fns().begin();
3239 f != decl->get_virtual_mem_fns().end();
3242 function_decl_sptr fn = *f;
3244 ABG_ASSERT(get_member_function_is_virtual(fn));
3246 do_indent(o, nb_ws);
3247 o << "<member-function";
3248 write_access(get_member_access_specifier(fn), o);
3249 write_cdtor_const_static( get_member_function_is_ctor(fn),
3250 get_member_function_is_dtor(fn),
3251 get_member_function_is_const(fn),
3252 get_member_is_static(fn),
3254 write_voffset(fn, o);
3257 write_function_decl(fn, ctxt,
3258 /*skip_first_parameter=*/false,
3259 get_indent_to_level(ctxt, indent, 2));
3262 do_indent_to_level(ctxt, indent, 1);
3263 o << "</member-function>\n";
3266 for (member_function_templates::const_iterator fn =
3267 decl->get_member_function_templates().begin();
3268 fn != decl->get_member_function_templates().end();
3271 do_indent(o, nb_ws);
3272 o << "<member-template";
3273 write_access((*fn)->get_access_specifier(), o);
3274 write_cdtor_const_static((*fn)->is_constructor(),
3277 (*fn)->get_is_static(), o);
3279 write_function_tdecl((*fn)->as_function_tdecl(), ctxt,
3280 get_indent_to_level(ctxt, indent, 2));
3282 do_indent(o, nb_ws);
3283 o << "</member-template>\n";
3286 for (member_class_templates::const_iterator cl =
3287 decl->get_member_class_templates().begin();
3288 cl != decl->get_member_class_templates().end();
3291 do_indent(o, nb_ws);
3292 o << "<member-template";
3293 write_access((*cl)->get_access_specifier(), o);
3294 write_cdtor_const_static(false, false, false,
3295 (*cl)->get_is_static(), o);
3297 write_class_tdecl((*cl)->as_class_tdecl(), ctxt,
3298 get_indent_to_level(ctxt, indent, 2));
3300 do_indent(o, nb_ws);
3301 o << "</member-template>\n";
3304 do_indent_to_level(ctxt, indent, 0);
3306 o << "</class-decl>";
3309 // We allow several *declarations* of the same class in the corpus,
3310 // but only one definition.
3311 if (!decl->get_is_declaration_only())
3312 ctxt.record_type_as_emitted(decl);
3314 ctxt.record_decl_only_type_as_emitted(decl);
3319 /// Serialize a class_decl type.
3321 /// @param decl the pointer to class_decl to serialize.
3323 /// @param ctxt the context of the serialization.
3325 /// @param indent the initial indentation to use.
3327 /// @return true upon successful completion.
3329 write_class_decl(const class_decl_sptr& decl,
3330 write_context& ctxt,
3332 {return write_class_decl(decl, "", ctxt, indent);}
3334 /// Serialize a @ref union_decl type.
3336 /// @param decl the pointer to @ref union_decl to serialize.
3338 /// @param ctxt the context of the serialization.
3340 /// @param indent the initial indentation to use.
3342 /// @return true upon successful completion.
3344 write_union_decl(const union_decl_sptr& decl,
3346 write_context& ctxt,
3352 annotate(decl, ctxt, indent);
3354 ostream& o = ctxt.get_ostream();
3356 write_union_decl_opening_tag(decl, id, ctxt, indent,
3357 /*prepare_to_handle_members=*/true);
3358 if (!decl->has_no_member())
3360 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1);
3361 for (class_decl::member_types::const_iterator ti =
3362 decl->get_member_types().begin();
3363 ti != decl->get_member_types().end();
3365 write_member_type(*ti, ctxt, nb_ws);
3367 for (union_decl::data_members::const_iterator data =
3368 decl->get_data_members().begin();
3369 data != decl->get_data_members().end();
3372 do_indent(o, nb_ws);
3373 o << "<data-member";
3374 write_access(get_member_access_specifier(*data), o);
3376 bool is_static = get_member_is_static(*data);
3377 write_cdtor_const_static(/*is_ctor=*/false,
3380 /*is_static=*/is_static,
3384 write_var_decl(*data, ctxt, is_static,
3385 get_indent_to_level(ctxt, indent, 2));
3388 do_indent_to_level(ctxt, indent, 1);
3389 o << "</data-member>\n";
3392 for (union_decl::member_functions::const_iterator f =
3393 decl->get_member_functions().begin();
3394 f != decl->get_member_functions().end();
3397 function_decl_sptr fn = *f;
3398 if (get_member_function_is_virtual(fn))
3399 // All virtual member functions are emitted together,
3403 ABG_ASSERT(!get_member_function_is_virtual(fn));
3405 do_indent(o, nb_ws);
3406 o << "<member-function";
3407 write_access(get_member_access_specifier(fn), o);
3408 write_cdtor_const_static( get_member_function_is_ctor(fn),
3409 get_member_function_is_dtor(fn),
3410 get_member_function_is_const(fn),
3411 get_member_is_static(fn),
3415 write_function_decl(fn, ctxt,
3416 /*skip_first_parameter=*/false,
3417 get_indent_to_level(ctxt, indent, 2));
3420 do_indent_to_level(ctxt, indent, 1);
3421 o << "</member-function>\n";
3424 for (member_function_templates::const_iterator fn =
3425 decl->get_member_function_templates().begin();
3426 fn != decl->get_member_function_templates().end();
3429 do_indent(o, nb_ws);
3430 o << "<member-template";
3431 write_access((*fn)->get_access_specifier(), o);
3432 write_cdtor_const_static((*fn)->is_constructor(),
3435 (*fn)->get_is_static(), o);
3437 write_function_tdecl((*fn)->as_function_tdecl(), ctxt,
3438 get_indent_to_level(ctxt, indent, 2));
3440 do_indent(o, nb_ws);
3441 o << "</member-template>\n";
3444 for (member_class_templates::const_iterator cl =
3445 decl->get_member_class_templates().begin();
3446 cl != decl->get_member_class_templates().end();
3449 do_indent(o, nb_ws);
3450 o << "<member-template";
3451 write_access((*cl)->get_access_specifier(), o);
3452 write_cdtor_const_static(false, false, false,
3453 (*cl)->get_is_static(), o);
3455 write_class_tdecl((*cl)->as_class_tdecl(), ctxt,
3456 get_indent_to_level(ctxt, indent, 2));
3458 do_indent(o, nb_ws);
3459 o << "</member-template>\n";
3462 do_indent_to_level(ctxt, indent, 0);
3464 o << "</union-decl>";
3467 // We allow several *declarations* of the same union in the corpus,
3468 // but only one definition.
3469 if (!decl->get_is_declaration_only())
3470 ctxt.record_type_as_emitted(decl);
3472 ctxt.record_decl_only_type_as_emitted(decl);
3478 write_union_decl(const union_decl_sptr& decl,
3479 write_context& ctxt,
3481 {return write_union_decl(decl, "", ctxt, indent);}
3483 /// Write the opening tag for a 'member-type' element.
3485 /// @param t the member type to consider.
3487 /// @param ctxt the write context to use.
3489 /// @param indent the number of white spaces to use for indentation.
3491 /// @return true upon successful completion.
3493 write_member_type_opening_tag(const type_base_sptr& t,
3494 write_context& ctxt,
3497 ostream& o = ctxt.get_ostream();
3499 do_indent_to_level(ctxt, indent, 0);
3501 decl_base_sptr decl = get_type_declaration(t);
3504 o << "<member-type";
3505 write_access(decl, o);
3511 /// Serialize a member type.
3513 /// Note that the id written as the value of the 'id' attribute of the
3514 /// underlying type is actually the id of the member type, not the one
3515 /// for the underying type. That id takes in account, the access
3516 /// specifier and the qualified name of the member type.
3518 /// @param decl the declaration of the member type to serialize.
3520 /// @param ctxt the write context to use.
3522 /// @param indent the number of levels to use for indentation
3524 write_member_type(const type_base_sptr& t, write_context& ctxt, unsigned indent)
3529 ostream& o = ctxt.get_ostream();
3531 write_member_type_opening_tag(t, ctxt, indent);
3534 string id = ctxt.get_id_for_type(t);
3536 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1);
3537 ABG_ASSERT(write_qualified_type_def(dynamic_pointer_cast<qualified_type_def>(t),
3539 || write_pointer_type_def(dynamic_pointer_cast<pointer_type_def>(t),
3541 || write_reference_type_def(dynamic_pointer_cast<reference_type_def>(t),
3543 || write_array_type_def(dynamic_pointer_cast<array_type_def>(t),
3545 || write_enum_type_decl(dynamic_pointer_cast<enum_type_decl>(t),
3547 || write_typedef_decl(dynamic_pointer_cast<typedef_decl>(t),
3549 || write_union_decl(dynamic_pointer_cast<union_decl>(t),
3551 || write_class_decl(dynamic_pointer_cast<class_decl>(t),
3555 do_indent_to_level(ctxt, indent, 0);
3556 o << "</member-type>\n";
3561 /// Serialize an instance of type_tparameter.
3563 /// @param decl the instance to serialize.
3565 /// @param ctxt the context of the serialization.
3567 /// @param indent the initial indentation to use.
3569 /// @return true upon successful completion, false otherwise.
3571 write_type_tparameter(const type_tparameter_sptr decl,
3572 write_context& ctxt,
3578 ostream &o = ctxt.get_ostream();
3579 do_indent_to_level(ctxt, indent, 0);
3581 string id_attr_name;
3582 if (ctxt.type_has_existing_id(decl))
3583 id_attr_name = "type-id";
3585 id_attr_name = "id";
3587 o << "<template-type-parameter "
3588 << id_attr_name << "='" << ctxt.get_id_for_type(decl) << "'";
3590 std::string name = xml::escape_xml_string(decl->get_name ());
3592 o << " name='" << name << "'";
3594 write_location(decl, ctxt);
3598 ctxt.record_type_as_emitted(decl);
3603 /// Serialize an instance of non_type_tparameter.
3605 /// @param decl the instance to serialize.
3607 /// @param ctxt the context of the serialization.
3609 /// @param indent the intial indentation to use.
3611 /// @return true open successful completion, false otherwise.
3613 write_non_type_tparameter(
3614 const shared_ptr<non_type_tparameter> decl,
3615 write_context& ctxt, unsigned indent)
3620 ostream &o = ctxt.get_ostream();
3621 do_indent_to_level(ctxt, indent, 0);
3623 o << "<template-non-type-parameter type-id='"
3624 << ctxt.get_id_for_type(decl->get_type())
3627 string name = xml::escape_xml_string(decl->get_name());
3629 o << " name='" << name << "'";
3631 write_location(decl, ctxt);
3638 /// Serialize an instance of template template parameter.
3640 /// @param decl the instance to serialize.
3642 /// @param ctxt the context of the serialization.
3644 /// @param indent the initial indentation to use.
3646 /// @return true upon successful completion, false otherwise.
3649 write_template_tparameter (const template_tparameter_sptr decl,
3650 write_context& ctxt,
3656 ostream& o = ctxt.get_ostream();
3657 do_indent_to_level(ctxt, indent, 0);
3659 string id_attr_name = "id";
3660 if (ctxt.type_has_existing_id(decl))
3661 id_attr_name = "type-id";
3663 o << "<template-template-parameter " << id_attr_name << "='"
3664 << ctxt.get_id_for_type(decl) << "'";
3666 string name = xml::escape_xml_string(decl->get_name());
3668 o << " name='" << name << "'";
3672 unsigned nb_spaces = get_indent_to_level(ctxt, indent, 1);
3673 for (list<shared_ptr<template_parameter> >::const_iterator p =
3674 decl->get_template_parameters().begin();
3675 p != decl->get_template_parameters().end();
3678 write_template_parameter(decl, ctxt, nb_spaces);
3682 do_indent_to_level(ctxt, indent, 0);
3683 o << "</template-template-parameter>";
3685 ctxt.record_type_as_emitted(decl);
3690 /// Serialize an instance of type_composition.
3692 /// @param decl the decl to serialize.
3694 /// @param ctxt the context of the serialization.
3696 /// @param indent the initial indentation to use.
3698 /// @return true upon successful completion, false otherwise.
3700 write_type_composition
3701 (const shared_ptr<type_composition> decl,
3702 write_context& ctxt, unsigned indent)
3707 ostream& o = ctxt.get_ostream();
3709 do_indent_to_level(ctxt, indent, 0);
3711 o << "<template-parameter-type-composition>\n";
3713 unsigned nb_spaces = get_indent_to_level(ctxt, indent, 1);
3714 (write_pointer_type_def
3715 (dynamic_pointer_cast<pointer_type_def>(decl->get_composed_type()),
3717 || write_reference_type_def
3718 (dynamic_pointer_cast<reference_type_def>(decl->get_composed_type()),
3720 || write_array_type_def
3721 (dynamic_pointer_cast<array_type_def>(decl->get_composed_type()),
3723 || write_qualified_type_def
3724 (dynamic_pointer_cast<qualified_type_def>(decl->get_composed_type()),
3729 do_indent_to_level(ctxt, indent, 0);
3730 o << "</template-parameter-type-composition>";
3735 /// Serialize an instance of template_parameter.
3737 /// @param decl the instance to serialize.
3739 /// @param ctxt the context of the serialization.
3741 /// @param indent the initial indentation to use.
3743 /// @return true upon successful completion, false otherwise.
3745 write_template_parameter(const shared_ptr<template_parameter> decl,
3746 write_context& ctxt, unsigned indent)
3748 if ((!write_type_tparameter
3749 (dynamic_pointer_cast<type_tparameter>(decl), ctxt, indent))
3750 && (!write_non_type_tparameter
3751 (dynamic_pointer_cast<non_type_tparameter>(decl),
3753 && (!write_template_tparameter
3754 (dynamic_pointer_cast<template_tparameter>(decl),
3756 && (!write_type_composition
3757 (dynamic_pointer_cast<type_composition>(decl),
3764 /// Serialize the template parameters of the a given template.
3766 /// @param tmpl the template for which to emit the template parameters.
3768 write_template_parameters(const shared_ptr<template_decl> tmpl,
3769 write_context& ctxt, unsigned indent)
3774 ostream &o = ctxt.get_ostream();
3776 unsigned nb_spaces = get_indent_to_level(ctxt, indent, 1);
3777 for (list<shared_ptr<template_parameter> >::const_iterator p =
3778 tmpl->get_template_parameters().begin();
3779 p != tmpl->get_template_parameters().end();
3782 write_template_parameter(*p, ctxt, nb_spaces);
3787 /// Serialize an instance of function_tdecl.
3789 /// @param decl the instance to serialize.
3791 /// @param ctxt the context of the serialization
3793 /// @param indent the initial indentation.
3795 write_function_tdecl(const shared_ptr<function_tdecl> decl,
3796 write_context& ctxt, unsigned indent)
3801 ostream& o = ctxt.get_ostream();
3803 do_indent_to_level(ctxt, indent, 0);
3805 o << "<function-template-decl id='" << ctxt.get_id_for_fn_tmpl(decl) << "'";
3807 write_location(decl, ctxt);
3809 write_visibility(decl, o);
3811 write_binding(decl, o);
3815 write_template_parameters(decl, ctxt, indent);
3817 write_function_decl(decl->get_pattern(), ctxt,
3818 /*skip_first_parameter=*/false,
3819 get_indent_to_level(ctxt, indent, 1));
3822 do_indent_to_level(ctxt, indent, 0);
3824 o << "</function-template-decl>";
3830 /// Serialize an instance of class_tdecl
3832 /// @param decl a pointer to the instance of class_tdecl to serialize.
3834 /// @param ctxt the context of the serializtion.
3836 /// @param indent the initial number of white space to use for
3839 /// @return true upon successful completion, false otherwise.
3841 write_class_tdecl(const shared_ptr<class_tdecl> decl,
3842 write_context& ctxt, unsigned indent)
3847 ostream& o = ctxt.get_ostream();
3849 do_indent_to_level(ctxt, indent, 0);
3851 o << "<class-template-decl id='" << ctxt.get_id_for_class_tmpl(decl) << "'";
3853 write_location(decl, ctxt);
3855 write_visibility(decl, o);
3859 write_template_parameters(decl, ctxt, indent);
3861 write_class_decl(decl->get_pattern(), ctxt,
3862 get_indent_to_level(ctxt, indent, 1));
3865 do_indent_to_level(ctxt, indent, 0);
3867 o << "</class-template-decl>";
3872 #ifdef WITH_ZIP_ARCHIVE
3874 /// A context used by functions that write a corpus out to disk in a
3875 /// ZIP archive of ABI Instrumentation XML files.
3877 /// The aim of this context file is to hold the buffers of data that
3878 /// are to be written into a given zip object, until the zip object is
3879 /// closed. It's at that point that the buffers data is really
3880 /// flushed into the zip archive.
3882 /// When an instance of this context type is created for a given zip
3883 /// object, is created, its life time should be longer than the @ref
3884 /// zip_sptr object it holds.
3886 /// The definition of this type is private and should remain hidden
3887 /// from client code.
3888 struct archive_write_ctxt
3890 list<string> serialized_tus;
3893 archive_write_ctxt(zip_sptr ar)
3897 typedef shared_ptr<archive_write_ctxt> archive_write_ctxt_sptr;
3899 /// Create a write context to a given archive. The result of this
3900 /// function is to be passed to the functions that are to write a
3901 /// corpus to an archive, e.g, write_corpus_to_archive().
3903 /// @param archive_path the path to the archive to create this write
3906 /// @return the resulting write context to pass to the functions that
3907 /// are to write a corpus to @ref archive_path.
3908 static archive_write_ctxt_sptr
3909 create_archive_write_context(const string& archive_path)
3911 if (archive_path.empty())
3912 return archive_write_ctxt_sptr();
3915 zip_sptr archive = open_archive(archive_path,
3916 ZIP_CREATE|ZIP_TRUNCATE|ZIP_CHECKCONS,
3919 return archive_write_ctxt_sptr();
3921 archive_write_ctxt_sptr r(new archive_write_ctxt(archive));
3925 /// Write a translation unit to an on-disk archive. The archive is a
3926 /// zip archive of ABI Instrumentation files in XML format.
3928 /// @param tu the translation unit to serialize.
3930 /// @param ctxt the context of the serialization. Contains
3931 /// information about where the archive is on disk, the zip archive,
3932 /// and the buffers holding the temporary data to be flushed into the archive.
3934 /// @param annotate whether ABIXML output should be annotated.
3936 /// @return true upon succesful serialization occured, false
3939 write_translation_unit_to_archive(const translation_unit& tu,
3940 archive_write_ctxt& ctxt,
3941 const bool annotate)
3947 if (!write_translation_unit(tu, /*indent=*/0, os, annotate))
3949 ctxt.serialized_tus.push_back(os.str());
3952 if ((source = zip_source_buffer(ctxt.archive.get(),
3953 ctxt.serialized_tus.back().c_str(),
3954 ctxt.serialized_tus.back().size(),
3958 if (zip_file_add(ctxt.archive.get(), tu.get_path().c_str(), source,
3959 ZIP_FL_OVERWRITE|ZIP_FL_ENC_GUESS) < 0)
3961 zip_source_free(source);
3968 /// Serialize a given corpus to disk in a file at a given path.
3970 /// @param tu the translation unit to serialize.
3972 /// @param ctxt the context of the serialization. Contains
3973 /// information about where the archive is on disk, the zip archive
3974 /// object, and the buffers holding the temporary data to be flushed
3975 /// into the archive.
3977 /// @param annotate whether ABIXML output should be annotated.
3979 /// @return true upon successful completion, false otherwise.
3981 write_corpus_to_archive(const corpus& corp,
3982 archive_write_ctxt& ctxt,
3983 const bool annotate)
3985 for (translation_units::const_iterator i =
3986 corp.get_translation_units().begin();
3987 i != corp.get_translation_units().end();
3990 if (! write_translation_unit_to_archive(**i, ctxt, annotate))
3994 // TODO: ensure abi-info descriptor is added to the archive.
3998 /// Serialize a given corpus to disk in an archive file at a given
4001 /// @param corp the ABI corpus to serialize.
4003 /// @param ctxt the context of the serialization. Contains
4004 /// information about where the archive is on disk, the zip archive
4005 /// object, and the buffers holding the temporary data to be flushed
4006 /// into the archive.
4008 /// @param annotate whether ABIXML output should be annotated.
4010 /// @return upon successful completion, false otherwise.
4012 write_corpus_to_archive(const corpus& corp,
4013 archive_write_ctxt_sptr ctxt,
4014 const bool annotate)
4015 {return write_corpus_to_archive(corp, *ctxt, annotate);}
4017 /// Serialize the current corpus to disk in a file at a given path.
4019 /// @param tu the translation unit to serialize.
4021 /// @param path the path of the file to serialize the
4022 /// translation_unit to.
4024 /// @param annotate whether ABIXML output should be annotated.
4026 /// @return true upon successful completion, false otherwise.
4028 write_corpus_to_archive(const corpus& corp,
4030 const bool annotate)
4032 archive_write_ctxt_sptr ctxt = create_archive_write_context(path);
4034 return write_corpus_to_archive(corp, ctxt, annotate);
4037 /// Serialize the current corpus to disk in a file. The file path is
4038 /// given by translation_unit::get_path().
4040 /// @param tu the translation unit to serialize.
4042 /// @param annotate whether ABIXML output should be annotated.
4044 /// @return true upon successful completion, false otherwise.
4046 write_corpus_to_archive(const corpus& corp, const bool annotate)
4047 {return write_corpus_to_archive(corp, corp.get_path(), annotate);}
4049 /// Serialize the current corpus to disk in a file. The file path is
4050 /// given by translation_unit::get_path().
4052 /// @param tu the translation unit to serialize.
4054 /// @param annotate whether ABIXML output should be annotated.
4056 /// @return true upon successful completion, false otherwise.
4058 write_corpus_to_archive(const corpus_sptr corp, const bool annotate)
4059 {return write_corpus_to_archive(*corp, annotate);}
4061 #endif //WITH_ZIP_ARCHIVE
4063 /// Serialize an ABI corpus to a single native xml document. The root
4064 /// note of the resulting XML document is 'abi-corpus'.
4066 /// @param ctxt the write context to use.
4068 /// @param corpus the corpus to serialize.
4070 /// @param indent the number of white space indentation to use.
4072 /// @return true upon successful completion, false otherwise.
4074 write_corpus(write_context& ctxt, const corpus_sptr& corpus, unsigned indent)
4079 do_indent_to_level(ctxt, indent, 0);
4081 std::ostream& out = ctxt.get_ostream();
4083 out << "<abi-corpus";
4084 if (!corpus->get_path().empty())
4085 out << " path='" << xml::escape_xml_string(corpus->get_path()) << "'";
4087 if (!corpus->get_architecture_name().empty())
4088 out << " architecture='" << corpus->get_architecture_name()<< "'";
4090 if (!corpus->get_soname().empty())
4091 out << " soname='" << corpus->get_soname()<< "'";
4093 if (corpus->is_empty())
4101 // Write the list of needed corpora.
4103 if (!corpus->get_needed().empty())
4105 do_indent_to_level(ctxt, indent, 1);
4106 out << "<elf-needed>\n";
4107 write_elf_needed(corpus->get_needed(), ctxt,
4108 get_indent_to_level(ctxt, indent, 2));
4110 do_indent_to_level(ctxt, indent, 1);
4111 out << "</elf-needed>\n";
4114 // Write the function symbols data base.
4115 if (!corpus->get_fun_symbol_map().empty())
4117 do_indent_to_level(ctxt, indent, 1);
4118 out << "<elf-function-symbols>\n";
4120 write_elf_symbols_table(corpus->get_sorted_fun_symbols(), ctxt,
4121 get_indent_to_level(ctxt, indent, 2));
4123 do_indent_to_level(ctxt, indent, 1);
4124 out << "</elf-function-symbols>\n";
4127 // Write the variable symbols data base.
4128 if (!corpus->get_var_symbol_map().empty())
4130 do_indent_to_level(ctxt, indent, 1);
4131 out << "<elf-variable-symbols>\n";
4133 write_elf_symbols_table(corpus->get_sorted_var_symbols(), ctxt,
4134 get_indent_to_level(ctxt, indent, 2));
4136 do_indent_to_level(ctxt, indent, 1);
4137 out << "</elf-variable-symbols>\n";
4140 // Now write the translation units.
4141 for (translation_units::const_iterator i =
4142 corpus->get_translation_units().begin();
4143 i != corpus->get_translation_units().end();
4146 translation_unit& tu = **i;
4148 write_translation_unit(ctxt, tu, get_indent_to_level(ctxt, indent, 1));
4151 do_indent_to_level(ctxt, indent, 0);
4152 out << "</abi-corpus>\n";
4157 /// Serialize an ABI corpus to a single native xml document. The root
4158 /// node of the resulting XML document is 'abi-corpus'.
4160 /// @param corpus the corpus to serialize.
4162 /// @param indent the number of white space indentation to use.
4164 /// @param ctxt the write context to use.
4166 /// @deprecated: use write_corpus(ctxt, corpus, indent)
4168 /// @return true upon successful completion, false otherwise.
4170 write_corpus(const corpus_sptr& corpus, unsigned indent, write_context& ctxt)
4172 return write_corpus(ctxt, corpus, indent);
4175 /// Serialize an ABI corpus to a single native xml document. The root
4176 /// node of the resulting XML document is 'abi-corpus'.
4178 /// @param corpus the corpus to serialize.
4180 /// @param indent the number of white space indentation to use.
4182 /// @param out the output stream to serialize the ABI corpus to.
4184 /// @param annotate whether ABIXML output should be annotated.
4186 /// @deprecated: use write_corpus(ctxt, corpus, indent)
4188 /// @return true upon successful completion, false otherwise.
4190 write_corpus(const corpus_sptr corpus,
4193 const bool annotate)
4198 write_context ctxt(corpus->get_environment(), out);
4199 set_annotate(ctxt, annotate);
4201 return write_corpus(ctxt, corpus, indent);
4204 /// Serialize an ABI corpus group to a single native xml document.
4205 /// The root note of the resulting XML document is 'abi-corpus-group'.
4207 /// @param ctxt the write context to use.
4209 /// @param group the corpus group to serialize.
4211 /// @param indent the number of white space indentation to use.
4213 /// @return true upon successful completion, false otherwise.
4215 write_corpus_group(write_context& ctxt,
4216 const corpus_group_sptr& group,
4223 do_indent_to_level(ctxt, indent, 0);
4225 std::ostream& out = ctxt.get_ostream();
4227 out << "<abi-corpus-group";
4229 if (!group->get_path().empty())
4230 out << " path='" << xml::escape_xml_string(group->get_path()) << "'";
4232 if (!group->get_architecture_name().empty())
4233 out << " architecture='" << group->get_architecture_name()<< "'";
4235 if (group->is_empty())
4243 // Write the list of corpora
4244 for (corpus_group::corpora_type::const_iterator c =
4245 group->get_corpora().begin();
4246 c != group->get_corpora().end();
4248 write_corpus(ctxt, *c, get_indent_to_level(ctxt, indent, 1));
4250 do_indent_to_level(ctxt, indent, 0);
4251 out << "</abi-corpus-group>\n";
4256 /// Serialize an ABI corpus group to a single native xml document.
4257 /// The root note of the resulting XML document is 'abi-corpus-group'.
4259 /// @param group the corpus group to serialize.
4261 /// @param indent the number of white space indentation to use.
4263 /// @param ctxt the write context to use.
4265 /// @deprecated use write_corpus_group(ctxt, corpus_group, indent)
4267 /// @return true upon successful completion, false otherwise.
4269 write_corpus_group(const corpus_group_sptr& group,
4271 write_context& ctxt)
4274 return write_corpus_group(ctxt, group, indent);
4277 /// Serialize an ABI corpus group to a single native xml document.
4278 /// The root note of the resulting XML document is 'abi-corpus-group'.
4280 /// @param group the corpus group to serialize.
4282 /// @param indent the number of white space indentation to use.
4284 /// @param out the output stream to serialize the ABI corpus to.
4286 /// @param annotate whether ABIXML output should be annotated.
4288 /// @deprecated use write_corpus_group(ctxt, corpus_group, indent)
4290 /// @return true upon successful completion, false otherwise.
4292 write_corpus_group(const corpus_group_sptr& group,
4295 const bool annotate)
4301 write_context ctxt(group->get_environment(), out);
4302 set_annotate(ctxt, annotate);
4304 return write_corpus_group(ctxt, group, indent);
4307 /// Serialize an ABI corpus to a single native xml document. The root
4308 /// note of the resulting XML document is 'abi-corpus'.
4310 /// @param corpus the corpus to serialize.
4312 /// @param indent the number of white space indentation to use.
4314 /// @param path the output file to serialize the ABI corpus to.
4316 /// @param annotate whether ABIXML output should be annotated.
4318 /// @deprecated: use write_corpus(ctxt, corpus, indent)
4320 /// @return true upon successful completion, false otherwise.
4322 write_corpus(const corpus_sptr corpus,
4325 const bool annotate)
4331 ofstream of(path.c_str(), std::ios_base::trunc);
4334 cerr << "failed to access " << path << "\n";
4338 const write_context_sptr& ctxt
4339 = create_write_context(corpus->get_environment(), of);
4340 ctxt->set_annotate(annotate);
4341 if (!write_corpus(*ctxt, corpus, indent))
4343 cerr << "failed to access " << path << "\n";
4351 cerr << "failed to write to " << path << "\n";
4358 } //end namespace xml_writer
4360 // <Debugging routines>
4362 using namespace abigail::ir;
4364 /// Serialize a pointer to decl_base to an output stream.
4366 /// @param d the pointer to decl_base to serialize.
4368 /// @param o the output stream to consider.
4370 /// @param annotate whether ABIXML output should be annotated.
4372 dump(const decl_base_sptr d, std::ostream& o, const bool annotate)
4374 xml_writer::write_context ctxt(d->get_environment(), o);
4375 xml_writer::set_annotate(ctxt, annotate);
4376 write_decl(d, ctxt, /*indent=*/0);
4380 /// Serialize a pointer to decl_base to stderr.
4382 /// @param d the pointer to decl_base to serialize.
4384 /// @param annotate whether ABIXML output should be annotated.
4386 dump(const decl_base_sptr d, const bool annotate)
4387 {dump(d, cerr, annotate);}
4389 /// Serialize a pointer to type_base to an output stream.
4391 /// @param t the pointer to type_base to serialize.
4393 /// @param o the output stream to serialize the @ref type_base to.
4395 /// @param annotate whether ABIXML output should be annotated.
4397 dump(const type_base_sptr t, std::ostream& o, const bool annotate)
4398 {dump(get_type_declaration(t), o, annotate);}
4400 /// Serialize a pointer to type_base to stderr.
4402 /// @param t the pointer to type_base to serialize.
4404 /// @param annotate whether ABIXML output should be annotated.
4406 dump(const type_base_sptr t, const bool annotate)
4407 {dump(t, cerr, annotate);}
4409 /// Serialize a pointer to var_decl to an output stream.
4411 /// @param v the pointer to var_decl to serialize.
4413 /// @param o the output stream to serialize the @ref var_decl to.
4415 /// @param annotate whether ABIXML output should be annotated.
4417 dump(const var_decl_sptr v, std::ostream& o, const bool annotate)
4419 xml_writer::write_context ctxt(v->get_environment(), o);
4420 xml_writer::set_annotate(ctxt, annotate);
4421 write_var_decl(v, ctxt, /*linkage_name*/true, /*indent=*/0);
4425 /// Serialize a pointer to var_decl to stderr.
4427 /// @param v the pointer to var_decl to serialize.
4429 /// @param annotate whether ABIXML output should be annotated.
4431 dump(const var_decl_sptr v, const bool annotate)
4432 {dump(v, cerr, annotate);}
4434 /// Serialize a @ref translation_unit to an output stream.
4436 /// @param t the translation_unit to serialize.
4438 /// @param o the outpout stream to serialize the translation_unit to.
4440 /// @param annotate whether ABIXML output should be annotated.
4442 dump(const translation_unit& t, std::ostream& o, const bool annotate)
4444 xml_writer::write_context ctxt(t.get_environment(), o);
4445 xml_writer::set_annotate(ctxt, annotate);
4446 write_translation_unit(ctxt, t, /*indent=*/0);
4450 /// Serialize an instance of @ref translation_unit to stderr.
4452 /// @param t the translation_unit to serialize.
4454 dump(const translation_unit& t, const bool annotate)
4455 {dump(t, cerr, annotate);}
4457 /// Serialize a pointer to @ref translation_unit to an output stream.
4459 /// @param t the @ref translation_unit_sptr to serialize.
4461 /// @param o the output stream to serialize the translation unit to.
4463 /// @param annotate whether ABIXML output should be annotated.
4465 dump(const translation_unit_sptr t, std::ostream& o, const bool annotate)
4468 dump(*t, o, annotate);
4471 /// Serialize a pointer to @ref translation_unit to stderr.
4473 /// @param t the translation_unit_sptr to serialize.
4475 /// @param annotate whether ABIXML output should be annotated.
4477 dump(const translation_unit_sptr t, const bool annotate)
4483 /// Serialize a source location to an output stream.
4485 /// @param l the declaration to consider.
4487 /// @param o the output stream to serialize to.
4489 dump_location(const location& l, ostream& o)
4492 unsigned line = 0, col = 0;
4494 l.expand(path, line, col);
4495 o << path << ":" << line << "," << col << "\n";
4498 /// Serialize a source location for debugging purposes.
4500 /// The location is serialized to the standard error output stream.
4502 /// @param l the declaration to consider.
4505 dump_location(const location& l)
4506 {dump_location(l, cerr);}
4508 /// Serialize the source location of a decl to an output stream for
4509 /// debugging purposes.
4511 /// @param d the declaration to consider.
4513 /// @param o the output stream to serizalize the location to.
4515 dump_decl_location(const decl_base& d, ostream& o)
4516 {dump_location(d.get_location(), o);}
4518 /// Serialize the source location of a decl to stderr for debugging
4521 /// @param d the declaration to consider.
4523 dump_decl_location(const decl_base& d)
4524 {dump_decl_location(d, cerr);}
4526 /// Serialize the source location of a dcl to stderr for debugging
4529 /// @param d the declaration to consider.
4531 dump_decl_location(const decl_base* d)
4534 dump_decl_location(*d);
4537 /// Serialize the source location of a decl to stderr for debugging
4540 /// @param d the declaration to consider.
4542 dump_decl_location(const decl_base_sptr d)
4543 {dump_decl_location(d.get());}
4545 // </Debugging routines>
4546 } //end namespace abigail