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