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