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