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