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