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