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