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