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_ptr_to_mbr_type(const ptr_to_mbr_type_sptr&,
923 write_context&, unsigned);
924static bool write_array_type_def(const array_type_def_sptr&,
925 write_context&, unsigned);
926static bool write_array_subrange_type(const array_type_def::subrange_sptr&,
927 write_context&,
928 unsigned);
929static bool write_enum_type_decl(const enum_type_decl_sptr&,
930 write_context&, unsigned);
931static bool write_typedef_decl(const typedef_decl_sptr&,
932 write_context&, unsigned);
933static bool write_elf_symbol(const elf_symbol_sptr&,
934 write_context&, unsigned);
935static bool write_elf_symbols_table(const elf_symbols&,
936 write_context&, unsigned);
937static bool write_var_decl(const var_decl_sptr&,
938 write_context&, bool, unsigned);
939static bool write_function_decl(const function_decl_sptr&,
940 write_context&, bool, unsigned);
941static bool write_function_type(const function_type_sptr&,
942 write_context&, unsigned);
943static bool write_member_type_opening_tag(const type_base_sptr&,
944 write_context&, unsigned);
945static bool write_member_type(const type_base_sptr&,
946 write_context&, unsigned);
947static bool write_class_decl_opening_tag(const class_decl_sptr&, const string&,
948 write_context&, unsigned, bool);
949static bool write_class_decl(const class_decl_sptr&,
950 write_context&, unsigned);
951static bool write_union_decl_opening_tag(const union_decl_sptr&, const string&,
952 write_context&, unsigned, bool);
953static bool write_union_decl(const union_decl_sptr&, const string&,
954 write_context&, unsigned);
955static bool write_union_decl(const union_decl_sptr&, write_context&, unsigned);
956static bool write_type_tparameter
957(const shared_ptr<type_tparameter>, write_context&, unsigned);
958static bool write_non_type_tparameter
959(const shared_ptr<non_type_tparameter>, write_context&, unsigned);
960static bool write_template_tparameter
961(const shared_ptr<template_tparameter>, write_context&, unsigned);
962static bool write_type_composition
963(const shared_ptr<type_composition>, write_context&, unsigned);
964static bool write_template_parameter(const shared_ptr<template_parameter>,
965 write_context&, unsigned);
966static void write_template_parameters(const shared_ptr<template_decl>,
967 write_context&, unsigned);
968static bool write_function_tdecl
969(const shared_ptr<function_tdecl>,
970 write_context&, unsigned);
971static bool write_class_tdecl
972(const shared_ptr<class_tdecl>,
973 write_context&, unsigned);
974static void do_indent(ostream&, unsigned);
975static void do_indent_to_level(write_context&, unsigned, unsigned);
976static unsigned get_indent_to_level(write_context&, unsigned, unsigned);
977
978/// Emit nb_whitespaces white spaces into the output stream.
979void
980do_indent(ostream& o, unsigned nb_whitespaces)
981{
982 for (unsigned i = 0; i < nb_whitespaces; ++i)
983 o << ' ';
984}
985
986/// Indent initial_indent + level number of xml element indentation.
987///
988/// @param ctxt the context of the parsing.
989///
990/// @param initial_indent the initial number of white space to indent to.
991///
992/// @param level the number of indentation level to indent to.
993static void
994do_indent_to_level(write_context& ctxt,
995 unsigned initial_indent,
996 unsigned level)
997{
998 do_indent(ctxt.get_ostream(),
999 get_indent_to_level(ctxt, initial_indent, level));
1000}
1001
1002/// Return the number of white space of indentation that
1003/// #do_indent_to_level would have used.
1004///
1005/// @param ctxt the context of the parsing.
1006///
1007/// @param initial_indent the initial number of white space to indent to.
1008///
1009/// @param level the number of indentation level to indent to.
1010static unsigned
1011get_indent_to_level(write_context& ctxt, unsigned initial_indent,
1012 unsigned level)
1013{
1014 int nb_ws = initial_indent +
1015 level * ctxt.get_config().get_xml_element_indent();
1016 return nb_ws;
1017}
1018
1019/// Annotate a declaration in form of an ABIXML comment.
1020///
1021/// This function is further specialized for declarations and types
1022/// with special requirements.
1023///
1024/// @tparam T shall be of type decl_base_sptr or a shared pointer to a
1025/// type derived from it, for the instantiation to be syntactically
1026/// correct.
1027///
1028/// @param decl_sptr the shared pointer to the declaration of type T.
1029///
1030/// @param ctxt the context of the parsing.
1031///
1032/// @param indent the amount of white space to indent to.
1033///
1034/// @return true iff decl is valid.
1035template <typename T>
1036static bool
1037annotate(const T& decl,
1038 write_context& ctxt,
1039 unsigned indent)
1040{
1041 if (!decl)
1042 return false;
1043
1044 if (!ctxt.get_annotate())
1045 return true;
1046
1047 ostream& o = ctxt.get_ostream();
1048
1049 do_indent(o, indent);
1050
1051 o << "<!-- "
1052 << xml::escape_xml_comment(decl->get_pretty_representation(/*internal=*/false))
1053 << " -->\n";
1054
1055 return true;
1056}
1057
1058/// Annotate an elf symbol in form of an ABIXML comment, effectively
1059/// writing out its demangled form.
1060///
1061/// @param sym the symbol, whose name should be demangled.
1062///
1063/// @param ctxt the context of the parsing.
1064///
1065/// @param indent the amount of white space to indent to.
1066///
1067/// @return true iff decl is valid
1068template<>
1069bool
1070annotate(const elf_symbol_sptr& sym,
1071 write_context& ctxt,
1072 unsigned indent)
1073{
1074 if (!sym)
1075 return false;
1076
1077 if (!ctxt.get_annotate())
1078 return true;
1079
1080 ostream& o = ctxt.get_ostream();
1081
1082 do_indent(o, indent);
1083 o << "<!-- "
1085 << " -->\n";
1086
1087 return true;
1088}
1089
1090/// Annotate a typedef declaration in form of an ABIXML comment.
1091///
1092/// @param typedef_decl the typedef to annotate.
1093///
1094/// @param ctxt the context of the parsing.
1095///
1096/// @param indent the amount of white space to indent to.
1097///
1098/// @return true iff decl is valid
1099template<>
1100bool
1102 write_context& ctxt,
1103 unsigned indent)
1104{
1105 if (!typedef_decl)
1106 return false;
1107
1108 if (!ctxt.get_annotate())
1109 return true;
1110
1111 ostream& o = ctxt.get_ostream();
1112
1113 do_indent(o, indent);
1114
1115 o << "<!-- typedef "
1117 << " "
1119 << " -->\n";
1120
1121 return true;
1122}
1123
1124/// Annotate a function type in form of an ABIXML comment.
1125///
1126/// @param function_type the function type to annotate.
1127///
1128/// @param ctxt the context of the parsing.
1129///
1130/// @param indent the amount of white space to indent to.
1131///
1132/// @param skip_first_parm if true, do not serialize the first
1133/// parameter of the function decl.
1134//
1135/// @return true iff decl is valid
1136bool
1138 write_context& ctxt,
1139 unsigned indent)
1140{
1141 if (!function_type)
1142 return false;
1143
1144 if (!ctxt.get_annotate())
1145 return true;
1146
1147 ostream& o = ctxt.get_ostream();
1148
1149 do_indent(o, indent);
1150 o << "<!-- "
1152 << " (";
1153
1154 vector<shared_ptr<function_decl::parameter> >::const_iterator pi =
1156
1157 for (; pi != function_type->get_parameters().end(); ++pi)
1158 {
1159 o << xml::escape_xml_comment((*pi)->get_type_name());
1160 // emit a comma after a param type, unless it's the last one
1161 if (distance(pi, function_type->get_parameters().end()) > 1)
1162 o << ", ";
1163 }
1164 o << ") -->\n";
1165
1166 return true;
1167}
1168
1169/// Annotate a function declaration in form of an ABIXML comment.
1170///
1171/// @param fn the function decl to annotate.
1172///
1173/// @param ctxt the context of the parsing.
1174///
1175/// @param indent the amount of white space to indent to.
1176///
1177/// @param skip_first_parm if true, do not serialize the first
1178/// parameter of the function decl.
1179//
1180/// @return true iff decl is valid
1181static bool
1182annotate(const function_decl_sptr& fn,
1183 write_context& ctxt,
1184 unsigned indent)
1185{
1186 if (!fn)
1187 return false;
1188
1189 if (!ctxt.get_annotate())
1190 return true;
1191
1192 ostream& o = ctxt.get_ostream();
1193
1194 do_indent(o, indent);
1195 o << "<!-- ";
1196
1197 if (is_member_function(fn)
1199 ; // we don't emit return types for ctor or dtors
1200 else
1201 o << xml::escape_xml_comment(get_type_name(fn->get_return_type()))
1202 << " ";
1203
1204 o << xml::escape_xml_comment(fn->get_qualified_name()) << "(";
1205
1206 vector<function_decl::parameter_sptr>::const_iterator pi =
1207 fn->get_first_non_implicit_parm();
1208
1209 for (; pi != fn->get_parameters().end(); ++pi)
1210 {
1211 o << xml::escape_xml_comment((*pi)->get_type_name());
1212 // emit a comma after a param type, unless it's the last one
1213 if (distance(pi, fn->get_parameters().end()) > 1)
1214 o << ", ";
1215 }
1216 o << ") -->\n";
1217
1218 return true;
1219}
1220
1221/// Annotate a function parameter in form of an ABIXML comment.
1222///
1223/// @param parm the function parameter to annotate.
1224///
1225/// @param ctxt the context of the parsing.
1226///
1227/// @param indent the amount of white space to indent to.
1228///
1229/// @return true iff decl is valid
1230template<>
1231bool
1233 write_context& ctxt,
1234 unsigned indent)
1235{
1236 if (!parm)
1237 return false;
1238
1239 if (!ctxt.get_annotate())
1240 return true;
1241
1242 ostream &o = ctxt.get_ostream();
1243
1244 do_indent(o, indent);
1245
1246 o << "<!-- ";
1247
1248 if (parm->get_variadic_marker())
1249 o << "variadic parameter";
1250 else
1251 {
1252 if (parm->get_is_artificial())
1253 {
1254 if (parm->get_index() == 0)
1255 o << "implicit ";
1256 else
1257 o << "artificial ";
1258 }
1259 o << "parameter of type '"
1261 }
1262
1263 o << "' -->\n";
1264
1265 return true;
1266}
1267
1268/// Write a location to the output stream.
1269///
1270/// If the location is empty, nothing is written.
1271///
1272/// @param loc the location to consider.
1273///
1274/// @param tu the translation unit the location belongs to.
1275///
1276/// @param ctxt the writer context to use.
1277static void
1278write_location(const location& loc, write_context& ctxt)
1279{
1280 if (!loc || loc.get_is_artificial())
1281 return;
1282
1283 if (!ctxt.get_show_locs())
1284 return;
1285
1286 string filepath;
1287 unsigned line = 0, column = 0;
1288
1289 loc.expand(filepath, line, column);
1290
1291 ostream &o = ctxt.get_ostream();
1292
1293 if (ctxt.get_short_locs())
1294 tools_utils::base_name(filepath, filepath);
1295
1296 o << " filepath='" << xml::escape_xml_string(filepath) << "'"
1297 << " line='" << line << "'"
1298 << " column='" << column << "'";
1299}
1300
1301/// Write the location of a decl to the output stream.
1302///
1303/// If the location is empty, nothing is written.
1304///
1305/// @param decl the decl to consider.
1306///
1307/// @param ctxt the @ref writer_context to use.
1308static void
1309write_location(const decl_base_sptr& decl,
1310 write_context& ctxt)
1311{
1312 if (!decl)
1313 return;
1314
1315 location loc = decl->get_location();
1316 if (!loc)
1317 return;
1318
1319 write_location(loc, ctxt);
1320}
1321
1322/// Serialize the visibility property of the current decl as the
1323/// 'visibility' attribute for the current xml element.
1324///
1325/// @param decl the instance of decl_base to consider.
1326///
1327/// @param o the output stream to serialize the property to.
1328///
1329/// @return true upon successful completion, false otherwise.
1330static bool
1331write_visibility(const shared_ptr<decl_base>& decl, ostream& o)
1332{
1333 if (!decl)
1334 return false;
1335
1336 decl_base::visibility v = decl->get_visibility();
1337 string str;
1338
1339 switch (v)
1340 {
1341 case decl_base::VISIBILITY_NONE:
1342 return true;
1343 case decl_base::VISIBILITY_DEFAULT:
1344 str = "default";
1345 break;
1346 case decl_base::VISIBILITY_PROTECTED:
1347 str = "protected";
1348 break;
1349 case decl_base::VISIBILITY_HIDDEN:
1350 str = "hidden";
1351 break;
1352 case decl_base::VISIBILITY_INTERNAL:
1353 str = "internal";
1354 break;
1355 }
1356
1357 if (str.empty())
1358 return false;
1359
1360 o << " visibility='" << str << "'";
1361
1362 return true;
1363}
1364
1365/// Serialize the 'binding' property of the current decl.
1366///
1367/// @param decl the decl to consider.
1368///
1369/// @param o the output stream to serialize the property to.
1370static bool
1371write_binding(const shared_ptr<decl_base>& decl, ostream& o)
1372{
1373 if (!decl)
1374 return false;
1375
1376 decl_base::binding bind = decl_base::BINDING_NONE;
1377
1378 shared_ptr<var_decl> var =
1379 dynamic_pointer_cast<var_decl>(decl);
1380 if (var)
1381 bind = var->get_binding();
1382 else
1383 {
1384 shared_ptr<function_decl> fun =
1385 dynamic_pointer_cast<function_decl>(decl);
1386 if (fun)
1387 bind = fun->get_binding();
1388 }
1389
1390 string str;
1391 switch (bind)
1392 {
1393 case decl_base::BINDING_NONE:
1394 break;
1395 case decl_base::BINDING_LOCAL:
1396 str = "local";
1397 break;
1398 case decl_base::BINDING_GLOBAL:
1399 str = "global";
1400 break;
1401 case decl_base::BINDING_WEAK:
1402 str = "weak";
1403 break;
1404 }
1405
1406 if (!str.empty())
1407 o << " binding='" << str << "'";
1408
1409 return true;
1410}
1411
1412/// Write the "is-artificial" attribute of the @ref decl.
1413///
1414/// @param decl the declaration to consider.
1415///
1416/// @param o the output stream to emit the "is-artificial" attribute
1417/// to.
1418///
1419/// @return true iff the "is-artificial" attribute was emitted.
1420static bool
1421write_is_artificial(const decl_base_sptr& decl, ostream& o)
1422{
1423 if (!decl)
1424 return false;
1425
1426 if (decl->get_is_artificial())
1427 o << " is-artificial='yes'";
1428
1429 return true;
1430}
1431
1432/// Write the 'is-non-reachable' attribute if a given type we are
1433/// looking at is not reachable from global functions and variables
1434/// and if the user asked us to track that information.
1435///
1436/// @param t the type to consider.
1437///
1438/// @param o the output stream to write the 'is-non-reachable'
1439/// attribute to.
1440static bool
1441write_is_non_reachable(const type_base_sptr& t, ostream& o)
1442{
1443 if (!t)
1444 return false;
1445
1446 corpus* c = t->get_corpus();
1447 if (!c)
1448 return false;
1449
1450 if (!c->recording_types_reachable_from_public_interface_supported()
1451 || c->type_is_reachable_from_public_interfaces(*t))
1452 return false;
1453
1454 o << " is-non-reachable='yes'";
1455
1456 return true;
1457}
1458
1459/// Write the 'tracking-non-reachable-types' attribute if for a given
1460/// corpus, the user wants us to track non-reachable types.
1461///
1462/// @param corpus the ABI corpus to consider.
1463///
1464/// @param o the output parameter to write the
1465/// 'tracking-non-reachable-types' attribute to.
1466static bool
1467write_tracking_non_reachable_types(const corpus_sptr& corpus,
1468 ostream& o)
1469{
1470 corpus_group* group = corpus->get_group();
1471 if (!group)
1472 if (corpus->recording_types_reachable_from_public_interface_supported())
1473 {
1474 o << " tracking-non-reachable-types='yes'";
1475 return true;
1476 }
1477
1478 return false;
1479}
1480
1481/// Serialize the size and alignment attributes of a given type.
1482///
1483/// @param decl the type to consider.
1484///
1485/// @param o the output stream to serialize to.
1486///
1487/// @param default_size size in bits that is the default for the type.
1488/// No size-in-bits attribute is written if it
1489/// would be the default value.
1490///
1491/// @param default_alignment alignment in bits that is the default for
1492/// the type. No alignment-in-bits attribute is
1493/// written if it would be the default value.
1494static void
1495write_size_and_alignment(const shared_ptr<type_base> decl, ostream& o,
1496 size_t default_size, size_t default_alignment)
1497{
1498 size_t size_in_bits = decl->get_size_in_bits();
1499 if (size_in_bits != default_size)
1500 o << " size-in-bits='" << size_in_bits << "'";
1501
1502 size_t alignment_in_bits = decl->get_alignment_in_bits();
1503 if (alignment_in_bits != default_alignment)
1504 o << " alignment-in-bits='" << alignment_in_bits << "'";
1505}
1506
1507/// Serialize the size and alignment attributes of a given type.
1508/// @param decl the type to consider.
1509///
1510/// @param o the output stream to serialize to.
1511static void
1512write_array_size_and_alignment(const shared_ptr<array_type_def> decl, ostream& o)
1513{
1514 if (decl->is_non_finite())
1515 o << " size-in-bits='" << "unknown" << "'";
1516 else {
1517 size_t size_in_bits = decl->get_size_in_bits();
1518 if (size_in_bits)
1519 o << " size-in-bits='" << size_in_bits << "'";
1520 }
1521
1522 size_t alignment_in_bits = decl->get_alignment_in_bits();
1523 if (alignment_in_bits)
1524 o << " alignment-in-bits='" << alignment_in_bits << "'";
1525}
1526/// Serialize the access specifier.
1527///
1528/// @param a the access specifier to serialize.
1529///
1530/// @param o the output stream to serialize it to.
1531static void
1532write_access(access_specifier a, ostream& o)
1533{
1534 string access_str = "private";
1535
1536 switch (a)
1537 {
1538 case private_access:
1539 access_str = "private";
1540 break;
1541
1542 case protected_access:
1543 access_str = "protected";
1544 break;
1545
1546 case public_access:
1547 access_str = "public";
1548 break;
1549
1550 default:
1551 break;
1552 }
1553
1554 o << " access='" << access_str << "'";
1555}
1556
1557/// Serialize the layout offset of a data member.
1558static void
1559write_layout_offset(var_decl_sptr member, ostream& o)
1560{
1561 if (!is_data_member(member))
1562 return;
1563
1564 if (get_data_member_is_laid_out(member))
1565 o << " layout-offset-in-bits='"
1566 << get_data_member_offset(member)
1567 << "'";
1568}
1569
1570/// Serialize the layout offset of a base class
1571static void
1572write_layout_offset(shared_ptr<class_decl::base_spec> base, ostream& o)
1573{
1574 if (!base)
1575 return;
1576
1577 if (base->get_offset_in_bits() >= 0)
1578 o << " layout-offset-in-bits='" << base->get_offset_in_bits() << "'";
1579}
1580
1581/// Serialize the access specifier of a class member.
1582///
1583/// @param member a pointer to the class member to consider.
1584///
1585/// @param o the ostream to serialize the member to.
1586static void
1587write_access(decl_base_sptr member, ostream& o)
1588{write_access(get_member_access_specifier(member), o);}
1589
1590/// Write the voffset of a member function if it's non-zero
1591///
1592/// @param fn the member function to consider
1593///
1594/// @param o the output stream to write to
1595static void
1596write_voffset(function_decl_sptr fn, ostream&o)
1597{
1598 if (!fn)
1599 return;
1600
1602 {
1603 ssize_t voffset = get_member_function_vtable_offset(fn);
1604 o << " vtable-offset='" << voffset << "'";
1605 }
1606}
1607
1608/// Serialize an elf_symbol::type into an XML node attribute named
1609/// 'type'.
1610///
1611/// @param t the elf_symbol::type to serialize.
1612///
1613/// @param o the output stream to serialize it to.
1614static void
1615write_elf_symbol_type(elf_symbol::type t, ostream& o)
1616{
1617 string repr;
1618
1619 switch (t)
1620 {
1621 case elf_symbol::NOTYPE_TYPE:
1622 repr = "no-type";
1623 break;
1624 case elf_symbol::OBJECT_TYPE:
1625 repr = "object-type";
1626 break;
1627 case elf_symbol::FUNC_TYPE:
1628 repr = "func-type";
1629 break;
1630 case elf_symbol::SECTION_TYPE:
1631 repr = "section-type";
1632 break;
1633 case elf_symbol::FILE_TYPE:
1634 repr = "file-type";
1635 break;
1636 case elf_symbol::COMMON_TYPE:
1637 repr = "common-type";
1638 break;
1639 case elf_symbol::TLS_TYPE:
1640 repr = "tls-type";
1641 break;
1642 case elf_symbol::GNU_IFUNC_TYPE:
1643 repr = "gnu-ifunc-type";
1644 break;
1645 default:
1646 repr = "no-type";
1647 break;
1648 }
1649
1650 o << " type='" << repr << "'";
1651}
1652
1653/// Serialize an elf_symbol::binding into an XML element attribute of
1654/// name 'binding'.
1655///
1656/// @param b the elf_symbol::binding to serialize.
1657///
1658/// @param o the output stream to serialize the binding to.
1659static void
1660write_elf_symbol_binding(elf_symbol::binding b, ostream& o)
1661{
1662 string repr;
1663
1664 switch (b)
1665 {
1666 case elf_symbol::LOCAL_BINDING:
1667 repr = "local-binding";
1668 break;
1669 case elf_symbol::GLOBAL_BINDING:
1670 repr = "global-binding";
1671 break;
1672 case elf_symbol::WEAK_BINDING:
1673 repr = "weak-binding";
1674 break;
1675 case elf_symbol::GNU_UNIQUE_BINDING:
1676 repr = "gnu-unique-binding";
1677 break;
1678 default:
1679 repr = "no-binding";
1680 break;
1681 }
1682
1683 o << " binding='" << repr << "'";
1684}
1685
1686/// Serialize an elf_symbol::binding into an XML element attribute of
1687/// name 'binding'.
1688///
1689/// @param b the elf_symbol::binding to serialize.
1690///
1691/// @param o the output stream to serialize the binding to.
1692static void
1693write_elf_symbol_visibility(elf_symbol::visibility v, ostream& o)
1694{
1695 string repr;
1696
1697 switch (v)
1698 {
1699 case elf_symbol::DEFAULT_VISIBILITY:
1700 repr = "default-visibility";
1701 break;
1702 case elf_symbol::PROTECTED_VISIBILITY:
1703 repr = "protected-visibility";
1704 break;
1705 case elf_symbol::HIDDEN_VISIBILITY:
1706 repr = "hidden-visibility";
1707 break;
1708 case elf_symbol::INTERNAL_VISIBILITY:
1709 repr = "internal-visibility";
1710 break;
1711 default:
1712 repr = "default-visibility";
1713 break;
1714 }
1715
1716 o << " visibility='" << repr << "'";
1717}
1718
1719/// Write alias attributes for the aliases of a given symbol.
1720///
1721/// @param sym the symbol to write the attributes for.
1722///
1723/// @param o the output stream to write the attributes to.
1724///
1725/// @return true upon successful completion.
1726static bool
1727write_elf_symbol_aliases(const elf_symbol& sym, ostream& out)
1728{
1729 if (!sym.is_main_symbol() || !sym.has_aliases())
1730 return false;
1731
1732
1733 std::vector<std::string> aliases;
1734 for (elf_symbol_sptr s = sym.get_next_alias(); s && !s->is_main_symbol();
1735 s = s->get_next_alias())
1736 {
1737 if (!s->is_public())
1738 continue;
1739
1740 if (s->is_suppressed())
1741 continue;
1742
1743 if (sym.is_in_ksymtab() != s->is_in_ksymtab())
1744 continue;
1745
1746 aliases.push_back(s->get_id_string());
1747 }
1748
1749 if (!aliases.empty())
1750 {
1751 out << " alias='";
1752 std::string separator;
1753 for (const auto& alias : aliases)
1754 {
1755 out << separator << alias;
1756 separator = ",";
1757 }
1758
1759 out << "'";
1760 return true;
1761 }
1762
1763 return false;
1764}
1765
1766/// Write an XML attribute for the reference to a symbol for the
1767/// current decl.
1768///
1769/// @param sym the symbol to consider.
1770///
1771/// @param o the output stream to write the attribute to.
1772///
1773/// @return true upon successful completion.
1774static bool
1775write_elf_symbol_reference(const elf_symbol& sym, ostream& o)
1776{
1777 const elf_symbol* main = sym.get_main_symbol().get();
1778 const elf_symbol* alias = &sym;
1779 bool found = !alias->is_suppressed();
1780 // If the symbol itself is suppressed, check the alias chain.
1781 if (!found)
1782 {
1783 alias = main;
1784 found = !alias->is_suppressed();
1785 }
1786 // If the main symbol is suppressed, search the remainder of the chain.
1787 while (!found)
1788 {
1789 alias = alias->get_next_alias().get();
1790 // Two separate termination conditions at present.
1791 if (!alias || alias == main)
1792 break;
1793 found = !alias->is_suppressed();
1794 }
1795 // If all aliases are suppressed, just stick with the main symbol.
1796 if (!found)
1797 alias = main;
1798 o << " elf-symbol-id='"
1799 << xml::escape_xml_string(alias->get_id_string())
1800 << "'";
1801 return true;
1802}
1803
1804/// Write an XML attribute for the reference to a symbol for the
1805/// current decl.
1806///
1807/// @param sym the symbol to consider.
1808///
1809/// @param o the output stream to write the attribute to.
1810///
1811/// @return true upon successful completion.
1812static bool
1813write_elf_symbol_reference(const elf_symbol_sptr sym, ostream& o)
1814{
1815 if (!sym)
1816 return false;
1817
1818 return write_elf_symbol_reference(*sym, o);
1819}
1820
1821/// Serialize the attributes "constructor", "destructor" or "static"
1822/// if they have true value.
1823///
1824/// @param is_ctor if set to true, the "constructor='true'" string is
1825/// emitted.
1826///
1827/// @param is_dtor if set to true the "destructor='true' string is
1828/// emitted.
1829///
1830/// @param is_static if set to true the "static='true'" string is
1831/// emitted.
1832///
1833/// @param o the output stream to use for the serialization.
1834static void
1835write_cdtor_const_static(bool is_ctor,
1836 bool is_dtor,
1837 bool is_const,
1838 bool is_static,
1839 ostream& o)
1840{
1841 if (is_static)
1842 o << " static='yes'";
1843 if (is_ctor)
1844 o << " constructor='yes'";
1845 else if (is_dtor)
1846 o << " destructor='yes'";
1847 if (is_const)
1848 o << " const='yes'";
1849}
1850
1851/// Serialize the attribute "is-declaration-only", if the
1852/// decl_base_sptr has its 'is_declaration_only property set.
1853///
1854/// @param t the pointer to instance of @ref decl_base to consider.
1855///
1856/// @param o the output stream to serialize to.
1857static void
1858write_is_declaration_only(const decl_base_sptr& d, ostream& o)
1859{
1860 if (d->get_is_declaration_only())
1861 o << " is-declaration-only='yes'";
1862}
1863
1864/// Serialize the attribute "is-struct", if the current instance of
1865/// class_decl is a struct.
1866///
1867/// @param klass a pointer to the instance of class_decl to consider.
1868///
1869/// @param o the output stream to serialize to.
1870static void
1871write_is_struct(const class_decl_sptr& klass, ostream& o)
1872{
1873 if (klass->is_struct())
1874 o << " is-struct='yes'";
1875}
1876
1877/// Serialize the attribute "is-anonymous", if the current instance of
1878/// decl is anonymous
1879///
1880/// @param dcl a pointer to the instance of @ref decl_base to consider.
1881///
1882/// @param o the output stream to serialize to.
1883static void
1884write_is_anonymous(const decl_base_sptr& decl, ostream& o)
1885{
1886 if (decl->get_is_anonymous())
1887 o << " is-anonymous='yes'";
1888}
1889
1890/// Serialize the "naming-typedef-id" attribute, if the current
1891/// instance of @ref class_decl has a naming typedef.
1892///
1893/// @param klass the @ref class_decl to consider.
1894///
1895/// @param ctxt the write context to use.
1896static void
1897write_naming_typedef(const decl_base_sptr& decl, write_context& ctxt)
1898{
1899 if (!decl)
1900 return;
1901
1902 ostream &o = ctxt.get_ostream();
1903
1904 if (typedef_decl_sptr typedef_type = decl->get_naming_typedef())
1905 {
1906 string id = ctxt.get_id_for_type(typedef_type);
1907 o << " naming-typedef-id='" << id << "'";
1908 ctxt.record_type_as_referenced(typedef_type);
1909 }
1910}
1911
1912/// Helper to serialize a type artifact.
1913///
1914/// @param type the type to serialize.
1915///
1916/// @param ctxt the @ref write_context to use.
1917///
1918/// @param indent the number of white space to use for indentation.
1919///
1920/// @return true upon successful completion.
1921static bool
1922write_type(const type_base_sptr& type, write_context& ctxt, unsigned indent)
1923{
1924 if (write_type_decl(dynamic_pointer_cast<type_decl> (type),
1925 ctxt, indent)
1926 || write_qualified_type_def (dynamic_pointer_cast<qualified_type_def>
1927 (type),
1928 ctxt, indent)
1929 || write_pointer_type_def(dynamic_pointer_cast<pointer_type_def>(type),
1930 ctxt, indent)
1931 || write_reference_type_def(dynamic_pointer_cast
1932 <reference_type_def>(type), ctxt, indent)
1933 || write_ptr_to_mbr_type(dynamic_pointer_cast
1934 <ptr_to_mbr_type>(type),
1935 ctxt, indent)
1936 || write_array_type_def(dynamic_pointer_cast
1937 <array_type_def>(type), ctxt, indent)
1938 || write_enum_type_decl(dynamic_pointer_cast<enum_type_decl>(type),
1939 ctxt, indent)
1940 || write_typedef_decl(dynamic_pointer_cast<typedef_decl>(type),
1941 ctxt, indent)
1942 || write_class_decl(is_class_type(type), ctxt, indent)
1943 || write_union_decl(is_union_type(type), ctxt, indent)
1944 || (write_function_tdecl
1945 (dynamic_pointer_cast<function_tdecl>(type), ctxt, indent))
1946 || (write_class_tdecl
1947 (dynamic_pointer_cast<class_tdecl>(type), ctxt, indent)))
1948 return true;
1949
1950 return false;
1951}
1952
1953/// Serialize a pointer to an of decl_base into an output stream.
1954///
1955/// @param decl the pointer to decl_base to serialize
1956///
1957/// @param ctxt the context of the serialization. It contains e.g, the
1958/// output stream to serialize to.
1959///
1960/// @param indent how many indentation spaces to use during the
1961/// serialization.
1962///
1963/// @return true upon successful completion, false otherwise.
1964static bool
1965write_decl(const decl_base_sptr& decl, write_context& ctxt, unsigned indent)
1966{
1967 if (write_type_decl(dynamic_pointer_cast<type_decl> (decl),
1968 ctxt, indent)
1969 || write_namespace_decl(dynamic_pointer_cast<namespace_decl>(decl),
1970 ctxt, indent)
1971 || write_qualified_type_def (dynamic_pointer_cast<qualified_type_def>
1972 (decl),
1973 ctxt, indent)
1974 || write_pointer_type_def(dynamic_pointer_cast<pointer_type_def>(decl),
1975 ctxt, indent)
1976 || write_reference_type_def(dynamic_pointer_cast
1977 <reference_type_def>(decl), ctxt, indent)
1978 || write_ptr_to_mbr_type(dynamic_pointer_cast
1979 <ptr_to_mbr_type>(decl),
1980 ctxt, indent)
1981 || write_array_type_def(dynamic_pointer_cast
1982 <array_type_def>(decl), ctxt, indent)
1983 || write_array_subrange_type(dynamic_pointer_cast
1984 <array_type_def::subrange_type>(decl),
1985 ctxt, indent)
1986 || write_enum_type_decl(dynamic_pointer_cast<enum_type_decl>(decl),
1987 ctxt, indent)
1988 || write_typedef_decl(dynamic_pointer_cast<typedef_decl>(decl),
1989 ctxt, indent)
1990 || write_var_decl(dynamic_pointer_cast<var_decl>(decl), ctxt,
1991 /*write_linkage_name=*/true, indent)
1992 || write_function_decl(dynamic_pointer_cast<method_decl>
1993 (decl), ctxt, /*skip_first_parameter=*/true,
1994 indent)
1995 || write_function_decl(dynamic_pointer_cast<function_decl>(decl),
1996 ctxt, /*skip_first_parameter=*/false, indent)
1997 || write_class_decl(is_class_type(decl), ctxt, indent)
1998 || write_union_decl(is_union_type(decl), ctxt, indent)
1999 || (write_function_tdecl
2000 (dynamic_pointer_cast<function_tdecl>(decl), ctxt, indent))
2001 || (write_class_tdecl
2002 (dynamic_pointer_cast<class_tdecl>(decl), ctxt, indent)))
2003 return true;
2004
2005 return false;
2006}
2007
2008/// Emit a declaration, along with its scope.
2009///
2010/// This function is called at the end of emitting a translation unit,
2011/// to emit type declarations that were referenced by types that were
2012/// emitted in the TU already, but that were not emitted themselves.
2013///
2014/// @param decl the decl to emit.
2015///
2016/// @param ctxt the write context to use.
2017///
2018/// @param initial_indent the number of indentation spaces to use.
2019static void
2020write_decl_in_scope(const decl_base_sptr& decl,
2021 write_context& ctxt,
2022 unsigned initial_indent)
2023{
2024 type_base_sptr type = is_type(decl);
2025 ABG_ASSERT(type);
2026
2027 if (ctxt.type_is_emitted(type))
2028 return;
2029
2030 list<scope_decl*> scopes;
2031 for (scope_decl* s = decl->get_scope();
2032 s && !is_global_scope(s);
2033 s = s->get_scope())
2034 scopes.push_front(s);
2035
2036 ostream& o = ctxt.get_ostream();
2037 const config& c = ctxt.get_config();
2038 stack<string> closing_tags;
2039 stack<unsigned> closing_indents;
2040 unsigned indent = initial_indent;
2041 for (list<scope_decl*>::const_iterator i = scopes.begin();
2042 i != scopes.end();
2043 ++i)
2044 {
2046
2047 // A type scope is either a namespace ...
2048 if (namespace_decl* n = is_namespace(*i))
2049 {
2050 do_indent(o, indent);
2051 o << "<namespace-decl name='"
2052 << xml::escape_xml_string(n->get_name())
2053 << "'>\n";
2054 closing_tags.push("</namespace-decl>");
2055 closing_indents.push(indent);
2056 }
2057 // ... or a class.
2058 else if (class_decl* c = is_class_type(*i))
2059 {
2061 class_decl_sptr class_type(c, noop_deleter());
2062 if (!ctxt.type_is_emitted(c))
2063 {
2064 write_type(class_type, ctxt, initial_indent);
2065 break;
2066 }
2067 else
2068 {
2069 write_class_decl_opening_tag(class_type, "", ctxt, indent,
2070 /*prepare_to_handle_empty=*/false);
2071 closing_tags.push("</class-decl>");
2072 closing_indents.push(indent);
2073
2074 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1);
2075 write_member_type_opening_tag(type, ctxt, nb_ws);
2076 indent = nb_ws;
2077 closing_tags.push("</member-type>");
2078 closing_indents.push(nb_ws);
2079 }
2080 }
2081 else if (union_decl *u = is_union_type(*i))
2082 {
2084 union_decl_sptr union_type(u, noop_deleter());
2085 if (!ctxt.type_is_emitted(u))
2086 {
2087 write_type(union_type, ctxt, initial_indent);
2088 break;
2089 }
2090 else
2091 {
2092 write_union_decl_opening_tag(union_type, "", ctxt, indent,
2093 /*prepare_to_handle_empty=*/false);
2094 closing_tags.push("</union-decl>");
2095 closing_indents.push(indent);
2096
2097 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1);
2098 write_member_type_opening_tag(type, ctxt, nb_ws);
2099 indent = nb_ws;
2100 closing_tags.push("</member-type>");
2101 closing_indents.push(nb_ws);
2102 }
2103 }
2104 else
2105 // We should never reach this point.
2106 abort();
2107 indent += c.get_xml_element_indent();
2108 }
2109
2110 bool do_write = false;
2111 if (type_base_sptr type = is_type(decl))
2112 {
2113 if (!ctxt.type_is_emitted(type))
2114 do_write= true;
2115 }
2116 else
2117 {
2118 if (!ctxt.decl_is_emitted(decl))
2119 do_write= true;
2120 }
2121
2122 if (do_write)
2123 write_decl(decl, ctxt, indent);
2124
2125 while (!closing_tags.empty())
2126 {
2127 do_indent(o, closing_indents.top());
2128 o << closing_tags.top() << "\n";
2129 closing_tags.pop();
2130 closing_indents.pop();
2131 }
2132}
2133
2134/// Create a @ref write_context object that can be used to emit abixml
2135/// files.
2136///
2137/// @param env the environment for the @ref write_context object to use.
2138///
2139/// @param default_output_stream the default output stream to use.
2140///
2141/// @return the new @ref write_context object.
2144 ostream& default_output_stream)
2145{
2146 write_context_sptr ctxt(new write_context(env, default_output_stream));
2147 return ctxt;
2148}
2149
2150/// Set the "show-locs" flag.
2151///
2152/// When this flag is set then the XML writer emits location (///
2153/// information (file name, line and column) for the ABI artifacts
2154/// that it emits.
2155///
2156/// @param ctxt the @ref write_context to set the option for.
2157///
2158/// @param flag the new value of the option.
2159void
2160set_show_locs(write_context& ctxt, bool flag)
2161{ctxt.set_show_locs(flag);}
2162
2163/// Set the 'annotate' flag.
2164///
2165/// When this flag is set then the XML writer annotates ABI artifacts
2166/// with a human readable description.
2167///
2168/// @param ctxt the context to set this flag on to.
2169///
2170/// @param flag the new value of the 'annotate' flag.
2171void
2172set_annotate(write_context& ctxt, bool flag)
2173{ctxt.set_annotate(flag);}
2174
2175/// Set the new ostream.
2176///
2177/// The ostream refers to the object, writers should stream new output to.
2178///
2179/// @param ctxt the context to set this to.
2180///
2181/// @param os the new ostream
2182void
2183set_ostream(write_context& ctxt, ostream& os)
2184{ctxt.set_ostream(os);}
2185
2186/// Set the 'write-architecture' flag.
2187///
2188/// When this flag is set then the XML writer will emit architecture
2189/// information
2190///
2191/// @param ctxt the context to set this flag on to.
2192///
2193/// @param flag the new value of the 'write-architecture' flag.
2194void
2195set_write_architecture(write_context& ctxt, bool flag)
2196{ctxt.set_write_architecture(flag);}
2197
2198/// Set the 'write-corpus-path' flag.
2199///
2200/// When this flag is set then the XML writer will emit corpus-path
2201/// information
2202///
2203/// @param ctxt the context to set this flag on to.
2204///
2205/// @param flag the new value of the 'write-corpus-path' flag.
2206void
2207set_write_corpus_path(write_context& ctxt, bool flag)
2208{ctxt.set_write_corpus_path(flag);}
2209
2210/// Set the 'write-comp-dir' flag.
2211///
2212/// When this flag is set then the XML writer will emit compilation dir
2213/// information
2214///
2215/// @param ctxt the context to set this flag on to.
2216///
2217/// @param flag the new value of the 'write-comp-dir' flag.
2218void
2219set_write_comp_dir(write_context& ctxt, bool flag)
2220{ctxt.set_write_comp_dir(flag);}
2221
2222/// Set the 'short-locs' flag.
2223///
2224/// When this flag is set then the XML writer will emit only file names
2225/// rather than full paths.
2226///
2227/// @param ctxt the context to set this flag on to.
2228///
2229/// @param flag the new value of the 'short-locs' flag.
2230void
2231set_short_locs(write_context& ctxt, bool flag)
2232{ctxt.set_short_locs(flag);}
2233
2234/// Set the 'parameter-names' flag.
2235///
2236/// When this flag is set then the XML writer will emit the names of
2237/// function parameters.
2238///
2239/// @param ctxt the context to set this flag on to.
2240///
2241/// @param flag the new value of the 'parameter-names' flag.
2242void
2243set_write_parameter_names(write_context& ctxt, bool flag)
2244{ctxt.set_write_parameter_names(flag);}
2245
2246/// Set the 'elf-needed' flag.
2247///
2248/// When this flag is set then the XML writer will emit corpus
2249/// get_needed() (DT_NEEDED) information.
2250///
2251/// @param ctxt the context to set this flag on to.
2252///
2253/// @param flag the new value of the 'elf-needed' flag.
2254void
2255set_write_elf_needed(write_context& ctxt, bool flag)
2256{ctxt.set_write_elf_needed(flag);}
2257
2258/// Set the 'default-sizes' flag.
2259///
2260/// When this flag is set then the XML writer will emit default
2261/// size-in-bits attributes for pointer type definitions, reference
2262/// type definitions, function declarations and function types even
2263/// when they are equal to the default address size of the translation
2264/// unit.
2265///
2266/// @param ctxt the context to set this flag on to.
2267///
2268/// @param flag the new value of the 'default-sizes' flag.
2269void
2270set_write_default_sizes(write_context& ctxt, bool flag)
2271{ctxt.set_write_default_sizes(flag);}
2272
2273/// Set the 'type-id-style' property.
2274///
2275/// This property controls the kind of type ids used in XML output.
2276///
2277/// @param ctxt the context to set this property on.
2278///
2279/// @param style the new value of the 'type-id-style' property.
2280void
2282{ctxt.set_type_id_style(style);}
2283
2284/// Serialize the canonical types of a given scope.
2285///
2286/// @param scope the scope to consider.
2287///
2288/// @param ctxt the write context to use.
2289///
2290/// @param indent the number of white space indentation to use.
2291 //
2292 // @param is_member_type if true, the canonical types are emitted as
2293 // member types (of a class).
2294 //
2295 // return true upon successful completion.
2296static bool
2297write_canonical_types_of_scope(const scope_decl &scope,
2298 write_context &ctxt,
2299 const unsigned indent,
2300 bool is_member_type = false)
2301{
2302 const type_base_sptrs_type &canonical_types =
2304
2305 for (type_base_sptrs_type::const_iterator i = canonical_types.begin();
2306 i != canonical_types.end();
2307 ++i)
2308 {
2309 if (ctxt.type_is_emitted(*i))
2310 continue;
2311 if (is_member_type)
2312 write_member_type(*i, ctxt, indent);
2313 else
2314 write_type(*i, ctxt, indent);
2315 }
2316
2317 return true;
2318}
2319
2320/// Test if a type referenced in a given translation unit should be
2321/// emitted or not.
2322///
2323/// This is a subroutine of @ref write_translation_unit.
2324///
2325/// @param t the type to consider.
2326///
2327/// @param ctxt the write context to consider.
2328///
2329/// @param tu the translation unit to consider.
2330///
2331/// @param tu_is_last true if @p tu is the last translation unit being
2332/// emitted.
2333///
2334/// @return true iff @p t is to be emitted.
2335static bool
2336referenced_type_should_be_emitted(const type_base *t,
2337 const write_context& ctxt,
2338 const translation_unit& tu,
2339 bool tu_is_last)
2340{
2341 if ((tu_is_last || (t->get_translation_unit()
2342 && (t->get_translation_unit()->get_absolute_path()
2343 == tu.get_absolute_path())))
2344 && !ctxt.type_is_emitted(t))
2345 return true;
2346 return false;
2347}
2348
2349/// Emit the types that were referenced by other emitted types.
2350///
2351/// This is a sub-routine of write_translation_unit.
2352///
2353/// @param ctxt the write context to use.
2354///
2355/// @param tu the current translation unit that is being emitted.
2356///
2357/// @param indent the indentation string.
2358///
2359/// @param is_last whether @p tu is the last translation unit or not.
2360static void
2361write_referenced_types(write_context & ctxt,
2362 const translation_unit& tu,
2363 const unsigned indent,
2364 bool is_last)
2365{
2366 const config& c = ctxt.get_config();
2367 // Now let's handle types that were referenced, but not yet
2368 // emitted because they are either:
2369 // 1/ Types without canonical type
2370 // 2/ or function types (these might have no scope).
2371
2372 // So this map of type -> string is to contain the referenced types
2373 // we need to emit.
2374 type_ptr_set_type referenced_types_to_emit;
2375
2376 // For each referenced type, ensure that it is either emitted in the
2377 // translation unit to which it belongs or in the last translation
2378 // unit as a last resort.
2379 for (type_ptr_set_type::const_iterator i =
2380 ctxt.get_referenced_types().begin();
2381 i != ctxt.get_referenced_types().end();
2382 ++i)
2383 if (referenced_type_should_be_emitted(*i, ctxt, tu, is_last))
2384 referenced_types_to_emit.insert(*i);
2385
2386 for (fn_type_ptr_set_type::const_iterator i =
2387 ctxt.get_referenced_function_types().begin();
2388 i != ctxt.get_referenced_function_types().end();
2389 ++i)
2390 if (referenced_type_should_be_emitted(*i, ctxt, tu, is_last))
2391 referenced_types_to_emit.insert(*i);
2392
2393 // Ok, now let's emit the referenced type for good.
2394 while (!referenced_types_to_emit.empty())
2395 {
2396 // But first, we need to sort them, otherwise, emitting the ABI
2397 // (in xml) of the same binary twice will yield different
2398 // results, because we'd be walking an *unordered* hash table.
2399 vector<type_base*> sorted_referenced_types;
2400 ctxt.sort_types(referenced_types_to_emit,
2401 sorted_referenced_types);
2402
2403 // Now, emit the referenced decls in a sorted order.
2404 for (vector<type_base*>::const_iterator i =
2405 sorted_referenced_types.begin();
2406 i != sorted_referenced_types.end();
2407 ++i)
2408 {
2409 // We handle types which have declarations *and* function
2410 // types here.
2411 type_base* t = *i;
2412 if (!ctxt.type_is_emitted(t))
2413 {
2414 if (decl_base* d = get_type_declaration(t))
2415 {
2416 decl_base_sptr decl(d, noop_deleter());
2417 write_decl_in_scope(decl, ctxt,
2418 indent + c.get_xml_element_indent());
2419 }
2420 else if (function_type* f = is_function_type(t))
2421 {
2422 function_type_sptr fn_type(f, noop_deleter());
2423 write_function_type(fn_type, ctxt,
2424 indent + c.get_xml_element_indent());
2425 }
2426 else
2428 }
2429 }
2430
2431 // So all the (referenced) types that we wanted to emit were
2432 // emitted.
2433 referenced_types_to_emit.clear();
2434
2435 // But then, while emitting those referenced type, other types
2436 // might have been referenced by those referenced types
2437 // themselves! So let's look at the sets of referenced type
2438 // that are maintained for the entire ABI corpus and see if
2439 // there are still some referenced types in there that are not
2440 // emitted yet. If yes, then we'll emit those again.
2441
2442 // For each referenced type, ensure that it is either emitted in
2443 // the translation unit to which it belongs or in the last
2444 // translation unit as a last resort.
2445 for (type_ptr_set_type::const_iterator i =
2446 ctxt.get_referenced_types().begin();
2447 i != ctxt.get_referenced_types().end();
2448 ++i)
2449 if (referenced_type_should_be_emitted(*i, ctxt, tu, is_last))
2450 referenced_types_to_emit.insert(*i);
2451 }
2452}
2453
2454/// Serialize a translation unit to an output stream.
2455///
2456/// @param ctxt the context of the serialization. It contains e.g,
2457/// the output stream to serialize to.
2458///
2459/// @param tu the translation unit to serialize.
2460///
2461/// @param indent how many indentation spaces to use during the
2462/// serialization.
2463///
2464/// @param is_last If true, it means the TU to emit is the last one of
2465/// the corpus. If this is the case, all the remaining referenced
2466/// types that were not emitted are going to be emitted here,
2467/// irrespective of if they belong to this TU or not. This is quite a
2468/// hack. Ideally, we should have a pass that walks all the TUs,
2469/// detect their non-emitted referenced types, before hand. Then,
2470/// when we start emitting the TUs, we know for each TU which
2471/// non-emitted referenced type should be emitted. As we don't yet
2472/// have such a pass, we do our best for now.
2473///
2474/// @return true upon successful completion, false otherwise.
2475bool
2476write_translation_unit(write_context& ctxt,
2477 const translation_unit& tu,
2478 const unsigned indent,
2479 bool is_last)
2480{
2481 if (tu.is_empty() && !is_last)
2482 return false;
2483
2484 if (is_last
2485 && tu.is_empty()
2486 && ctxt.has_non_emitted_referenced_types())
2487 return false;
2488
2489 ostream& o = ctxt.get_ostream();
2490 const config& c = ctxt.get_config();
2491
2492 do_indent(o, indent);
2493
2494 o << "<abi-instr";
2495
2496 if (tu.get_address_size() != 0)
2497 o << " address-size='" << static_cast<int>(tu.get_address_size()) << "'";
2498
2499 std::string tu_path = tu.get_path();
2500 if (ctxt.get_short_locs())
2501 tools_utils::base_name(tu_path, tu_path);
2502 if (!tu_path.empty())
2503 o << " path='" << xml::escape_xml_string(tu_path) << "'";
2504
2505 if (!tu.get_compilation_dir_path().empty() && ctxt.get_write_comp_dir())
2506 o << " comp-dir-path='"
2508
2509 if (tu.get_language() != translation_unit::LANG_UNKNOWN)
2510 o << " language='"
2512 <<"'";
2513
2514 if (tu.is_empty() && !is_last)
2515 {
2516 o << "/>\n";
2517 return true;
2518 }
2519
2520 o << ">\n";
2521
2522 write_canonical_types_of_scope(*tu.get_global_scope(),
2523 ctxt, indent + c.get_xml_element_indent());
2524
2525 typedef scope_decl::declarations declarations;
2526 const declarations& decls = tu.get_global_scope()->get_sorted_member_decls();
2527
2528 for (const decl_base_sptr& decl : decls)
2529 {
2530 if (type_base_sptr t = is_type(decl))
2531 {
2532 // Emit declaration-only classes that are needed. Some of
2533 // these classes can be empty. Those beasts can be classes
2534 // that only contain member types. They can also be classes
2535 // considered "opaque".
2536 if (class_decl_sptr class_type = is_class_type(t))
2537 if (class_type->get_is_declaration_only()
2538 && !ctxt.type_is_emitted(class_type))
2539 write_type(class_type, ctxt,
2540 indent + c.get_xml_element_indent());
2541
2542 if (is_non_canonicalized_type(t) && !ctxt.type_is_emitted(t))
2543 write_type(t, ctxt, indent + c.get_xml_element_indent());
2544 }
2545 else
2546 {
2547 if (!ctxt.decl_is_emitted(decl))
2548 write_decl(decl, ctxt, indent + c.get_xml_element_indent());
2549 }
2550 }
2551
2552 write_referenced_types(ctxt, tu, indent, is_last);
2553
2554 // Now handle all function types that were not only referenced by
2555 // emitted types.
2556 const vector<function_type_sptr>& t = tu.get_live_fn_types();
2557 vector<type_base_sptr> sorted_types;
2558 ctxt.sort_types(t, sorted_types);
2559
2560 for (vector<type_base_sptr>::const_iterator i = sorted_types.begin();
2561 i != sorted_types.end();
2562 ++i)
2563 {
2565
2566 if (fn_type->get_is_artificial() || ctxt.type_is_emitted(fn_type))
2567 // This function type is either already emitted or it's
2568 // artificial (i.e, artificially created just to represent the
2569 // conceptual type of a function), so skip it.
2570 continue;
2571
2572 ABG_ASSERT(fn_type);
2573 write_function_type(fn_type, ctxt, indent + c.get_xml_element_indent());
2574 }
2575
2576 // After we've written out the live function types, we need to write
2577 // the types they referenced.
2578 write_referenced_types(ctxt, tu, indent, is_last);
2579
2580 do_indent(o, indent);
2581 o << "</abi-instr>\n";
2582
2583 return true;
2584}
2585
2586/// Serialize a pointer to an instance of basic type declaration, into
2587/// an output stream.
2588///
2589/// @param d the basic type 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_type_decl(const type_decl_sptr& d, write_context& ctxt, unsigned indent)
2600{
2601 if (!d)
2602 return false;
2603
2604 ostream& o = ctxt.get_ostream();
2605
2606 annotate(d, ctxt, indent);
2607
2608 do_indent(o, indent);
2609
2610 o << "<type-decl name='" << xml::escape_xml_string(d->get_name()) << "'";
2611
2612 write_is_anonymous(d, o);
2613
2614 write_size_and_alignment(d, o);
2615
2616 write_is_declaration_only(d, o);
2617
2618 write_location(d, ctxt);
2619
2620 o << " id='" << ctxt.get_id_for_type(d) << "'" << "/>\n";
2621
2622 ctxt.record_type_as_emitted(d);
2623
2624 return true;
2625}
2626
2627/// Serialize a namespace declaration int an output stream.
2628///
2629/// @param decl the namespace declaration to serialize.
2630///
2631/// @param ctxt the context of the serialization. It contains e.g, the
2632/// output stream to serialize to.
2633///
2634/// @param indent how many indentation spaces to use during the
2635/// serialization.
2636///
2637/// @return true upon successful completion, false otherwise.
2638static bool
2639write_namespace_decl(const namespace_decl_sptr& decl,
2640 write_context& ctxt, unsigned indent)
2641{
2642 if (!decl || decl->is_empty_or_has_empty_sub_namespaces())
2643 return false;
2644
2645 ostream& o = ctxt.get_ostream();
2646 const config &c = ctxt.get_config();
2647
2648 annotate(decl, ctxt, indent);
2649
2650 do_indent(o, indent);
2651
2652 o << "<namespace-decl name='"
2653 << xml::escape_xml_string(decl->get_name())
2654 << "'>\n";
2655
2656 typedef scope_decl::declarations declarations;
2657 typedef declarations::const_iterator const_iterator;
2658 const declarations& d = decl->get_sorted_member_decls();
2659
2660 write_canonical_types_of_scope(*decl, ctxt,
2661 indent + c.get_xml_element_indent());
2662
2663 for (const_iterator i = d.begin(); i != d.end(); ++i)
2664 {
2665 if (type_base_sptr t = is_type(*i))
2666 if (ctxt.type_is_emitted(t))
2667 // This type has already been emitted to the current
2668 // translation unit so do not emit it again.
2669 continue;
2670 write_decl(*i, ctxt, indent + c.get_xml_element_indent());
2671 }
2672
2673 do_indent(o, indent);
2674 o << "</namespace-decl>\n";
2675
2676 return true;
2677}
2678
2679/// Serialize a qualified type declaration to an output stream.
2680///
2681/// @param decl the qualfied type declaration to write.
2682///
2683/// @param id the type id identitifier to use in the serialized
2684/// output. If this is empty, the function will compute an
2685/// appropriate one. This is useful when this function is called to
2686/// serialize the underlying type of a member type; in that case, the
2687/// caller has already computed the id of the *member type*, and that
2688/// id is the one to be written as the value of the 'id' attribute of
2689/// the XML element of the underlying type.
2690///
2691/// @param ctxt the write context.
2692///
2693/// @param indent the number of space to indent to during the
2694/// serialization.
2695///
2696/// @return true upon successful completion, false otherwise.
2697static bool
2698write_qualified_type_def(const qualified_type_def_sptr& decl,
2699 const string& id,
2700 write_context& ctxt,
2701 unsigned indent)
2702{
2703 if (!decl)
2704 return false;
2705
2706 ostream& o = ctxt.get_ostream();
2707
2708
2709 type_base_sptr underlying_type = decl->get_underlying_type();
2710
2711 annotate(decl, ctxt, indent);
2712
2713 do_indent(o, indent);
2714 o << "<qualified-type-def type-id='"
2715 << ctxt.get_id_for_type(underlying_type)
2716 << "'";
2717
2718 ctxt.record_type_as_referenced(underlying_type);
2719
2720 if (decl->get_cv_quals() & qualified_type_def::CV_CONST)
2721 o << " const='yes'";
2722 if (decl->get_cv_quals() & qualified_type_def::CV_VOLATILE)
2723 o << " volatile='yes'";
2724 if (decl->get_cv_quals() & qualified_type_def::CV_RESTRICT)
2725 o << " restrict='yes'";
2726
2727 write_location(static_pointer_cast<decl_base>(decl), ctxt);
2728
2729 string i = id;
2730 if (i.empty())
2731 i = ctxt.get_id_for_type(decl);
2732
2733 o << " id='" << i << "'/>\n";
2734
2735 ctxt.record_type_as_emitted(decl);
2736
2737 return true;
2738}
2739
2740/// Serialize a qualified type declaration to an output stream.
2741///
2742/// @param decl the qualfied type declaration to write.
2743///
2744/// @param ctxt the write context.
2745///
2746/// @param indent the number of space to indent to during the
2747/// serialization.
2748///
2749/// @return true upon successful completion, false otherwise.
2750static bool
2751write_qualified_type_def(const qualified_type_def_sptr& decl,
2752 write_context& ctxt,
2753 unsigned indent)
2754{return write_qualified_type_def(decl, "", ctxt, indent);}
2755
2756/// Serialize a pointer to an instance of pointer_type_def.
2757///
2758/// @param decl the pointer_type_def to serialize.
2759///
2760/// @param id the type id identitifier to use in the serialized
2761/// output. If this is empty, the function will compute an
2762/// appropriate one. This is useful when this function is called to
2763/// serialize the underlying type of a member type; in that case, the
2764/// caller has already computed the id of the *member type*, and that
2765/// id is the one to be written as the value of the 'id' attribute of
2766/// the XML element of the underlying type.
2767///
2768/// @param ctxt the context of the serialization.
2769///
2770/// @param indent the number of indentation white spaces to use.
2771///
2772/// @return true upon succesful completion, false otherwise.
2773static bool
2774write_pointer_type_def(const pointer_type_def_sptr& decl,
2775 const string& id,
2776 write_context& ctxt,
2777 unsigned indent)
2778{
2779 if (!decl)
2780 return false;
2781
2782 ostream& o = ctxt.get_ostream();
2783
2784 annotate(decl, ctxt, indent);
2785
2786 do_indent(o, indent);
2787
2788 string i;
2789
2790 o << "<pointer-type-def ";
2791
2792 type_base_sptr pointed_to_type = decl->get_pointed_to_type();
2793
2794 i = ctxt.get_id_for_type(pointed_to_type);
2795
2796 o << "type-id='" << i << "'";
2797
2798 ctxt.record_type_as_referenced(pointed_to_type);
2799
2800 write_size_and_alignment(decl, o,
2801 (ctxt.get_write_default_sizes()
2802 ? 0
2803 : decl->get_translation_unit()->get_address_size()),
2804 0);
2805
2806 i = id;
2807 if (i.empty())
2808 i = ctxt.get_id_for_type(decl);
2809
2810 o << " id='" << i << "'";
2811
2812 write_location(static_pointer_cast<decl_base>(decl), ctxt);
2813 o << "/>\n";
2814
2815 ctxt.record_type_as_emitted(decl);
2816
2817 return true;
2818}
2819
2820/// Serialize a pointer to an instance of pointer_type_def.
2821///
2822/// @param decl the pointer_type_def to serialize.
2823///
2824/// @param ctxt the context of the serialization.
2825///
2826/// @param indent the number of indentation white spaces to use.
2827///
2828/// @return true upon succesful completion, false otherwise.
2829static bool
2830write_pointer_type_def(const pointer_type_def_sptr& decl,
2831 write_context& ctxt,
2832 unsigned indent)
2833{return write_pointer_type_def(decl, "", ctxt, indent);}
2834
2835/// Serialize a pointer to an instance of reference_type_def.
2836///
2837/// @param decl the reference_type_def to serialize.
2838///
2839/// @param id the type id identitifier to use in the serialized
2840/// output. If this is empty, the function will compute an
2841/// appropriate one. This is useful when this function is called to
2842/// serialize the underlying type of a member type; in that case, the
2843/// caller has already computed the id of the *member type*, and that
2844/// id is the one to be written as the value of the 'id' attribute of
2845/// the XML element of the underlying type.
2846///
2847/// @param ctxt the context of the serialization.
2848///
2849/// @param indent the number of indentation white spaces to use.
2850///
2851/// @return true upon succesful completion, false otherwise.
2852static bool
2853write_reference_type_def(const reference_type_def_sptr& decl,
2854 const string& id,
2855 write_context& ctxt,
2856 unsigned indent)
2857{
2858 if (!decl)
2859 return false;
2860
2861 annotate(decl->get_canonical_type(), ctxt, indent);
2862
2863 ostream& o = ctxt.get_ostream();
2864
2865 do_indent(o, indent);
2866
2867 o << "<reference-type-def kind='";
2868 if (decl->is_lvalue())
2869 o << "lvalue";
2870 else
2871 o << "rvalue";
2872 o << "'";
2873
2874 type_base_sptr pointed_to_type = decl->get_pointed_to_type();
2875 o << " type-id='" << ctxt.get_id_for_type(pointed_to_type) << "'";
2876
2877 ctxt.record_type_as_referenced(pointed_to_type);
2878
2879 if (function_type_sptr f = is_function_type(decl->get_pointed_to_type()))
2880 ctxt.record_type_as_referenced(f);
2881
2882 write_size_and_alignment(decl, o,
2883 (ctxt.get_write_default_sizes()
2884 ? 0
2885 : decl->get_translation_unit()->get_address_size()),
2886 0);
2887
2888 string i = id;
2889 if (i.empty())
2890 i = ctxt.get_id_for_type(decl);
2891 o << " id='" << i << "'";
2892
2893 write_location(static_pointer_cast<decl_base>(decl), ctxt);
2894
2895 o << "/>\n";
2896
2897 ctxt.record_type_as_emitted(decl);
2898
2899 return true;
2900}
2901
2902/// Serialize a pointer to an instance of reference_type_def.
2903///
2904/// @param decl the reference_type_def to serialize.
2905///
2906/// @param ctxt the context of the serialization.
2907///
2908/// @param indent the number of indentation white spaces to use.
2909///
2910/// @return true upon succesful completion, false otherwise.
2911static bool
2912write_reference_type_def(const reference_type_def_sptr& decl,
2913 write_context& ctxt,
2914 unsigned indent)
2915{return write_reference_type_def(decl, "", ctxt, indent);}
2916
2917/// Serialize a pointer to an instance of @ref ptr_to_mbr_type.
2918///
2919/// @param decl a pointer to the @ref ptr_to_mbr_type to serialize.
2920///
2921/// @param id the ID of the type. If it's an empty string then a new
2922/// ID is generated.
2923///
2924/// @param ctxt the context of the serialization.
2925///
2926/// @param indent the number of indentation white spaces to use.
2927///
2928/// @return true upon succesful completion, false otherwise.
2929static bool
2930write_ptr_to_mbr_type(const ptr_to_mbr_type_sptr& decl,
2931 const string& id, write_context& ctxt,
2932 unsigned indent)
2933{
2934 if (!decl)
2935 return false;
2936
2937 annotate(decl->get_canonical_type(), ctxt, indent);
2938
2939 ostream& o = ctxt.get_ostream();
2940
2941 do_indent(o, indent);
2942
2943 o << "<pointer-to-member-type";
2944
2945 write_size_and_alignment(decl, o,
2946 (ctxt.get_write_default_sizes()
2947 ? 0
2948 : decl->get_translation_unit()->get_address_size()),
2949 0);
2950
2951 write_location(static_pointer_cast<decl_base>(decl), ctxt);
2952
2953 type_base_sptr member_type = decl->get_member_type();
2954 string i = ctxt.get_id_for_type(member_type);
2955 o << " member-type-id='" << i << "'";
2956 ctxt.record_type_as_referenced(member_type);
2957
2958 type_base_sptr containing_type = decl->get_containing_type();
2959 i = ctxt.get_id_for_type(containing_type);
2960 o << " containing-type-id='" << i << "'";
2961 ctxt.record_type_as_referenced(containing_type);
2962
2963 i = id;
2964 if (i.empty())
2965 i = ctxt.get_id_for_type(decl);
2966 o << " id ='" << i << "'";
2967
2968 o << "/>\n";
2969
2970 ctxt.record_type_as_emitted(decl);
2971
2972 return true;
2973}
2974
2975/// Serialize a pointer to an instance of @ref ptr_to_mbr_type.
2976///
2977/// @param decl a pointer to the @ref ptr_to_mbr_type to serialize.
2978///
2979/// @param ctxt the context of the serialization.
2980///
2981/// @param indent the number of indentation white spaces to use.
2982///
2983/// @return true upon succesful completion, false otherwise.
2984static bool
2985write_ptr_to_mbr_type(const ptr_to_mbr_type_sptr& decl,
2986 write_context& ctxt, unsigned indent)
2987{return write_ptr_to_mbr_type(decl, "", ctxt, indent);}
2988
2989/// Serialize an instance of @ref array_type_def::subrange_type.
2990///
2991/// @param decl the array_type_def::subrange_type to serialize.
2992///
2993/// @param ctxt the context of the serialization.
2994///
2995/// @param indent the number of indentation white spaces to use.
2996///
2997/// return true upon successful completion, false otherwise.
2998static bool
2999write_array_subrange_type(const array_type_def::subrange_sptr& decl,
3000 write_context& ctxt,
3001 unsigned indent)
3002{
3003 if (!decl)
3004 return false;
3005
3006 annotate(decl, ctxt, indent);
3007
3008 ostream& o = ctxt.get_ostream();
3009
3010 do_indent(o, indent);
3011
3012 o << "<subrange";
3013
3014 if (!decl->get_name().empty())
3015 o << " name='" << decl->get_name() << "'";
3016
3017 o << " length='";
3018 if (decl->is_non_finite())
3019 o << "unknown";
3020 else
3021 o << decl->get_length();
3022
3023 o << "'";
3024
3025 ABG_ASSERT(decl->is_non_finite()
3026 || decl->get_length() == 0
3027 || (decl->get_length() ==
3028 (uint64_t) (decl->get_upper_bound()
3029 - decl->get_lower_bound() + 1)));
3030 o << " lower-bound='" << decl->get_lower_bound() << "' upper-bound='"
3031 << decl->get_upper_bound() << "'";
3032
3033 type_base_sptr underlying_type = decl->get_underlying_type();
3034 if (underlying_type)
3035 {
3036 o << " type-id='"
3037 << ctxt.get_id_for_type(underlying_type)
3038 << "'";
3039 ctxt.record_type_as_referenced(underlying_type);
3040 }
3041
3042 o << " id='" << ctxt.get_id_for_type(decl) << "'";
3043
3044 write_location(decl->get_location(), ctxt);
3045
3046 o << "/>\n";
3047
3048 ctxt.record_type_as_emitted(decl);
3049
3050 return true;
3051}
3052
3053/// Serialize a pointer to an instance of array_type_def.
3054///
3055/// @param decl the array_type_def to serialize.
3056///
3057/// @param id the type id identitifier to use in the serialized
3058/// output. If this is empty, the function will compute an
3059/// appropriate one. This is useful when this function is called to
3060/// serialize the underlying type of a member type; in that case, the
3061/// caller has already computed the id of the *member type*, and that
3062/// id is the one to be written as the value of the 'id' attribute of
3063/// the XML element of the underlying type.
3064///
3065/// @param ctxt the context of the serialization.
3066///
3067/// @param indent the number of indentation white spaces to use.
3068///
3069/// @return true upon succesful completion, false otherwise.
3070static bool
3071write_array_type_def(const array_type_def_sptr& decl,
3072 const string& id,
3073 write_context& ctxt,
3074 unsigned indent)
3075{
3076 if (!decl)
3077 return false;
3078
3079 annotate(decl, ctxt, indent);
3080
3081 ostream& o = ctxt.get_ostream();
3082
3083 do_indent(o, indent);
3084 o << "<array-type-def";
3085
3086 o << " dimensions='" << decl->get_dimension_count() << "'";
3087
3088 type_base_sptr element_type = decl->get_element_type();
3089 o << " type-id='" << ctxt.get_id_for_type(element_type) << "'";
3090
3091 ctxt.record_type_as_referenced(element_type);
3092
3093 write_array_size_and_alignment(decl, o);
3094
3095 string i = id;
3096 if (i.empty())
3097 i = ctxt.get_id_for_type(decl);
3098 o << " id='" << i << "'";
3099
3100 write_location(static_pointer_cast<decl_base>(decl), ctxt);
3101
3102 if (!decl->get_dimension_count())
3103 o << "/>\n";
3104 else
3105 {
3106 o << ">\n";
3107
3108 vector<array_type_def::subrange_sptr>::const_iterator si;
3109
3110 for (si = decl->get_subranges().begin();
3111 si != decl->get_subranges().end(); ++si)
3112 {
3113 unsigned local_indent =
3114 indent + ctxt.get_config().get_xml_element_indent();
3115 write_array_subrange_type(*si, ctxt, local_indent);
3116 }
3117
3118 do_indent(o, indent);
3119 o << "</array-type-def>\n";
3120 }
3121
3122 ctxt.record_type_as_emitted(decl);
3123
3124 return true;
3125}
3126
3127/// Serialize a pointer to an instance of array_type_def.
3128///
3129/// @param decl the array_type_def to serialize.
3130///
3131/// @param ctxt the context of the serialization.
3132///
3133/// @param indent the number of indentation white spaces to use.
3134///
3135/// @return true upon succesful completion, false otherwise.
3136static bool
3137write_array_type_def(const array_type_def_sptr& decl,
3138 write_context& ctxt,
3139 unsigned indent)
3140{return write_array_type_def(decl, "", ctxt, indent);}
3141
3142/// Serialize a pointer to an instance of enum_type_decl.
3143///
3144/// @param decl the enum_type_decl to serialize.
3145///
3146/// @param id the type id identitifier to use in the serialized
3147/// output. If this is empty, the function will compute an
3148/// appropriate one. This is useful when this function is called to
3149/// serialize the underlying type of a member type; in that case, the
3150/// caller has already computed the id of the *member type*, and that
3151/// id is the one to be written as the value of the 'id' attribute of
3152/// the XML element of the underlying type.
3153///
3154/// @param ctxt the context of the serialization.
3155///
3156/// @param indent the number of indentation white spaces to use.
3157///
3158/// @return true upon succesful completion, false otherwise.
3159static bool
3160write_enum_type_decl(const enum_type_decl_sptr& d,
3161 const string& id,
3162 write_context& ctxt,
3163 unsigned indent)
3164{
3165 if (!d)
3166 return false;
3167
3169
3170 annotate(decl->get_canonical_type(), ctxt, indent);
3171
3172 ostream& o = ctxt.get_ostream();
3173
3174 do_indent(o, indent);
3175 o << "<enum-decl name='" << xml::escape_xml_string(decl->get_name()) << "'";
3176
3177 write_is_anonymous(decl, o);
3178 write_naming_typedef(decl, ctxt);
3179 write_is_artificial(decl, o);
3180 write_is_non_reachable(is_type(decl), o);
3181
3182 if (!decl->get_linkage_name().empty())
3183 o << " linkage-name='"
3184 << xml::escape_xml_string(decl->get_linkage_name())
3185 << "'";
3186
3187 write_location(decl, ctxt);
3188 write_is_declaration_only(decl, o);
3189
3190 string i = id;
3191 if (i.empty())
3192 i = ctxt.get_id_for_type(decl);
3193 o << " id='" << i << "'>\n";
3194
3195 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
3196 o << "<underlying-type type-id='"
3197 << ctxt.get_id_for_type(decl->get_underlying_type())
3198 << "'/>\n";
3199
3200 for (enum_type_decl::enumerators::const_iterator i =
3201 decl->get_enumerators().begin();
3202 i != decl->get_enumerators().end();
3203 ++i)
3204 {
3205 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
3206 o << "<enumerator name='"
3207 << i->get_name()
3208 << "' value='"
3209 << i->get_value()
3210 << "'/>\n";
3211 }
3212
3213 do_indent(o, indent);
3214 o << "</enum-decl>\n";
3215
3216 ctxt.record_type_as_emitted(decl);
3217
3218 return true;
3219}
3220
3221/// Serialize a pointer to an instance of enum_type_decl.
3222///
3223/// @param decl the enum_type_decl to serialize.
3224///
3225/// @param ctxt the context of the serialization.
3226///
3227/// @param indent the number of indentation white spaces to use.
3228///
3229/// @return true upon succesful completion, false otherwise.
3230static bool
3231write_enum_type_decl(const enum_type_decl_sptr& decl,
3232 write_context& ctxt,
3233 unsigned indent)
3234{return write_enum_type_decl(decl, "", ctxt, indent);}
3235
3236/// Serialize an @ref elf_symbol to an XML element of name
3237/// 'elf-symbol'.
3238///
3239/// @param sym the elf symbol to serialize.
3240///
3241/// @param ctxt the read context to use.
3242///
3243/// @param indent the number of white spaces to use as indentation.
3244///
3245/// @return true iff the function completed successfully.
3246static bool
3247write_elf_symbol(const elf_symbol_sptr& sym,
3248 write_context& ctxt,
3249 unsigned indent)
3250{
3251 if (!sym)
3252 return false;
3253
3254 ostream &o = ctxt.get_ostream();
3255
3256 annotate(sym, ctxt, indent);
3257 do_indent(o, indent);
3258 o << "<elf-symbol name='" << xml::escape_xml_string(sym->get_name()) << "'";
3259 if (sym->is_variable() && sym->get_size())
3260 o << " size='" << sym->get_size() << "'";
3261
3262 if (!sym->get_version().is_empty())
3263 {
3264 o << " version='" << sym->get_version().str() << "'";
3265 o << " is-default-version='";
3266 if (sym->get_version().is_default())
3267 o << "yes";
3268 else
3269 o << "no";
3270 o << "'";
3271 }
3272
3273 write_elf_symbol_type(sym->get_type(), o);
3274
3275 write_elf_symbol_binding(sym->get_binding(), o);
3276
3277 write_elf_symbol_visibility(sym->get_visibility(), o);
3278
3279 write_elf_symbol_aliases(*sym, o);
3280
3281 o << " is-defined='";
3282 if (sym->is_defined())
3283 o << "yes";
3284 else
3285 o << "no";
3286 o << "'";
3287
3288 if (sym->is_common_symbol())
3289 o << " is-common='yes'";
3290
3291 if (sym->get_crc().has_value())
3292 o << " crc='"
3293 << std::hex << std::showbase << sym->get_crc().value()
3294 << std::dec << std::noshowbase << "'";
3295
3296 if (sym->get_namespace().has_value())
3297 o << " namespace='" << sym->get_namespace().value() << "'";
3298
3299 o << "/>\n";
3300
3301 return true;
3302}
3303
3304/// Write the elf symbol database to the output associated to the
3305/// current context.
3306///
3307/// @param syms the sorted elf symbol data to write out.
3308///
3309/// @param ctxt the context to consider.
3310///
3311/// @param indent the number of white spaces to use as indentation.
3312///
3313/// @return true upon successful completion.
3314static bool
3315write_elf_symbols_table(const elf_symbols& syms,
3316 write_context& ctxt,
3317 unsigned indent)
3318{
3319 if (syms.empty())
3320 return false;
3321
3322 for (elf_symbols::const_iterator it = syms.begin(); it != syms.end(); ++it)
3323 write_elf_symbol(*it, ctxt, indent);
3324
3325 return true;
3326}
3327
3328/// Write a vector of dependency names for the current corpus we are
3329/// writting.
3330///
3331/// @param needed the vector of dependency names to write.
3332///
3333/// @param ctxt the write context to use for the writting.
3334///
3335/// @param indent the number of indendation spaces to use.
3336///
3337/// @return true upon successful completion, false otherwise.
3338static bool
3339write_elf_needed(const vector<string>& needed,
3340 write_context& ctxt,
3341 unsigned indent)
3342{
3343 if (needed.empty())
3344 return false;
3345
3346 ostream& o = ctxt.get_ostream();
3347
3348 for (vector<string>::const_iterator i = needed.begin();
3349 i != needed.end();
3350 ++i)
3351 {
3352 do_indent(o, indent);
3353 o << "<dependency name='" << *i << "'/>\n";
3354 }
3355 return true;
3356}
3357
3358/// Serialize a pointer to an instance of typedef_decl.
3359///
3360/// @param decl the typedef_decl to serialize.
3361///
3362/// @param id the type id identitifier to use in the serialized
3363/// output. If this is empty, the function will compute an
3364/// appropriate one. This is useful when this function is called to
3365/// serialize the underlying type of a member type; in that case, the
3366/// caller has already computed the id of the *member type*, and that
3367/// id is the one to be written as the value of the 'id' attribute of
3368/// the XML element of the underlying type.
3369///
3370/// @param ctxt the context of the serialization.
3371///
3372/// @param indent the number of indentation white spaces to use.
3373///
3374/// @return true upon succesful completion, false otherwise.
3375static bool
3376write_typedef_decl(const typedef_decl_sptr& decl,
3377 const string& id,
3378 write_context& ctxt,
3379 unsigned indent)
3380{
3381 if (!decl)
3382 return false;
3383
3384 ostream &o = ctxt.get_ostream();
3385
3386 annotate(decl, ctxt, indent);
3387
3388 do_indent(o, indent);
3389
3390 o << "<typedef-decl name='"
3391 << xml::escape_xml_string(decl->get_name())
3392 << "'";
3393
3394 type_base_sptr underlying_type = decl->get_underlying_type();
3395 string type_id = ctxt.get_id_for_type(underlying_type);
3396 o << " type-id='" << type_id << "'";
3397 ctxt.record_type_as_referenced(underlying_type);
3398
3399 write_location(decl, ctxt);
3400
3401 string i = id;
3402 if (i.empty())
3403 i = ctxt.get_id_for_type(decl);
3404
3405 o << " id='" << i << "'/>\n";
3406
3407 ctxt.record_type_as_emitted(decl);
3408
3409 return true;
3410}
3411
3412/// Serialize a pointer to an instance of typedef_decl.
3413///
3414/// @param decl the typedef_decl to serialize.
3415///
3416/// @param ctxt the context of the serialization.
3417///
3418/// @param indent the number of indentation white spaces to use.
3419///
3420/// @return true upon succesful completion, false otherwise.
3421static bool
3422write_typedef_decl(const typedef_decl_sptr& decl,
3423 write_context& ctxt,
3424 unsigned indent)
3425{return write_typedef_decl(decl, "", ctxt, indent);}
3426
3427/// Serialize a pointer to an instances of var_decl.
3428///
3429/// @param decl the var_decl to serialize.
3430///
3431/// @param ctxt the context of the serialization.
3432///
3433/// @param write_linkage_name if true, serialize the mangled name of
3434/// this variable.
3435///
3436/// @param indent the number of indentation white spaces to use.
3437///
3438/// @return true upon succesful completion, false otherwise.
3439static bool
3440write_var_decl(const var_decl_sptr& decl, write_context& ctxt,
3441 bool write_linkage_name, unsigned indent)
3442{
3443 if (!decl)
3444 return false;
3445
3446 annotate(decl, ctxt, indent);
3447
3448 ostream &o = ctxt.get_ostream();
3449
3450 do_indent(o, indent);
3451
3452 o << "<var-decl name='" << xml::escape_xml_string(decl->get_name()) << "'";
3453 type_base_sptr var_type = decl->get_type();
3454 o << " type-id='" << ctxt.get_id_for_type(var_type) << "'";
3455 ctxt.record_type_as_referenced(var_type);
3456
3457 if (write_linkage_name)
3458 {
3459 const string& linkage_name = decl->get_linkage_name();
3460 if (!linkage_name.empty())
3461 o << " mangled-name='" << linkage_name << "'";
3462 }
3463
3464 write_visibility(decl, o);
3465
3466 write_binding(decl, o);
3467
3468 write_location(decl, ctxt);
3469
3470 write_elf_symbol_reference(decl->get_symbol(), o);
3471
3472 o << "/>\n";
3473
3474 ctxt.record_decl_as_emitted(decl);
3475
3476 return true;
3477}
3478
3479/// Serialize a pointer to a function_decl.
3480///
3481/// @param decl the pointer to function_decl to serialize.
3482///
3483/// @param ctxt the context of the serialization.
3484///
3485/// @param skip_first_parm if true, do not serialize the first
3486/// parameter of the function decl.
3487///
3488/// @param indent the number of indentation white spaces to use.
3489///
3490/// @return true upon succesful completion, false otherwise.
3491static bool
3492write_function_decl(const function_decl_sptr& decl, write_context& ctxt,
3493 bool skip_first_parm, unsigned indent)
3494{
3495 if (!decl)
3496 return false;
3497
3498 annotate(decl, ctxt, indent);
3499
3500 ostream &o = ctxt.get_ostream();
3501
3502 do_indent(o, indent);
3503
3504 o << "<function-decl name='"
3505 << xml::escape_xml_string(decl->get_name())
3506 << "'";
3507
3508 if (!decl->get_linkage_name().empty())
3509 o << " mangled-name='"
3510 << xml::escape_xml_string(decl->get_linkage_name()) << "'";
3511
3512 write_location(decl, ctxt);
3513
3514 if (decl->is_declared_inline())
3515 o << " declared-inline='yes'";
3516
3517 write_visibility(decl, o);
3518
3519 write_binding(decl, o);
3520
3521 write_size_and_alignment(decl->get_type(), o,
3522 (ctxt.get_write_default_sizes()
3523 ? 0
3524 : decl->get_translation_unit()->get_address_size()),
3525 0);
3526 write_elf_symbol_reference(decl->get_symbol(), o);
3527
3528 o << ">\n";
3529
3530 type_base_sptr parm_type;
3531 vector<shared_ptr<function_decl::parameter> >::const_iterator pi =
3532 decl->get_parameters().begin();
3533 for ((skip_first_parm && pi != decl->get_parameters().end()) ? ++pi: pi;
3534 pi != decl->get_parameters().end();
3535 ++pi)
3536 {
3537 if ((*pi)->get_variadic_marker())
3538 {
3539 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
3540 o << "<parameter is-variadic='yes'";
3541 }
3542 else
3543 {
3544 parm_type = (*pi)->get_type();
3545
3546 annotate(*pi, ctxt,
3547 indent + ctxt.get_config().get_xml_element_indent());
3548
3549 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
3550
3551 o << "<parameter type-id='"
3552 << ctxt.get_id_for_type(parm_type)
3553 << "'";
3554 ctxt.record_type_as_referenced(parm_type);
3555
3556 if (ctxt.get_write_parameter_names() && !(*pi)->get_name().empty())
3557 o << " name='" << xml::escape_xml_string((*pi)->get_name()) << "'";
3558 }
3559 write_is_artificial(*pi, o);
3560 write_location((*pi)->get_location(), ctxt);
3561 o << "/>\n";
3562 }
3563
3564 if (shared_ptr<type_base> return_type = decl->get_return_type())
3565 {
3566 annotate(return_type , ctxt,
3567 indent + ctxt.get_config().get_xml_element_indent());
3568 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
3569 o << "<return type-id='" << ctxt.get_id_for_type(return_type) << "'/>\n";
3570 ctxt.record_type_as_referenced(return_type);
3571 }
3572
3573 do_indent(o, indent);
3574 o << "</function-decl>\n";
3575
3576 ctxt.record_decl_as_emitted(decl);
3577
3578 return true;
3579}
3580
3581/// Serialize a function_type.
3582///
3583/// @param decl the pointer to function_type to serialize.
3584///
3585/// @param ctxt the context of the serialization.
3586///
3587/// @param indent the number of indentation white spaces to use.
3588///
3589/// @return true upon succesful completion, false otherwise.
3590static bool
3591write_function_type(const function_type_sptr& fn_type,
3592 write_context& ctxt, unsigned indent)
3593{
3594 if (!fn_type)
3595 return false;
3596
3597 ostream &o = ctxt.get_ostream();
3598
3599 annotate(fn_type, ctxt, indent);
3600
3601 do_indent(o, indent);
3602
3603 o << "<function-type";
3604
3605 write_size_and_alignment(fn_type, o,
3606 (ctxt.get_write_default_sizes()
3607 ? 0
3608 : fn_type->get_translation_unit()->get_address_size()),
3609 0);
3610
3611 if (method_type_sptr method_type = is_method_type(fn_type))
3612 {
3613 o << " method-class-id='"
3614 << ctxt.get_id_for_type(method_type->get_class_type())
3615 << "'";
3616
3617 write_cdtor_const_static(/*is_ctor=*/false, /*is_dtor=*/false,
3618 /*is_const=*/method_type->get_is_const(),
3619 /*is_static=*/false, o);
3620 }
3621
3622 interned_string id = ctxt.get_id_for_type(fn_type);
3623
3624 o << " id='"
3625 << id << "'"
3626 << ">\n";
3627
3628 type_base_sptr parm_type;
3629 for (vector<function_decl::parameter_sptr>::const_iterator pi =
3630 fn_type->get_parameters().begin();
3631 pi != fn_type->get_parameters().end();
3632 ++pi)
3633 {
3634
3635 if ((*pi)->get_variadic_marker())
3636 {
3637 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
3638 o << "<parameter is-variadic='yes'";
3639 }
3640 else
3641 {
3642 parm_type = (*pi)->get_type();
3643
3644 annotate(*pi, ctxt, indent + ctxt.get_config().get_xml_element_indent());
3645
3646 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
3647 o << "<parameter type-id='"
3648 << ctxt.get_id_for_type(parm_type)
3649 << "'";
3650 ctxt.record_type_as_referenced(parm_type);
3651
3652 if (!(*pi)->get_name().empty())
3653 {
3654 string name = xml::escape_xml_string((*pi)->get_name());
3655 o << " name='" << name << "'";
3656 }
3657 }
3658 write_is_artificial(*pi, o);
3659 o << "/>\n";
3660 }
3661
3662 if (type_base_sptr return_type = fn_type->get_return_type())
3663 {
3664 annotate(return_type, ctxt, indent + ctxt.get_config().get_xml_element_indent());
3665 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
3666 o << "<return type-id='" << ctxt.get_id_for_type(return_type) << "'/>\n";
3667 ctxt.record_type_as_referenced(return_type);
3668 }
3669
3670 do_indent(o, indent);
3671 o << "</function-type>\n";
3672
3673 ctxt.record_type_as_emitted(fn_type);
3674 return true;
3675}
3676
3677/// Write the opening tag of a 'class-decl' element.
3678///
3679/// @param decl the class declaration to serialize.
3680///
3681/// @param the type ID to use for the 'class-decl' element,, or empty
3682/// if we need to build a new one.
3683///
3684/// @param ctxt the write context to use.
3685///
3686/// @param indent the number of white space to use for indentation.
3687///
3688/// @param prepare_to_handle_empty if set to true, then this function
3689/// figures out if the opening tag should be for an empty element or
3690/// not. If set to false, then the opening tag is unconditionnaly for
3691/// a non-empty element.
3692///
3693/// @return true upon successful completion.
3694static bool
3695write_class_decl_opening_tag(const class_decl_sptr& decl,
3696 const string& id,
3697 write_context& ctxt,
3698 unsigned indent,
3699 bool prepare_to_handle_empty)
3700{
3701 if (!decl)
3702 return false;
3703
3704 ostream& o = ctxt.get_ostream();
3705
3706 do_indent_to_level(ctxt, indent, 0);
3707
3708 o << "<class-decl name='" << xml::escape_xml_string(decl->get_name()) << "'";
3709
3710 write_size_and_alignment(decl, o);
3711
3712 write_is_struct(decl, o);
3713
3714 write_is_anonymous(decl, o);
3715
3716 write_is_artificial(decl, o);
3717
3718 write_is_non_reachable(is_type(decl), o);
3719
3720 write_naming_typedef(decl, ctxt);
3721
3722 write_visibility(decl, o);
3723
3724 write_location(decl, ctxt);
3725
3726 write_is_declaration_only(decl, o);
3727
3728 if (decl->get_earlier_declaration())
3729 {
3730 // This instance is the definition of an earlier declaration.
3731 o << " def-of-decl-id='"
3732 << ctxt.get_id_for_type(is_type(decl->get_earlier_declaration()))
3733 << "'";
3734 }
3735
3736 string i = id;
3737 if (i.empty())
3738 i = ctxt.get_id_for_type(decl);
3739 o << " id='" << i << "'";
3740
3741 if (prepare_to_handle_empty && decl->has_no_base_nor_member())
3742 o << "/>\n";
3743 else
3744 o << ">\n";
3745
3746 return true;
3747}
3748
3749/// Write the opening tag of a 'union-decl' element.
3750///
3751/// @param decl the union declaration to serialize.
3752///
3753/// @param the type ID to use for the 'union-decl' element, or empty
3754/// if we need to build a new one.
3755///
3756/// @param ctxt the write context to use.
3757///
3758/// @param indent the number of white space to use for indentation.
3759///
3760/// @param prepare_to_handle_empty if set to true, then this function
3761/// figures out if the opening tag should be for an empty element or
3762/// not. If set to false, then the opening tag is unconditionnaly for
3763/// a non-empty element.
3764///
3765/// @return true upon successful completion.
3766static bool
3767write_union_decl_opening_tag(const union_decl_sptr& decl,
3768 const string& id,
3769 write_context& ctxt,
3770 unsigned indent,
3771 bool prepare_to_handle_empty)
3772{
3773 if (!decl)
3774 return false;
3775
3776 ostream& o = ctxt.get_ostream();
3777
3778 do_indent_to_level(ctxt, indent, 0);
3779
3780 o << "<union-decl name='" << xml::escape_xml_string(decl->get_name()) << "'";
3781
3782 if (!decl->get_is_declaration_only())
3783 write_size_and_alignment(decl, o);
3784
3785 write_is_anonymous(decl, o);
3786
3787 write_naming_typedef(decl, ctxt);
3788
3789 write_visibility(decl, o);
3790
3791 write_is_artificial(decl, o);
3792
3793 write_is_non_reachable(is_type(decl), o);
3794
3795 write_location(decl, ctxt);
3796
3797 write_is_declaration_only(decl, o);
3798
3799 string i = id;
3800 if (i.empty())
3801 i = ctxt.get_id_for_type(decl);
3802 o << " id='" << i << "'";
3803
3804 if (prepare_to_handle_empty && decl->has_no_member())
3805 o << "/>\n";
3806 else
3807 o << ">\n";
3808
3809 return true;
3810}
3811
3812/// Serialize a class_decl type.
3813///
3814/// @param d the pointer to class_decl to serialize.
3815///
3816/// @param id the type id identitifier to use in the serialized
3817/// output. If this is empty, the function will compute an
3818/// appropriate one. This is useful when this function is called to
3819/// serialize the underlying type of a member type; in that case, the
3820/// caller has already computed the id of the *member type*, and that
3821/// id is the one to be written as the value of the 'id' attribute of
3822/// the XML element of the underlying type.
3823///
3824/// @param ctxt the context of the serialization.
3825///
3826/// @param indent the initial indentation to use.
3827static bool
3828write_class_decl(const class_decl_sptr& d,
3829 const string& id,
3830 write_context& ctxt,
3831 unsigned indent)
3832{
3833 if (!d)
3834 return false;
3835
3837
3838 annotate(decl, ctxt, indent);
3839
3840 ostream& o = ctxt.get_ostream();
3841
3842 if (decl->get_is_declaration_only())
3843 {
3844 type_base_wptrs_type result;
3845 canonical_type_sptr_set_type member_types;
3846 const environment& env = ctxt.get_environment();
3847
3848 // We are looking at a decl-only class. All decl-only classes
3849 // of a given name are equal. But then the problem is that a
3850 // decl-only class can still have member types. So we might
3851 // have other decl-only classes of the same name as this one,
3852 // but that have been defined in a namespace definition
3853 // somewhere else in a different translation-unit, for exemple.
3854 // Those other decl-only classes of the same name might have a
3855 // number of different member-types. So depending on the
3856 // decl-only class that is seen first, "different" ones might be
3857 // emitted here, even though they compare equal from the
3858 // library's point of view. This might lead to an instability
3859 // of the abixml output.
3860 //
3861 // So let's gather all the member-types of all the decl-only
3862 // classes of the fully-qualified name and emit them here.
3863 if (lookup_decl_only_class_types(env.intern(decl->get_qualified_name()),
3864 *decl->get_corpus(),
3865 result))
3866 {
3867 for (auto t : result)
3868 {
3869 type_base_sptr type(t);
3871 for (auto m : c->get_member_types())
3872 if (member_types.find(m) != member_types.end())
3873 member_types.insert(m);
3874 }
3875 }
3876
3877 if (!member_types.empty())
3878 {
3879 // So we now have a hand on the member types of the current
3880 // decl-only class we are looking at, so let's emit them in
3881 // a sorted manner.
3882
3883 write_class_decl_opening_tag(decl, id, ctxt, indent,
3884 /*prepare_to_handle_empty=*/
3885 member_types.empty());
3886
3887 vector<type_base_sptr> sorted_types;
3888 sort_types(member_types, sorted_types);
3889
3890 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1);
3891 // Really emit the member types now.
3892 for (auto t : sorted_types)
3893 if (!ctxt.type_is_emitted(t))
3894 write_member_type(t, ctxt, nb_ws);
3895
3896 if (!member_types.empty())
3897 o << indent << "</class-decl>\n";
3898
3899 // Mark all the decl-only classes as emitted, even if just
3900 // marking one of them should be enough. We are doing this
3901 // for logical consistency.
3902 for (auto t : result)
3903 ctxt.record_type_as_emitted(type_base_sptr(t));
3904 return true;
3905 }
3906 }
3907
3908 write_class_decl_opening_tag(decl, id, ctxt, indent,
3909 /*prepare_to_handle_empty=*/true);
3910
3911 if (!decl->has_no_base_nor_member())
3912 {
3913 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1);
3914 type_base_sptr base_type;
3915 for (class_decl::base_specs::const_iterator base =
3916 decl->get_base_specifiers().begin();
3917 base != decl->get_base_specifiers().end();
3918 ++base)
3919 {
3920 annotate((*base)->get_base_class(), ctxt, nb_ws);
3921 do_indent(o, nb_ws);
3922 o << "<base-class";
3923
3924 write_access((*base)->get_access_specifier(), o);
3925
3926 write_layout_offset (*base, o);
3927
3928 if ((*base)->get_is_virtual ())
3929 o << " is-virtual='yes'";
3930
3931 base_type = (*base)->get_base_class();
3932 o << " type-id='"
3933 << ctxt.get_id_for_type(base_type)
3934 << "'/>\n";
3935
3936 ctxt.record_type_as_referenced(base_type);
3937 }
3938
3939 write_canonical_types_of_scope(*decl, ctxt, nb_ws,
3940 /*is_member_type=*/true);
3941
3942 for (class_decl::member_types::const_iterator ti =
3943 decl->get_sorted_member_types().begin();
3944 ti != decl->get_sorted_member_types().end();
3945 ++ti)
3946 if (!(*ti)->get_naked_canonical_type())
3947 write_member_type(*ti, ctxt, nb_ws);
3948
3949 for (class_decl::data_members::const_iterator data =
3950 decl->get_data_members().begin();
3951 data != decl->get_data_members().end();
3952 ++data)
3953 {
3954 do_indent(o, nb_ws);
3955 o << "<data-member";
3956 write_access(get_member_access_specifier(*data), o);
3957
3958 bool is_static = get_member_is_static(*data);
3959 write_cdtor_const_static(/*is_ctor=*/false,
3960 /*is_dtor=*/false,
3961 /*is_const=*/false,
3962 /*is_static=*/is_static,
3963 o);
3964 write_layout_offset(*data, o);
3965 o << ">\n";
3966
3967 write_var_decl(*data, ctxt, is_static,
3968 get_indent_to_level(ctxt, indent, 2));
3969
3970 do_indent_to_level(ctxt, indent, 1);
3971 o << "</data-member>\n";
3972 }
3973
3974 for (class_decl::member_functions::const_iterator f =
3975 decl->get_member_functions().begin();
3976 f != decl->get_member_functions().end();
3977 ++f)
3978 {
3979 function_decl_sptr fn = *f;
3981 // All virtual member functions are emitted together,
3982 // later.
3983 continue;
3984
3986
3987 do_indent(o, nb_ws);
3988 o << "<member-function";
3989 write_access(get_member_access_specifier(fn), o);
3990 write_cdtor_const_static( get_member_function_is_ctor(fn),
3994 o);
3995 o << ">\n";
3996
3997 write_function_decl(fn, ctxt,
3998 /*skip_first_parameter=*/false,
3999 get_indent_to_level(ctxt, indent, 2));
4000
4001 do_indent_to_level(ctxt, indent, 1);
4002 o << "</member-function>\n";
4003 }
4004
4005 for (class_decl::member_functions::const_iterator f =
4006 decl->get_virtual_mem_fns().begin();
4007 f != decl->get_virtual_mem_fns().end();
4008 ++f)
4009 {
4010 function_decl_sptr fn = *f;
4011
4013
4014 do_indent(o, nb_ws);
4015 o << "<member-function";
4016 write_access(get_member_access_specifier(fn), o);
4017 write_cdtor_const_static( get_member_function_is_ctor(fn),
4021 o);
4022 write_voffset(fn, o);
4023 o << ">\n";
4024
4025 write_function_decl(fn, ctxt,
4026 /*skip_first_parameter=*/false,
4027 get_indent_to_level(ctxt, indent, 2));
4028
4029 do_indent_to_level(ctxt, indent, 1);
4030 o << "</member-function>\n";
4031 }
4032
4033 for (member_function_templates::const_iterator fn =
4034 decl->get_member_function_templates().begin();
4035 fn != decl->get_member_function_templates().end();
4036 ++fn)
4037 {
4038 do_indent(o, nb_ws);
4039 o << "<member-template";
4040 write_access((*fn)->get_access_specifier(), o);
4041 write_cdtor_const_static((*fn)->is_constructor(),
4042 /*is_dtor=*/false,
4043 (*fn)->is_const(),
4044 (*fn)->get_is_static(), o);
4045 o << ">\n";
4046 write_function_tdecl((*fn)->as_function_tdecl(), ctxt,
4047 get_indent_to_level(ctxt, indent, 2));
4048 do_indent(o, nb_ws);
4049 o << "</member-template>\n";
4050 }
4051
4052 for (member_class_templates::const_iterator cl =
4053 decl->get_member_class_templates().begin();
4054 cl != decl->get_member_class_templates().end();
4055 ++cl)
4056 {
4057 do_indent(o, nb_ws);
4058 o << "<member-template";
4059 write_access((*cl)->get_access_specifier(), o);
4060 write_cdtor_const_static(false, false, false,
4061 (*cl)->get_is_static(), o);
4062 o << ">\n";
4063 write_class_tdecl((*cl)->as_class_tdecl(), ctxt,
4064 get_indent_to_level(ctxt, indent, 2));
4065 do_indent(o, nb_ws);
4066 o << "</member-template>\n";
4067 }
4068
4069 do_indent_to_level(ctxt, indent, 0);
4070
4071 o << "</class-decl>\n";
4072 }
4073
4074 ctxt.record_type_as_emitted(decl);
4075
4076 return true;
4077}
4078
4079/// Serialize a class_decl type.
4080///
4081/// @param decl the pointer to class_decl to serialize.
4082///
4083/// @param ctxt the context of the serialization.
4084///
4085/// @param indent the initial indentation to use.
4086///
4087/// @return true upon successful completion.
4088static bool
4089write_class_decl(const class_decl_sptr& decl,
4090 write_context& ctxt,
4091 unsigned indent)
4092{return write_class_decl(decl, "", ctxt, indent);}
4093
4094/// Serialize a @ref union_decl type.
4095///
4096/// @param d the pointer to @ref union_decl to serialize.
4097///
4098/// @param ctxt the context of the serialization.
4099///
4100/// @param indent the initial indentation to use.
4101///
4102/// @return true upon successful completion.
4103static bool
4104write_union_decl(const union_decl_sptr& d,
4105 const string& id,
4106 write_context& ctxt,
4107 unsigned indent)
4108{
4109 if (!d)
4110 return false;
4111
4112 union_decl_sptr decl = is_union_type(look_through_decl_only_class(d));
4113
4114 annotate(decl, ctxt, indent);
4115
4116 ostream& o = ctxt.get_ostream();
4117
4118 write_union_decl_opening_tag(decl, id, ctxt, indent,
4119 /*prepare_to_handle_empty=*/true);
4120 if (!decl->has_no_member())
4121 {
4122 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1);
4123 for (class_decl::member_types::const_iterator ti =
4124 decl->get_member_types().begin();
4125 ti != decl->get_member_types().end();
4126 ++ti)
4127 if (!(*ti)->get_naked_canonical_type())
4128 write_member_type(*ti, ctxt, nb_ws);
4129
4130 write_canonical_types_of_scope(*decl, ctxt, nb_ws,
4131 /*is_member_type=*/true);
4132
4133 for (union_decl::data_members::const_iterator data =
4134 decl->get_data_members().begin();
4135 data != decl->get_data_members().end();
4136 ++data)
4137 {
4138 do_indent(o, nb_ws);
4139 o << "<data-member";
4140 write_access(get_member_access_specifier(*data), o);
4141
4142 bool is_static = get_member_is_static(*data);
4143 write_cdtor_const_static(/*is_ctor=*/false,
4144 /*is_dtor=*/false,
4145 /*is_const=*/false,
4146 /*is_static=*/is_static,
4147 o);
4148 o << ">\n";
4149
4150 write_var_decl(*data, ctxt, is_static,
4151 get_indent_to_level(ctxt, indent, 2));
4152
4153 do_indent_to_level(ctxt, indent, 1);
4154 o << "</data-member>\n";
4155 }
4156
4157 for (union_decl::member_functions::const_iterator f =
4158 decl->get_member_functions().begin();
4159 f != decl->get_member_functions().end();
4160 ++f)
4161 {
4162 function_decl_sptr fn = *f;
4164 // All virtual member functions are emitted together,
4165 // later.
4166 continue;
4167
4169
4170 do_indent(o, nb_ws);
4171 o << "<member-function";
4172 write_access(get_member_access_specifier(fn), o);
4173 write_cdtor_const_static( get_member_function_is_ctor(fn),
4177 o);
4178 o << ">\n";
4179
4180 write_function_decl(fn, ctxt,
4181 /*skip_first_parameter=*/false,
4182 get_indent_to_level(ctxt, indent, 2));
4183
4184 do_indent_to_level(ctxt, indent, 1);
4185 o << "</member-function>\n";
4186 }
4187
4188 for (member_function_templates::const_iterator fn =
4189 decl->get_member_function_templates().begin();
4190 fn != decl->get_member_function_templates().end();
4191 ++fn)
4192 {
4193 do_indent(o, nb_ws);
4194 o << "<member-template";
4195 write_access((*fn)->get_access_specifier(), o);
4196 write_cdtor_const_static((*fn)->is_constructor(),
4197 /*is_dtor=*/false,
4198 (*fn)->is_const(),
4199 (*fn)->get_is_static(), o);
4200 o << ">\n";
4201 write_function_tdecl((*fn)->as_function_tdecl(), ctxt,
4202 get_indent_to_level(ctxt, indent, 2));
4203 do_indent(o, nb_ws);
4204 o << "</member-template>\n";
4205 }
4206
4207 for (member_class_templates::const_iterator cl =
4208 decl->get_member_class_templates().begin();
4209 cl != decl->get_member_class_templates().end();
4210 ++cl)
4211 {
4212 do_indent(o, nb_ws);
4213 o << "<member-template";
4214 write_access((*cl)->get_access_specifier(), o);
4215 write_cdtor_const_static(false, false, false,
4216 (*cl)->get_is_static(), o);
4217 o << ">\n";
4218 write_class_tdecl((*cl)->as_class_tdecl(), ctxt,
4219 get_indent_to_level(ctxt, indent, 2));
4220 do_indent(o, nb_ws);
4221 o << "</member-template>\n";
4222 }
4223
4224 do_indent_to_level(ctxt, indent, 0);
4225
4226 o << "</union-decl>\n";
4227 }
4228
4229 ctxt.record_type_as_emitted(decl);
4230
4231 return true;
4232}
4233
4234static bool
4235write_union_decl(const union_decl_sptr& decl,
4236 write_context& ctxt,
4237 unsigned indent)
4238{return write_union_decl(decl, "", ctxt, indent);}
4239
4240/// Write the opening tag for a 'member-type' element.
4241///
4242/// @param t the member type to consider.
4243///
4244/// @param ctxt the write context to use.
4245///
4246/// @param indent the number of white spaces to use for indentation.
4247///
4248/// @return true upon successful completion.
4249static bool
4250write_member_type_opening_tag(const type_base_sptr& t,
4251 write_context& ctxt,
4252 unsigned indent)
4253{
4254 ostream& o = ctxt.get_ostream();
4255
4256 do_indent_to_level(ctxt, indent, 0);
4257
4258 decl_base_sptr decl = get_type_declaration(t);
4259 ABG_ASSERT(decl);
4260
4261 o << "<member-type";
4262 write_access(decl, o);
4263 o << ">\n";
4264
4265 return true;
4266}
4267
4268/// Serialize a member type.
4269///
4270/// Note that the id written as the value of the 'id' attribute of the
4271/// underlying type is actually the id of the member type, not the one
4272/// for the underying type. That id takes in account, the access
4273/// specifier and the qualified name of the member type.
4274///
4275/// @param decl the declaration of the member type to serialize.
4276///
4277/// @param ctxt the write context to use.
4278///
4279/// @param indent the number of levels to use for indentation
4280static bool
4281write_member_type(const type_base_sptr& t, write_context& ctxt, unsigned indent)
4282{
4283 if (!t)
4284 return false;
4285
4286 ostream& o = ctxt.get_ostream();
4287
4288 write_member_type_opening_tag(t, ctxt, indent);
4289
4290 string id = ctxt.get_id_for_type(t);
4291
4292 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1);
4293 ABG_ASSERT(write_qualified_type_def(dynamic_pointer_cast<qualified_type_def>(t),
4294 id, ctxt, nb_ws)
4295 || write_pointer_type_def(dynamic_pointer_cast<pointer_type_def>(t),
4296 id, ctxt, nb_ws)
4297 || write_reference_type_def(dynamic_pointer_cast<reference_type_def>(t),
4298 id, ctxt, nb_ws)
4299 || write_ptr_to_mbr_type(dynamic_pointer_cast<ptr_to_mbr_type>(t),
4300 id, ctxt, nb_ws)
4301 || write_array_type_def(dynamic_pointer_cast<array_type_def>(t),
4302 id, ctxt, nb_ws)
4303 || write_enum_type_decl(dynamic_pointer_cast<enum_type_decl>(t),
4304 id, ctxt, nb_ws)
4305 || write_typedef_decl(dynamic_pointer_cast<typedef_decl>(t),
4306 id, ctxt, nb_ws)
4307 || write_union_decl(dynamic_pointer_cast<union_decl>(t),
4308 id, ctxt, nb_ws)
4309 || write_class_decl(dynamic_pointer_cast<class_decl>(t),
4310 id, ctxt, nb_ws));
4311
4312 do_indent_to_level(ctxt, indent, 0);
4313 o << "</member-type>\n";
4314
4315 return true;
4316}
4317
4318/// Serialize an instance of type_tparameter.
4319///
4320/// @param decl the instance to serialize.
4321///
4322/// @param ctxt the context of the serialization.
4323///
4324/// @param indent the initial indentation to use.
4325///
4326/// @return true upon successful completion, false otherwise.
4327static bool
4328write_type_tparameter(const type_tparameter_sptr decl,
4329 write_context& ctxt,
4330 unsigned indent)
4331{
4332 if (!decl)
4333 return false;
4334
4335 ostream &o = ctxt.get_ostream();
4336 do_indent_to_level(ctxt, indent, 0);
4337
4338 string id_attr_name;
4339 if (ctxt.type_has_existing_id(decl))
4340 id_attr_name = "type-id";
4341 else
4342 id_attr_name = "id";
4343
4344 o << "<template-type-parameter "
4345 << id_attr_name << "='" << ctxt.get_id_for_type(decl) << "'";
4346
4347 std::string name = xml::escape_xml_string(decl->get_name ());
4348 if (!name.empty())
4349 o << " name='" << name << "'";
4350
4351 write_location(decl, ctxt);
4352
4353 o << "/>\n";
4354
4355 ctxt.record_type_as_emitted(decl);
4356
4357 return true;
4358}
4359
4360/// Serialize an instance of non_type_tparameter.
4361///
4362/// @param decl the instance to serialize.
4363///
4364/// @param ctxt the context of the serialization.
4365///
4366/// @param indent the intial indentation to use.
4367///
4368/// @return true open successful completion, false otherwise.
4369static bool
4370write_non_type_tparameter(
4371 const shared_ptr<non_type_tparameter> decl,
4372 write_context& ctxt, unsigned indent)
4373{
4374 if (!decl)
4375 return false;
4376
4377 ostream &o = ctxt.get_ostream();
4378 do_indent_to_level(ctxt, indent, 0);
4379
4380 o << "<template-non-type-parameter type-id='"
4381 << ctxt.get_id_for_type(decl->get_type())
4382 << "'";
4383
4384 string name = xml::escape_xml_string(decl->get_name());
4385 if (!name.empty())
4386 o << " name='" << name << "'";
4387
4388 write_location(decl, ctxt);
4389
4390 o << "/>\n";
4391
4392 return true;
4393}
4394
4395/// Serialize an instance of template template parameter.
4396///
4397/// @param decl the instance to serialize.
4398///
4399/// @param ctxt the context of the serialization.
4400///
4401/// @param indent the initial indentation to use.
4402///
4403/// @return true upon successful completion, false otherwise.
4404
4405static bool
4406write_template_tparameter (const template_tparameter_sptr decl,
4407 write_context& ctxt,
4408 unsigned indent)
4409{
4410 if (!decl)
4411 return false;
4412
4413 ostream& o = ctxt.get_ostream();
4414 do_indent_to_level(ctxt, indent, 0);
4415
4416 string id_attr_name = "id";
4417 if (ctxt.type_has_existing_id(decl))
4418 id_attr_name = "type-id";
4419
4420 o << "<template-template-parameter " << id_attr_name << "='"
4421 << ctxt.get_id_for_type(decl) << "'";
4422
4423 string name = xml::escape_xml_string(decl->get_name());
4424 if (!name.empty())
4425 o << " name='" << name << "'";
4426
4427 o << ">\n";
4428
4429 unsigned nb_spaces = get_indent_to_level(ctxt, indent, 1);
4430 for (list<shared_ptr<template_parameter> >::const_iterator p =
4431 decl->get_template_parameters().begin();
4432 p != decl->get_template_parameters().end();
4433 ++p)
4434 write_template_parameter(decl, ctxt, nb_spaces);
4435
4436 do_indent_to_level(ctxt, indent, 0);
4437 o << "</template-template-parameter>\n";
4438
4439 ctxt.record_type_as_emitted(decl);
4440
4441 return true;
4442}
4443
4444/// Serialize an instance of type_composition.
4445///
4446/// @param decl the decl to serialize.
4447///
4448/// @param ctxt the context of the serialization.
4449///
4450/// @param indent the initial indentation to use.
4451///
4452/// @return true upon successful completion, false otherwise.
4453static bool
4454write_type_composition
4455(const shared_ptr<type_composition> decl,
4456 write_context& ctxt, unsigned indent)
4457{
4458 if (!decl)
4459 return false;
4460
4461 ostream& o = ctxt.get_ostream();
4462
4463 do_indent_to_level(ctxt, indent, 0);
4464
4465 o << "<template-parameter-type-composition>\n";
4466
4467 unsigned nb_spaces = get_indent_to_level(ctxt, indent, 1);
4468 (write_pointer_type_def
4469 (dynamic_pointer_cast<pointer_type_def>(decl->get_composed_type()),
4470 ctxt, nb_spaces)
4471 || write_reference_type_def
4472 (dynamic_pointer_cast<reference_type_def>(decl->get_composed_type()),
4473 ctxt, nb_spaces)
4474 || write_array_type_def
4475 (dynamic_pointer_cast<array_type_def>(decl->get_composed_type()),
4476 ctxt, nb_spaces)
4477 || write_qualified_type_def
4478 (dynamic_pointer_cast<qualified_type_def>(decl->get_composed_type()),
4479 ctxt, nb_spaces));
4480
4481 do_indent_to_level(ctxt, indent, 0);
4482 o << "</template-parameter-type-composition>\n";
4483
4484 return true;
4485}
4486
4487/// Serialize an instance of template_parameter.
4488///
4489/// @param decl the instance to serialize.
4490///
4491/// @param ctxt the context of the serialization.
4492///
4493/// @param indent the initial indentation to use.
4494///
4495/// @return true upon successful completion, false otherwise.
4496static bool
4497write_template_parameter(const shared_ptr<template_parameter> decl,
4498 write_context& ctxt, unsigned indent)
4499{
4500 if ((!write_type_tparameter
4501 (dynamic_pointer_cast<type_tparameter>(decl), ctxt, indent))
4502 && (!write_non_type_tparameter
4503 (dynamic_pointer_cast<non_type_tparameter>(decl),
4504 ctxt, indent))
4505 && (!write_template_tparameter
4506 (dynamic_pointer_cast<template_tparameter>(decl),
4507 ctxt, indent))
4508 && (!write_type_composition
4509 (dynamic_pointer_cast<type_composition>(decl),
4510 ctxt, indent)))
4511 return false;
4512
4513 return true;
4514}
4515
4516/// Serialize the template parameters of the a given template.
4517///
4518/// @param tmpl the template for which to emit the template parameters.
4519static void
4520write_template_parameters(const shared_ptr<template_decl> tmpl,
4521 write_context& ctxt, unsigned indent)
4522{
4523 if (!tmpl)
4524 return;
4525
4526 unsigned nb_spaces = get_indent_to_level(ctxt, indent, 1);
4527 for (list<shared_ptr<template_parameter> >::const_iterator p =
4528 tmpl->get_template_parameters().begin();
4529 p != tmpl->get_template_parameters().end();
4530 ++p)
4531 write_template_parameter(*p, ctxt, nb_spaces);
4532}
4533
4534/// Serialize an instance of function_tdecl.
4535///
4536/// @param decl the instance to serialize.
4537///
4538/// @param ctxt the context of the serialization
4539///
4540/// @param indent the initial indentation.
4541static bool
4542write_function_tdecl(const shared_ptr<function_tdecl> decl,
4543 write_context& ctxt, unsigned indent)
4544{
4545 if (!decl)
4546 return false;
4547
4548 ostream& o = ctxt.get_ostream();
4549
4550 do_indent_to_level(ctxt, indent, 0);
4551
4552 o << "<function-template-decl id='" << ctxt.get_id_for_fn_tmpl(decl) << "'";
4553
4554 write_location(decl, ctxt);
4555
4556 write_visibility(decl, o);
4557
4558 write_binding(decl, o);
4559
4560 o << ">\n";
4561
4562 write_template_parameters(decl, ctxt, indent);
4563
4564 write_function_decl(decl->get_pattern(), ctxt,
4565 /*skip_first_parameter=*/false,
4566 get_indent_to_level(ctxt, indent, 1));
4567
4568 do_indent_to_level(ctxt, indent, 0);
4569
4570 o << "</function-template-decl>\n";
4571
4572 return true;
4573}
4574
4575
4576/// Serialize an instance of class_tdecl
4577///
4578/// @param decl a pointer to the instance of class_tdecl to serialize.
4579///
4580/// @param ctxt the context of the serializtion.
4581///
4582/// @param indent the initial number of white space to use for
4583/// indentation.
4584///
4585/// @return true upon successful completion, false otherwise.
4586static bool
4587write_class_tdecl(const shared_ptr<class_tdecl> decl,
4588 write_context& ctxt, unsigned indent)
4589{
4590 if (!decl)
4591 return false;
4592
4593 ostream& o = ctxt.get_ostream();
4594
4595 do_indent_to_level(ctxt, indent, 0);
4596
4597 o << "<class-template-decl id='" << ctxt.get_id_for_class_tmpl(decl) << "'";
4598
4599 write_location(decl, ctxt);
4600
4601 write_visibility(decl, o);
4602
4603 o << ">\n";
4604
4605 write_template_parameters(decl, ctxt, indent);
4606
4607 write_class_decl(decl->get_pattern(), ctxt,
4608 get_indent_to_level(ctxt, indent, 1));
4609
4610 do_indent_to_level(ctxt, indent, 0);
4611
4612 o << "</class-template-decl>\n";
4613
4614 return true;
4615}
4616
4617/// Serialize the current version number of the ABIXML format.
4618///
4619/// @param ctxt the writing context to use.
4620static void
4621write_version_info(write_context& ctxt)
4622{
4623 ostream& o = ctxt.get_ostream();
4624 const config& c = ctxt.get_config();
4625
4626 o << "version='"
4627 << c.get_format_major_version_number()
4628 << "." << c.get_format_minor_version_number()
4629 << "'";
4630}
4631
4632/// Serialize an ABI corpus to a single native xml document. The root
4633/// note of the resulting XML document is 'abi-corpus'.
4634///
4635/// Note: If either corpus is null or corpus does not contain serializable
4636/// content (i.e. corpus.is_empty()), nothing is emitted to the ctxt's
4637/// output stream.
4638///
4639/// @param ctxt the write context to use.
4640///
4641/// @param corpus the corpus to serialize.
4642///
4643/// @param indent the number of white space indentation to use.
4644///
4645/// @return true upon successful completion, false otherwise.
4646bool
4647write_corpus(write_context& ctxt,
4648 const corpus_sptr& corpus,
4649 unsigned indent,
4650 bool member_of_group)
4651{
4652 if (!corpus)
4653 return false;
4654
4655 if (corpus->is_empty())
4656 return true;
4657
4658 do_indent_to_level(ctxt, indent, 0);
4659
4660 std::ostream& out = ctxt.get_ostream();
4661
4662 out << "<abi-corpus ";
4663
4664 write_version_info(ctxt);
4665
4666 // For an abi-corpus as part of an abi-corpus group, only omit the path, but
4667 // keep the filename.
4668 std::string corpus_path = corpus->get_path();
4669 if (!ctxt.get_write_corpus_path())
4670 {
4671 if (member_of_group)
4672 tools_utils::base_name(corpus_path, corpus_path);
4673 else
4674 corpus_path.clear();
4675 }
4676 else
4677 {
4678 if (ctxt.get_short_locs())
4679 tools_utils::base_name(corpus_path, corpus_path);
4680 }
4681 if (!corpus_path.empty())
4682 out << " path='" << xml::escape_xml_string(corpus_path) << "'";
4683
4684 if (!corpus->get_architecture_name().empty()
4685 && ctxt.get_write_architecture())
4686 out << " architecture='" << corpus->get_architecture_name()<< "'";
4687
4688 if (!corpus->get_soname().empty())
4689 out << " soname='" << corpus->get_soname()<< "'";
4690
4691 write_tracking_non_reachable_types(corpus, out);
4692
4693 out << ">\n";
4694
4695 // Write the list of needed corpora.
4696
4697 if (ctxt.get_write_elf_needed () && !corpus->get_needed().empty())
4698 {
4699 do_indent_to_level(ctxt, indent, 1);
4700 out << "<elf-needed>\n";
4701 write_elf_needed(corpus->get_needed(), ctxt,
4702 get_indent_to_level(ctxt, indent, 2));
4703 do_indent_to_level(ctxt, indent, 1);
4704 out << "</elf-needed>\n";
4705 }
4706
4707 // Write the function symbols data base.
4708 if (!corpus->get_fun_symbol_map().empty())
4709 {
4710 do_indent_to_level(ctxt, indent, 1);
4711 out << "<elf-function-symbols>\n";
4712
4713 write_elf_symbols_table(corpus->get_sorted_fun_symbols(), ctxt,
4714 get_indent_to_level(ctxt, indent, 2));
4715
4716 do_indent_to_level(ctxt, indent, 1);
4717 out << "</elf-function-symbols>\n";
4718 }
4719
4720 // Write the variable symbols data base.
4721 if (!corpus->get_var_symbol_map().empty())
4722 {
4723 do_indent_to_level(ctxt, indent, 1);
4724 out << "<elf-variable-symbols>\n";
4725
4726 write_elf_symbols_table(corpus->get_sorted_var_symbols(), ctxt,
4727 get_indent_to_level(ctxt, indent, 2));
4728
4729 do_indent_to_level(ctxt, indent, 1);
4730 out << "</elf-variable-symbols>\n";
4731 }
4732
4733 // Now write the translation units.
4734 unsigned nb_tus = corpus->get_translation_units().size(), n = 0;
4735 for (translation_units::const_iterator i =
4736 corpus->get_translation_units().begin();
4737 i != corpus->get_translation_units().end();
4738 ++i, ++n)
4739 {
4740 translation_unit& tu = **i;
4741 write_translation_unit(ctxt, tu,
4742 get_indent_to_level(ctxt, indent, 1),
4743 n == nb_tus - 1);
4744 }
4745
4746 do_indent_to_level(ctxt, indent, 0);
4747 out << "</abi-corpus>\n";
4748
4749 ctxt.clear_referenced_types();
4750 ctxt.record_corpus_as_emitted(corpus);
4751
4752 return true;
4753}
4754
4755/// Serialize an ABI corpus group to a single native xml document.
4756/// The root note of the resulting XML document is 'abi-corpus-group'.
4757///
4758/// @param ctxt the write context to use.
4759///
4760/// @param group the corpus group to serialize.
4761///
4762/// @param indent the number of white space indentation to use.
4763///
4764/// @return true upon successful completion, false otherwise.
4765bool
4766write_corpus_group(write_context& ctxt,
4767 const corpus_group_sptr& group,
4768 unsigned indent)
4769
4770{
4771 if (!group)
4772 return false;
4773
4774 do_indent_to_level(ctxt, indent, 0);
4775
4776std::ostream& out = ctxt.get_ostream();
4777
4778 out << "<abi-corpus-group ";
4779 write_version_info(ctxt);
4780
4781 if (!group->get_path().empty() && ctxt.get_write_corpus_path())
4782 out << " path='" << xml::escape_xml_string(group->get_path()) << "'";
4783
4784 if (!group->get_architecture_name().empty() && ctxt.get_write_architecture())
4785 out << " architecture='" << group->get_architecture_name()<< "'";
4786
4787 write_tracking_non_reachable_types(group, out);
4788
4789 if (group->is_empty())
4790 {
4791 out << "/>\n";
4792 return true;
4793 }
4794
4795 out << ">\n";
4796
4797 // Write the list of corpora
4798 for (corpus_group::corpora_type::const_iterator c =
4799 group->get_corpora().begin();
4800 c != group->get_corpora().end();
4801 ++c)
4802 {
4803 ABG_ASSERT(!ctxt.corpus_is_emitted(*c));
4804 write_corpus(ctxt, *c, get_indent_to_level(ctxt, indent, 1), true);
4805 }
4806
4807 do_indent_to_level(ctxt, indent, 0);
4808 out << "</abi-corpus-group>\n";
4809
4810 return true;
4811}
4812
4813} //end namespace xml_writer
4814
4815// <Debugging routines>
4816
4817using namespace abigail::ir;
4818
4819/// Serialize a pointer to decl_base to an output stream.
4820///
4821/// @param d the pointer to decl_base to serialize.
4822///
4823/// @param o the output stream to consider.
4824///
4825/// @param annotate whether ABIXML output should be annotated.
4826void
4827dump(const decl_base_sptr d, std::ostream& o, const bool annotate)
4828{
4829 xml_writer::write_context ctxt(d->get_environment(), o);
4831 write_decl(d, ctxt, /*indent=*/0);
4832}
4833
4834/// Serialize a pointer to decl_base to stderr.
4835///
4836/// @param d the pointer to decl_base to serialize.
4837///
4838/// @param annotate whether ABIXML output should be annotated.
4839void
4840dump(const decl_base_sptr d, const bool annotate)
4841{dump(d, cerr, annotate);}
4842
4843/// Serialize a pointer to type_base to an output stream.
4844///
4845/// @param t the pointer to type_base to serialize.
4846///
4847/// @param o the output stream to serialize the @ref type_base to.
4848///
4849/// @param annotate whether ABIXML output should be annotated.
4850void
4851dump(const type_base_sptr t, std::ostream& o, const bool annotate)
4853
4854/// Serialize a pointer to type_base to stderr.
4855///
4856/// @param t the pointer to type_base to serialize.
4857///
4858/// @param annotate whether ABIXML output should be annotated.
4859void
4860dump(const type_base_sptr t, const bool annotate)
4861{dump(t, cerr, annotate);}
4862
4863/// Serialize a pointer to var_decl to an output stream.
4864///
4865/// @param v the pointer to var_decl to serialize.
4866///
4867/// @param o the output stream to serialize the @ref var_decl to.
4868///
4869/// @param annotate whether ABIXML output should be annotated.
4870void
4871dump(const var_decl_sptr v, std::ostream& o, const bool annotate)
4872{
4873 xml_writer::write_context ctxt(v->get_environment(), o);
4875 write_var_decl(v, ctxt, /*linkage_name*/true, /*indent=*/0);
4876}
4877
4878/// Serialize a pointer to var_decl to stderr.
4879///
4880/// @param v the pointer to var_decl to serialize.
4881///
4882/// @param annotate whether ABIXML output should be annotated.
4883void
4884dump(const var_decl_sptr v, const bool annotate)
4885{dump(v, cerr, annotate);}
4886
4887/// Serialize a @ref translation_unit to an output stream.
4888///
4889/// @param t the translation_unit to serialize.
4890///
4891/// @param o the outpout stream to serialize the translation_unit to.
4892///
4893/// @param annotate whether ABIXML output should be annotated.
4894void
4895dump(const translation_unit& t, std::ostream& o, const bool annotate)
4896{
4897 xml_writer::write_context ctxt(t.get_environment(), o);
4899 write_translation_unit(ctxt, t, /*indent=*/0);
4900}
4901
4902/// Serialize an instance of @ref translation_unit to stderr.
4903///
4904/// @param t the translation_unit to serialize.
4905void
4906dump(const translation_unit& t, const bool annotate)
4907{dump(t, cerr, annotate);}
4908
4909/// Serialize a pointer to @ref translation_unit to an output stream.
4910///
4911/// @param t the @ref translation_unit_sptr to serialize.
4912///
4913/// @param o the output stream to serialize the translation unit to.
4914///
4915/// @param annotate whether ABIXML output should be annotated.
4916void
4917dump(const translation_unit_sptr t, std::ostream& o, const bool annotate)
4918{
4919 if (t)
4920 dump(*t, o, annotate);
4921}
4922
4923/// Serialize a pointer to @ref translation_unit to stderr.
4924///
4925/// @param t the translation_unit_sptr to serialize.
4926///
4927/// @param annotate whether ABIXML output should be annotated.
4928void
4930{
4931 if (t)
4932 dump(*t, annotate);
4933}
4934
4935/// Serialize a source location to an output stream.
4936///
4937/// @param l the declaration to consider.
4938///
4939/// @param o the output stream to serialize to.
4940void
4941dump_location(const location& l, ostream& o)
4942{
4943 string path;
4944 unsigned line = 0, col = 0;
4945
4946 l.expand(path, line, col);
4947 o << path << ":" << line << "," << col << "\n";
4948}
4949
4950/// Serialize a source location for debugging purposes.
4951///
4952/// The location is serialized to the standard error output stream.
4953///
4954/// @param l the declaration to consider.
4955///
4956void
4958{dump_location(l, cerr);}
4959
4960/// Serialize the source location of a decl to an output stream for
4961/// debugging purposes.
4962///
4963/// @param d the declaration to consider.
4964///
4965/// @param o the output stream to serizalize the location to.
4966void
4967dump_decl_location(const decl_base& d, ostream& o)
4968{dump_location(d.get_location(), o);}
4969
4970/// Serialize the source location of a decl to stderr for debugging
4971/// purposes.
4972///
4973/// @param d the declaration to consider.
4974void
4976{dump_decl_location(d, cerr);}
4977
4978/// Serialize the source location of a dcl to stderr for debugging
4979/// purposes.
4980///
4981/// @param d the declaration to consider.
4982void
4984{
4985 if (d)
4987}
4988
4989/// Serialize the source location of a decl to stderr for debugging
4990/// purposes.
4991///
4992/// @param d the declaration to consider.
4993void
4994dump_decl_location(const decl_base_sptr d)
4995{dump_decl_location(d.get());}
4996
4997#ifdef WITH_DEBUG_SELF_COMPARISON
4998/// Write one of the records of the "type-ids" debugging file.
4999///
5000/// This is a sub-routine of write_canonical_type_ids.
5001///
5002/// @param ctxt the context to use.
5003///
5004/// @param type the type which canonical type pointer value to emit.
5005///
5006/// @param o the output stream to write to.
5007static void
5008write_type_record(xml_writer::write_context& ctxt,
5009 const type_base* type,
5010 ostream& o)
5011{
5012 // We want to serialize a type record which content looks like:
5013 //
5014 // <type>
5015 // <id>type-id-573</id>
5016 // <c>0x262ee28</c>
5017 // </type>
5018 // <type>
5019 // <id>type-id-569</id>
5020 // <c>0x2628298</c>
5021 // </type>
5022 // <type>
5023 // <id>type-id-575</id>
5024 // <c>0x25f9ba8</c>
5025 // </type>
5026
5027 type_base* canonical = type->get_naked_canonical_type();
5028 string id ;
5029 if (canonical)
5030 {
5031 id = ctxt.get_id_for_type (const_cast<type_base*>(type));
5032
5033 o << " <type>\n"
5034 << " <id>" << id << "</id>\n"
5035 << " <c>"
5036 << std::hex
5037 << reinterpret_cast<uintptr_t>(canonical)
5038 << "</c>\n"
5039 << " </type>\n";
5040 }
5041}
5042
5043/// Serialize the map that is stored at
5044/// environment::get_type_id_canonical_type_map() to an output stream.
5045///
5046/// This is for debugging purposes and is triggered ultimately by
5047/// invoking the command 'abidw --debug-abidiff <binary>'.
5048///
5049/// @param ctxt the write context.
5050///
5051/// @param o the output stream to serialize the map to.
5052void
5053write_canonical_type_ids(xml_writer::write_context& ctxt, ostream& o)
5054{
5055 // We want to serialize a file which content looks like:
5056 //
5057 // <abixml-types-check>
5058 // <type>
5059 // <id>type-id-573</id>
5060 // <c>0x262ee28</c>
5061 // </type>
5062 // <type>
5063 // <id>type-id-569</id>
5064 // <c>0x2628298</c>
5065 // </type>
5066 // <type>
5067 // <id>type-id-575</id>
5068 // <c>0x25f9ba8</c>
5069 // </type>
5070 // <abixml-types-check>
5071
5072 o << "<abixml-types-check>\n";
5073
5074 for (const auto &type : ctxt.get_emitted_types_set())
5075 write_type_record(ctxt, type, o);
5076
5077 o << "</abixml-types-check>\n";
5078}
5079
5080/// Serialize the map that is stored at
5081/// environment::get_type_id_canonical_type_map() to a file.
5082///
5083/// This is for debugging purposes and is triggered ultimately by
5084/// invoking the command 'abidw --debug-abidiff <binary>'.
5085///
5086/// @param ctxt the write context.
5087///
5088/// @param file_path the file to serialize the map to.
5089bool
5090write_canonical_type_ids(xml_writer::write_context& ctxt,
5091 const string &file_path)
5092{
5093 std:: ofstream o (file_path);
5094
5095 if (!o.is_open())
5096 return true;
5097 write_canonical_type_ids(ctxt, o);
5098 o.close();
5099 return true;
5100}
5101#endif
5102// </Debugging routines>
5103} //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:1695
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:2537
shared_ptr< base_spec > base_spec_sptr
Convenience typedef.
Definition: abg-ir.h:4246
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:1160
const vector< string > & get_needed() const
Getter of the needed property of the corpus.
Definition: abg-corpus.cc:990
virtual const string_elf_symbols_map_type & get_var_symbol_map() const
Getter for the variable symbols map.
Definition: abg-corpus.cc:1176
virtual const elf_symbols & get_sorted_fun_symbols() const
Return a sorted vector of function symbols for this corpus.
Definition: abg-corpus.cc:1140
const string & get_soname()
Getter for the soname property of the corpus.
Definition: abg-corpus.cc:1013
const translation_units & get_translation_units() const
Return the list of translation units of the current corpus.
Definition: abg-corpus.cc:729
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:1059
string & get_path() const
Get the file path associated to the corpus file.
Definition: abg-corpus.cc:967
virtual const string_elf_symbols_map_type & get_fun_symbol_map() const
Getter for the function symbols map.
Definition: abg-corpus.cc:1119
const string & get_architecture_name() const
Getter for the architecture name of the corpus.
Definition: abg-corpus.cc:1035
The base type of all declarations.
Definition: abg-ir.h:1538
const location & get_location() const
Get the location of a given declaration.
Definition: abg-ir.cc:4838
binding
ELF binding.
Definition: abg-ir.h:1589
visibility
ELF visibility.
Definition: abg-ir.h:1579
Abstraction of an elf symbol.
Definition: abg-ir.h:923
binding
The binding of a symbol.
Definition: abg-ir.h:940
type
The type of a symbol.
Definition: abg-ir.h:927
visibility
The visibility of the symbol.
Definition: abg-ir.h:949
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:3876
shared_ptr< parameter > parameter_sptr
Convenience typedef for a shared pointer on a function_decl::parameter.
Definition: abg-ir.h:3135
Abstraction of a function type.
Definition: abg-ir.h:3387
type_base_sptr get_return_type() const
Getter for the return type of the current instance of function_type.
Definition: abg-ir.cc:21244
parameters::const_iterator get_first_non_implicit_parm() const
Get the first parameter of the function.
Definition: abg-ir.cc:21529
const parameters & get_parameters() const
Getter for the set of parameters of the current intance of function_type.
Definition: abg-ir.cc:21261
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:462
A declaration that introduces a scope.
Definition: abg-ir.h:1809
std::vector< decl_base_sptr > declarations
Convenience typedef for a vector of decl_base_sptr.
Definition: abg-ir.h:1816
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:7924
This is the abstraction of the set of relevant artefacts (types, variable declarations,...
Definition: abg-ir.h:686
char get_address_size() const
Getter of the address size in this translation unit.
Definition: abg-ir.cc:1475
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:1378
const scope_decl_sptr & get_global_scope() const
Getter of the the global scope of the translation unit.
Definition: abg-ir.cc:1277
bool is_empty() const
Tests whether if the current translation unit contains ABI artifacts or not.
Definition: abg-ir.cc:1464
const std::string & get_path() const
Get the path of the current translation unit.
Definition: abg-ir.cc:1354
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:1320
const environment & get_environment() const
Getter of the environment of the current translation_unit.
Definition: abg-ir.cc:1327
language get_language() const
Getter of the language of the source code of the translation unit.
Definition: abg-ir.cc:1334
An abstraction helper for type declarations.
Definition: abg-ir.h:1973
const interned_string & get_cached_pretty_representation(bool internal=false) const
Get the pretty representation of the current type.
Definition: abg-ir.cc:15916
type_base * get_naked_canonical_type() const
Getter of the canonical type pointer.
Definition: abg-ir.cc:15899
const environment & get_environment() const
Getter of the environment of the current ABI artifact.
Definition: abg-ir.cc:4415
The abstraction of a typedef declaration.
Definition: abg-ir.h:2889
type_base_sptr get_underlying_type() const
Getter of the underlying type of the typedef.
Definition: abg-ir.cc:20488
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:327
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:27808
bool get_member_function_is_dtor(const function_decl &f)
Test whether a member function is a destructor.
Definition: abg-ir.cc:6620
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:5809
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:879
shared_ptr< class_tdecl > class_tdecl_sptr
Convenience typedef for a shared pointer on a class_tdecl.
Definition: abg-fwd.h:286
ssize_t get_member_function_vtable_offset(const function_decl &f)
Get the vtable offset of a member function.
Definition: abg-ir.cc:6744
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:10541
string translation_unit_language_to_string(translation_unit::language l)
Converts a translation_unit::language enumerator into a string.
Definition: abg-ir.cc:1596
shared_ptr< elf_symbol > elf_symbol_sptr
A convenience typedef for a shared pointer to elf_symbol.
Definition: abg-ir.h:888
type_base * get_exemplar_type(const type_base *type)
For a given type, return its exemplar type.
Definition: abg-ir.cc:27879
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:10823
shared_ptr< array_type_def > array_type_def_sptr
Convenience typedef for a shared pointer on a array_type_def.
Definition: abg-fwd.h:241
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:9332
std::vector< elf_symbol_sptr > elf_symbols
Convenience typedef for a vector of elf_symbol.
Definition: abg-ir.h:904
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:11736
decl_base_sptr look_through_decl_only(const decl_base &d)
If a decl is decl-only get its definition. Otherwise, just return nil.
Definition: abg-ir.cc:11625
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:11516
typedef_decl_sptr is_typedef(const type_or_decl_base_sptr t)
Test whether a type is a typedef.
Definition: abg-ir.cc:10701
shared_ptr< template_tparameter > template_tparameter_sptr
Convenience typedef for a shared_ptr to template_tparameter.
Definition: abg-fwd.h:324
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:3607
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:896
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:13471
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:10773
shared_ptr< var_decl > var_decl_sptr
Convenience typedef for a shared pointer on a var_decl.
Definition: abg-fwd.h:253
shared_ptr< ptr_to_mbr_type > ptr_to_mbr_type_sptr
Convenience typedef for a shared pointer to a ptr_to_mbr_type.
Definition: abg-fwd.h:236
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:6510
bool get_member_function_is_const(const function_decl &f)
Test whether a member function is const.
Definition: abg-ir.cc:6676
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:6534
bool is_member_type(const type_base_sptr &t)
Tests if a type is a class member.
Definition: abg-ir.cc:5698
access_specifier get_member_access_specifier(const decl_base &d)
Gets the access specifier for a class member.
Definition: abg-ir.cc:5749
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:6350
bool get_member_function_is_virtual(const function_decl &f)
Test if a given member function is virtual.
Definition: abg-ir.cc:6807
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:11576
bool is_union_type(const type_or_decl_base &t)
Test if a type is a union_decl.
Definition: abg-ir.cc:11103
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:7180
bool is_global_scope(const scope_decl &scope)
Tests whether if a given scope is the global scope.
Definition: abg-ir.cc:10286
bool is_data_member(const var_decl &v)
Test if a var_decl is a data member.
Definition: abg-ir.cc:5847
const decl_base * get_type_declaration(const type_base *t)
Get the declaration for a given type.
Definition: abg-ir.cc:10174
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:281
string demangle_cplus_mangled_name(const string &mangled_name)
Demangle a C++ mangled name and return the resulting string.
Definition: abg-ir.cc:15086
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:8885
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:11546
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:11606
shared_ptr< function_tdecl > function_tdecl_sptr
Convenience typedef for a shared pointer on a function_tdecl.
Definition: abg-fwd.h:291
bool get_member_function_is_ctor(const function_decl &f)
Test whether a member function is a constructor.
Definition: abg-ir.cc:6561
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:2231
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:2143
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:2243
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:1232
void set_ostream(write_context &ctxt, ostream &os)
Set the new ostream.
Definition: abg-writer.cc:2183
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:4766
void set_annotate(write_context &ctxt, bool flag)
Set the 'annotate' flag.
Definition: abg-writer.cc:2172
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:2476
void set_write_default_sizes(write_context &ctxt, bool flag)
Set the 'default-sizes' flag.
Definition: abg-writer.cc:2270
void set_write_elf_needed(write_context &ctxt, bool flag)
Set the 'elf-needed' flag.
Definition: abg-writer.cc:2255
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:4647
void set_write_corpus_path(write_context &ctxt, bool flag)
Set the 'write-corpus-path' flag.
Definition: abg-writer.cc:2207
void set_write_architecture(write_context &ctxt, bool flag)
Set the 'write-architecture' flag.
Definition: abg-writer.cc:2195
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:2160
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:2281
void set_write_comp_dir(write_context &ctxt, bool flag)
Set the 'write-comp-dir' flag.
Definition: abg-writer.cc:2219
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:4827
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:4967
void dump_location(const location &l, ostream &o)
Serialize a source location to an output stream.
Definition: abg-writer.cc:4941
A deleter for shared pointers that ... doesn't delete the object managed by the shared pointer.
Datum consolidating style preferences.