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