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