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