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