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