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