libabigail
abg-reader.cc
Go to the documentation of this file.
1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- mode: C++ -*-
3 //
4 // Copyright (C) 2013-2023 Red Hat, Inc.
5 
6 /// @file
7 ///
8 /// This file contains the definitions of the entry points to
9 /// de-serialize an instance of @ref abigail::translation_unit from 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 <libxml/xmlreader.h>
16 #include <libxml/xmlstring.h>
17 #include <cerrno>
18 #include <cstdlib>
19 #include <cstring>
20 #include <deque>
21 #include <memory>
22 #include <sstream>
23 #include <unordered_map>
24 
25 #include "abg-suppression-priv.h"
26 
27 #include "abg-internal.h"
28 #include "abg-symtab-reader.h"
29 
30 // <headers defining libabigail's API go under here>
31 ABG_BEGIN_EXPORT_DECLARATIONS
32 
33 #include "abg-libxml-utils.h"
34 #include "abg-reader.h"
35 #include "abg-corpus.h"
36 #include "abg-fe-iface.h"
37 #include "abg-tools-utils.h"
38 
39 ABG_END_EXPORT_DECLARATIONS
40 // </headers defining libabigail's API>
41 
42 namespace abigail
43 {
44 
45 using xml::xml_char_sptr;
46 
47 /// The namespace for the native XML file format reader.
48 namespace abixml
49 {
50 using std::string;
51 using std::deque;
52 using std::shared_ptr;
53 using std::unordered_map;
54 using std::dynamic_pointer_cast;
55 using std::vector;
56 using std::istream;
57 
58 class reader;
59 
60 static bool read_is_declaration_only(xmlNodePtr, bool&);
61 static bool read_is_artificial(xmlNodePtr, bool&);
62 static bool read_tracking_non_reachable_types(xmlNodePtr, bool&);
63 static bool read_is_non_reachable_type(xmlNodePtr, bool&);
64 static bool read_naming_typedef_id_string(xmlNodePtr, string&);
65 #ifdef WITH_DEBUG_SELF_COMPARISON
66 static bool read_type_id_string(xmlNodePtr, string&);
67 static bool maybe_map_type_with_type_id(const type_base_sptr&,
68  xmlNodePtr);
69 static bool maybe_map_type_with_type_id(const type_base_sptr&,
70  const string&);
71 
72 #define MAYBE_MAP_TYPE_WITH_TYPE_ID(type, xml_node) \
73  maybe_map_type_with_type_id(type, xml_node)
74 #else
75 #define MAYBE_MAP_TYPE_WITH_TYPE_ID(type, xml_node)
76 #endif
77 static void maybe_set_naming_typedef(reader& rdr,
78  xmlNodePtr,
79  const decl_base_sptr &);
80 class reader;
81 
82 static int advance_cursor(reader& rdr);
83 
84 static void
85 handle_version_attribute(xml::reader_sptr& reader, corpus& corp);
86 
87 static void
88 walk_xml_node_to_map_type_ids(reader& rdr, xmlNodePtr node);
89 
90 static bool
91 read_elf_needed_from_input(reader& rdr, vector<string>& needed);
92 
93 static bool
94 read_symbol_db_from_input(reader& rdr,
96  string_elf_symbols_map_sptr& var_symdb);
97 
99 read_translation_unit_from_input(fe_iface& rdr);
100 
101 /// The ABIXML reader object.
102 ///
103 /// This abstracts the context in which the current ABI
104 /// instrumentation dump is being de-serialized. It carries useful
105 /// information needed during the de-serialization, but that does not
106 /// make sense to be stored in the final resulting in-memory
107 /// representation of ABI Corpus.
108 class reader : public fe_iface
109 {
110 public:
111 
112  typedef unordered_map<string,
113  vector<type_base_sptr> >::const_iterator
114  const_types_map_it;
115 
116  typedef unordered_map<string,
117  vector<type_base_sptr> >::iterator
118  types_map_it;
119 
120  typedef unordered_map<string,
121  shared_ptr<function_tdecl> >::const_iterator
122  const_fn_tmpl_map_it;
123 
124  typedef unordered_map<string,
125  shared_ptr<class_tdecl> >::const_iterator
126  const_class_tmpl_map_it;
127 
128  typedef unordered_map<string, xmlNodePtr> string_xml_node_map;
129 
130  typedef unordered_map<xmlNodePtr, decl_base_sptr> xml_node_decl_base_sptr_map;
131 
132  friend vector<type_base_sptr>* get_types_from_type_id(reader&,
133  const string&);
134 
135  friend unordered_map<type_or_decl_base*, vector<type_or_decl_base*>>*
136  get_artifact_used_by_relation_map(reader& rdr);
137 
138 private:
139  unordered_map<string, vector<type_base_sptr> > m_types_map;
140  unordered_map<string, shared_ptr<function_tdecl> > m_fn_tmpl_map;
141  unordered_map<string, shared_ptr<class_tdecl> > m_class_tmpl_map;
142  vector<type_base_sptr> m_types_to_canonicalize;
143  string_xml_node_map m_id_xml_node_map;
144  xml_node_decl_base_sptr_map m_xml_node_decl_map;
145  xml::reader_sptr m_reader;
146  xmlNodePtr m_corp_node;
147  deque<shared_ptr<decl_base> > m_decls_stack;
148  bool m_tracking_non_reachable_types;
149  bool m_drop_undefined_syms;
150 #ifdef WITH_SHOW_TYPE_USE_IN_ABILINT
151  unordered_map<type_or_decl_base*,
152  vector<type_or_decl_base*>> m_artifact_used_by_map;
153 #endif
154 
155  reader();
156 
157 public:
158  reader(xml::reader_sptr reader,
159  environment& env)
160  : fe_iface("", env),
161  m_reader(reader),
162  m_corp_node(),
163  m_tracking_non_reachable_types(),
164  m_drop_undefined_syms()
165  {
166  }
167 
168  /// Test if logging was requested.
169  ///
170  /// @return true iff logging was requested.
171  bool
172  do_log() const
173  {return options().do_log;}
174 
175  /// Getter for the flag that tells us if we are tracking types that
176  /// are not reachable from global functions and variables.
177  ///
178  /// @return true iff we are tracking types that are not reachable
179  /// from global functions and variables.
180  bool
181  tracking_non_reachable_types() const
182  {return m_tracking_non_reachable_types;}
183 
184  /// Setter for the flag that tells us if we are tracking types that
185  /// are not reachable from global functions and variables.
186  ///
187  /// @param f the new value of the flag.
188  /// from global functions and variables.
189  void
190  tracking_non_reachable_types(bool f)
191  {m_tracking_non_reachable_types = f;}
192 
193  /// Getter for the flag that tells us if we are dropping functions
194  /// and variables that have undefined symbols.
195  ///
196  /// @return true iff we are dropping functions and variables that have
197  /// undefined symbols.
198  bool
199  drop_undefined_syms() const
200  {return m_drop_undefined_syms;}
201 
202  /// Setter for the flag that tells us if we are dropping functions
203  /// and variables that have undefined symbols.
204  ///
205  /// @param f the new value of the flag.
206  void
207  drop_undefined_syms(bool f)
208  {m_drop_undefined_syms = f;}
209 
210  /// Getter of the path to the ABI file.
211  ///
212  /// @return the path to the native xml abi file.
213  const string&
214  get_path() const
215  {return corpus_path();}
216 
217  /// Setter of the path to the ABI file.
218  ///
219  /// @param the new path to the native ABI file.
220  void
221  set_path(const string& s)
222  {
223  corpus_path(s);
224  }
225 
226  /// Getter for the environment of this reader.
227  ///
228  /// @return the environment of this reader.
229  environment&
230  get_environment()
231  {return options().env;}
232 
233  /// Getter for the environment of this reader.
234  ///
235  /// @return the environment of this reader.
236  const environment&
237  get_environment() const
238  {return const_cast<reader*>(this)->get_environment();}
239 
241  get_libxml_reader() const
242  {return m_reader;}
243 
244  /// Getter of the current XML node in the corpus element sub-tree
245  /// that needs to be processed.
246  ///
247  /// @return the current XML node in the corpus element sub-tree that
248  /// needs to be processed.
249  xmlNodePtr
250  get_corpus_node() const
251  {return m_corp_node;}
252 
253  /// Setter of the current XML node in the corpus element sub-tree
254  /// that needs to be processed.
255  ///
256  /// @param node set the current XML node in the corpus element
257  /// sub-tree that needs to be processed.
258  void
259  set_corpus_node(xmlNodePtr node)
260  {m_corp_node = node;}
261 
262  const string_xml_node_map&
263  get_id_xml_node_map() const
264  {return m_id_xml_node_map;}
265 
266  string_xml_node_map&
267  get_id_xml_node_map()
268  {return m_id_xml_node_map;}
269 
270  void
271  clear_id_xml_node_map()
272  {get_id_xml_node_map().clear();}
273 
274  const xml_node_decl_base_sptr_map&
275  get_xml_node_decl_map() const
276  {return m_xml_node_decl_map;}
277 
278  xml_node_decl_base_sptr_map&
279  get_xml_node_decl_map()
280  {return m_xml_node_decl_map;}
281 
282  void
283  map_xml_node_to_decl(xmlNodePtr node,
284  decl_base_sptr decl)
285  {
286  if (node)
287  get_xml_node_decl_map()[node]= decl;
288  }
289 
290  decl_base_sptr
291  get_decl_for_xml_node(xmlNodePtr node) const
292  {
293  xml_node_decl_base_sptr_map::const_iterator i =
294  get_xml_node_decl_map().find(node);
295 
296  if (i != get_xml_node_decl_map().end())
297  return i->second;
298 
299  return decl_base_sptr();
300  }
301 
302  void
303  clear_xml_node_decl_map()
304  {get_xml_node_decl_map().clear();}
305 
306  void
307  map_id_and_node (const string& id,
308  xmlNodePtr node)
309  {
310  if (!node)
311  return;
312 
313  string_xml_node_map::iterator i = get_id_xml_node_map().find(id);
314  if (i != get_id_xml_node_map().end())
315  {
316  bool is_declaration = false;
317  read_is_declaration_only(node, is_declaration);
318  if (is_declaration)
319  i->second = node;
320  }
321  else
322  get_id_xml_node_map()[id] = node;
323  }
324 
325  xmlNodePtr
326  get_xml_node_from_id(const string& id) const
327  {
328  string_xml_node_map::const_iterator i = get_id_xml_node_map().find(id);
329  if (i != get_id_xml_node_map().end())
330  return i->second;
331  return 0;
332  }
333 
335  get_scope_for_node(xmlNodePtr node,
336  access_specifier& access);
337 
338  // This is defined later, after build_type() is declared, because it
339  // uses it.
340  type_base_sptr
341  build_or_get_type_decl(const string& id,
342  bool add_decl_to_scope);
343 
344  /// Return the first type already seen, that is identified by a
345  /// given ID.
346  ///
347  /// Note that for a type to be "identified" by id, the function
348  /// key_type_decl must have been previously called with that type
349  /// and with id.
350  ///
351  /// @param id the id to consider.
352  ///
353  /// @return the type identified by the unique id id, or a null
354  /// pointer if no type has ever been associated with id before.
355  type_base_sptr
356  get_type_decl(const string& id) const
357  {
358  const_types_map_it i = m_types_map.find(id);
359  if (i == m_types_map.end())
360  return type_base_sptr();
361  type_base_sptr result = i->second[0];
362  return result;
363  }
364 
365  /// Return the vector of types already seen, that are identified by
366  /// a given ID.
367  ///
368  /// Note that for a type to be "identified" by id, the function
369  /// key_type_decl must have been previously called with that type
370  /// and with id.
371  ///
372  /// @param id the id to consider.
373  ///
374  /// @return thevector of types already seen, that are identified by
375  /// a given ID, or 0 if no type has ever been associated with @p id
376  /// before.
377  const vector<type_base_sptr>*
378  get_all_type_decls(const string& id) const
379  {
380  const_types_map_it i = m_types_map.find(id);
381  if (i == m_types_map.end())
382  return 0;
383  else
384  return &i->second;
385  }
386 
387  /// Return the function template that is identified by a unique ID.
388  ///
389  /// Note that for a function template to be identified by id, the
390  /// function key_fn_tmpl_decl must have been previously called with
391  /// that function template and with id.
392  ///
393  /// @param id the ID to consider.
394  ///
395  /// @return the function template identified by id, or a null
396  /// pointer if no function template has ever been associated with
397  /// id before.
398  shared_ptr<function_tdecl>
399  get_fn_tmpl_decl(const string& id) const
400  {
401  const_fn_tmpl_map_it i = m_fn_tmpl_map.find(id);
402  if (i == m_fn_tmpl_map.end())
403  return shared_ptr<function_tdecl>();
404  return i->second;
405  }
406 
407  /// Return the class template that is identified by a unique ID.
408  ///
409  /// Note that for a class template to be identified by id, the
410  /// function key_class_tmpl_decl must have been previously called
411  /// with that class template and with id.
412  ///
413  /// @param id the ID to consider.
414  ///
415  /// @return the class template identified by id, or a null pointer
416  /// if no class template has ever been associated with id before.
417  shared_ptr<class_tdecl>
418  get_class_tmpl_decl(const string& id) const
419  {
420  const_class_tmpl_map_it i = m_class_tmpl_map.find(id);
421  if (i == m_class_tmpl_map.end())
422  return shared_ptr<class_tdecl>();
423  return i->second;
424  }
425 
426  /// Return the current lexical scope.
427  scope_decl*
428  get_cur_scope() const
429  {
430  shared_ptr<decl_base> cur_decl = get_cur_decl();
431 
432  if (dynamic_cast<scope_decl*>(cur_decl.get()))
433  // The current decl is a scope_decl, so it's our lexical scope.
434  return dynamic_pointer_cast<scope_decl>(cur_decl).get();
435  else if (cur_decl)
436  // The current decl is not a scope_decl, so our lexical scope is
437  // the scope of this decl.
438  return cur_decl->get_scope();
439  else
440  // We have no scope set.
441  return 0;
442  }
443 
444  decl_base_sptr
445  get_cur_decl() const
446  {
447  if (m_decls_stack.empty())
448  return shared_ptr<decl_base>(static_cast<decl_base*>(0));
449  return m_decls_stack.back();
450  }
451 
454  {
455  const global_scope* global = 0;
456  for (deque<shared_ptr<decl_base> >::reverse_iterator i =
457  m_decls_stack.rbegin();
458  i != m_decls_stack.rend();
459  ++i)
460  if (decl_base_sptr d = *i)
461  if ((global = get_global_scope(d)))
462  break;
463 
464  if (global)
465  return global->get_translation_unit();
466 
467  return 0;
468  }
469 
470  /// Test if a given type is from the current translation unit.
471  ///
472  /// @param type the type to consider.
473  ///
474  /// @return true iff the type is from the current translation unit.
475  bool
476  type_is_from_translation_unit(type_base_sptr type)
477  {
478  decl_base_sptr d = get_type_declaration(type);
479  if (d)
481  else if (function_type_sptr fn_type = is_function_type(type))
482  return bool(lookup_function_type(fn_type, *get_translation_unit()));
483  else
484  return false;
485  }
486 
487  void
488  push_decl(decl_base_sptr d)
489  {
490  m_decls_stack.push_back(d);
491  }
492 
493  decl_base_sptr
494  pop_decl()
495  {
496  if (m_decls_stack.empty())
497  return decl_base_sptr();
498 
499  shared_ptr<decl_base> t = get_cur_decl();
500  m_decls_stack.pop_back();
501  return t;
502  }
503 
504  /// Pop all decls until a give scope is popped.
505  ///
506  /// @param scope the scope to pop.
507  ///
508  /// @return true if the scope was popped, false otherwise. Note
509  /// that if the scope wasn't found, it might mean that many other
510  /// decls were popped.
511  bool
512  pop_scope(scope_decl_sptr scope)
513  {
514  decl_base_sptr d;
515  do
516  {
517  d = pop_decl();
518  scope_decl_sptr s = dynamic_pointer_cast<scope_decl>(d);
519  if (s == scope)
520  break;
521  }
522  while (d);
523 
524  if (!d)
525  return false;
526 
527  return dynamic_pointer_cast<scope_decl>(d) == scope;
528  }
529 
530  /// like @ref pop_scope, but if the scope couldn't be popped, the
531  /// function aborts the execution of the process.
532  ///
533  /// @param scope the scope to pop.
534  void
535  pop_scope_or_abort(scope_decl_sptr scope)
536  {ABG_ASSERT(pop_scope(scope));}
537 
538  void
539  clear_decls_stack()
540  {m_decls_stack.clear();}
541 
542  void
543  clear_type_map()
544  {m_types_map.clear();}
545 
546  /// Clean the vector of types to canonicalize after the translation
547  /// unit has been read.
548  void
549  clear_types_to_canonicalize()
550  {m_types_to_canonicalize.clear();}
551 
552 
553  /// Test if two types are equal, without comparing them structurally.
554  ///
555  /// This either tests that type pointers are equal, or it tests
556  /// their names. This is because it might be two early to compare
557  /// types structurally because we are not necessarily done building
558  /// them yet.
559  ///
560  /// @param t1 the first type to compare.
561  ///
562  /// @param t2 the second type to compare.
563  ///
564  /// @return true iff the types are equal.
565  bool
566  types_equal(type_base_sptr t1, type_base_sptr t2)
567  {
568  if (t1.get() == t2.get())
569  return true;
570 
571  // We are going to test qualified names only if both types have
572  // already been added to their scope.
573  bool qualified = (get_type_scope(t1) && get_type_scope(t2));
574 
575  return (get_type_name(t1, qualified)
576  == get_type_name(t2, qualified));
577  }
578 
579  /// Associate an ID with a type.
580  ///
581  /// @param type the type to associate witht he ID.
582  ///
583  /// @param id the ID to associate to the type.
584  ///
585  /// @return true upon successful completion.
586  bool
587  key_type_decl(const type_base_sptr& type, const string& id)
588  {
589  if (!type)
590  return false;
591 
592  m_types_map[id].push_back(type);
593 
594  return true;
595  }
596 
597  /// Associate an ID to a function template.
598  ///
599  /// @param fn_tmpl_decl the function template to consider.
600  ///
601  /// @param id the ID to associate to the function template.
602  ///
603  /// @return true upon successful completion, false otherwise. Note
604  /// that the function returns false if an ID was previously
605  /// associated to the function template.
606  bool
607  key_fn_tmpl_decl(shared_ptr<function_tdecl> fn_tmpl_decl,
608  const string& id)
609  {
610  ABG_ASSERT(fn_tmpl_decl);
611 
612  const_fn_tmpl_map_it i = m_fn_tmpl_map.find(id);
613  if (i != m_fn_tmpl_map.end())
614  return false;
615 
616  m_fn_tmpl_map[id] = fn_tmpl_decl;
617  return true;
618  }
619 
620  /// Associate an ID to a class template.
621  ///
622  /// @param class_tmpl_decl the class template to consider.
623  ///
624  /// @param id the ID to associate to the class template.
625  ///
626  /// @return true upon successful completion, false otherwise. Note
627  /// that the function returns false if an ID was previously
628  /// associated to the class template.
629  bool
630  key_class_tmpl_decl(shared_ptr<class_tdecl> class_tmpl_decl,
631  const string& id)
632  {
633  ABG_ASSERT(class_tmpl_decl);
634 
635  const_class_tmpl_map_it i = m_class_tmpl_map.find(id);
636  if (i != m_class_tmpl_map.end())
637  return false;
638 
639  m_class_tmpl_map[id] = class_tmpl_decl;
640  return true;
641  }
642 
643 #ifdef WITH_SHOW_TYPE_USE_IN_ABILINT
644  /// Record that an artifact is used by another one.
645  ///
646  /// If a type is "used" by another one (as in the type is a sub-type
647  /// of another one), this function records that relation.
648  ///
649  /// @param used the type that is used.
650  ///
651  /// @param user the type that uses @p used.
652  void
653  record_artifact_as_used_by(type_or_decl_base* used,
654  type_or_decl_base* user)
655  {
656  if (m_artifact_used_by_map.find(used) == m_artifact_used_by_map.end())
657  {
658  vector<type_or_decl_base*> v;
659  m_artifact_used_by_map[used] = v;
660  }
661  m_artifact_used_by_map[used].push_back(user);
662  }
663 
664  /// Record that an artifact is used by another one.
665  ///
666  /// If a type is "used" by another one (as in the type is a sub-type
667  /// of another one), this function records that relation.
668  ///
669  /// @param used the type that is used.
670  ///
671  /// @param user the type that uses @p used.
672  void
673  record_artifact_as_used_by(const type_or_decl_base_sptr& used,
674  const type_or_decl_base_sptr& user)
675  {record_artifact_as_used_by(used.get(), user.get());}
676 
677  /// Record the sub-types of a fn-decl as being used by the fn-decl.
678  ///
679  /// @param fn the function decl to consider.
680  void
681  record_artifacts_as_used_in_fn_decl(const function_decl *fn)
682  {
683  if (!fn)
684  return;
685 
686  type_base_sptr t = fn->get_return_type();
687  record_artifact_as_used_by(t.get(), const_cast<function_decl*>(fn));
688 
689  for (auto pit : fn->get_parameters())
690  {
691  type_base_sptr t = pit->get_type();
692  record_artifact_as_used_by(t.get(), const_cast<function_decl*>(fn));
693  }
694  }
695 
696  /// Record the sub-types of a function decl as being used by it.
697  ///
698  /// @param fn the function decl to consider.
699  void
700  record_artifacts_as_used_in_fn_decl(const function_decl_sptr& fn)
701  {record_artifacts_as_used_in_fn_decl(fn.get());}
702 
703  /// Record the sub-types of a function type as being used by it.
704  ///
705  /// @param fn_type the function decl to consider.
706  void
707  record_artifacts_as_used_in_fn_type(const function_type *fn_type)
708  {
709  if (!fn_type)
710  return;
711 
712  type_base_sptr t = fn_type->get_return_type();
713  record_artifact_as_used_by(t.get(), const_cast<function_type*>(fn_type));
714 
715  for (auto pit : fn_type->get_parameters())
716  {
717  type_base_sptr t = pit->get_type();
718  record_artifact_as_used_by(t.get(),
719  const_cast<function_type*>(fn_type));
720  }
721  }
722 
723  /// Record the sub-types of a function type as being used by it.
724  ///
725  /// @param fn_type the function decl to consider.
726  void
727  record_artifacts_as_used_in_fn_type(const function_type_sptr& fn_type)
728  {record_artifacts_as_used_in_fn_type(fn_type.get());}
729 #endif
730 
731  /// This function must be called on each declaration that is created during
732  /// the parsing. It adds the declaration to the current scope, and updates
733  /// the state of the parsing context accordingly.
734  ///
735  /// @param decl the newly created declaration.
736  void
737  push_decl_to_current_scope(decl_base_sptr decl,
738  bool add_to_current_scope)
739  {
740  ABG_ASSERT(decl);
741 
742  if (add_to_current_scope)
743  add_decl_to_scope(decl, get_cur_scope());
744  if (!decl->get_translation_unit())
745  decl->set_translation_unit(get_translation_unit());
746  ABG_ASSERT(decl->get_translation_unit());
747  push_decl(decl);
748  }
749 
750  /// This function must be called on each type decl that is created
751  /// during the parsing. It adds the type decl to the current scope
752  /// and associates a unique ID to it.
753  ///
754  /// @param t type_decl
755  ///
756  /// @param id the unique ID to be associated to t
757  ///
758  /// @return true upon successful completion.
759  ///
760  bool
761  push_and_key_type_decl(shared_ptr<type_base> t, const string& id,
762  bool add_to_current_scope)
763  {
764  shared_ptr<decl_base> decl = dynamic_pointer_cast<decl_base>(t);
765  ABG_ASSERT(decl);
766 
767  push_decl_to_current_scope(decl, add_to_current_scope);
768  if (!t->get_translation_unit())
769  t->set_translation_unit(get_translation_unit());
770  ABG_ASSERT(t->get_translation_unit());
771  key_type_decl(t, id);
772  return true;
773  }
774 
775  /// Getter for the object that determines if a given declaration
776  /// ought to be put in the set of exported decls of the current
777  /// corpus.
778  ///
779  /// @return the exported decls builder.
781  get_exported_decls_builder()
782  {return corpus()->get_exported_decls_builder().get();}
783 
784  /// Test if there are suppression specifications (associated to the
785  /// current corpus) that match a given SONAME or file name.
786  ///
787  /// @param soname the SONAME to consider.
788  ///
789  /// @param the file name to consider.
790  ///
791  /// @return true iff there are suppression specifications (associated to the
792  /// current corpus) that match the SONAME denoted by @p soname or
793  /// the file name denoted by @p filename.
794  bool
795  corpus_is_suppressed_by_soname_or_filename(const string& soname,
796  const string& filename)
797  {
801 
802  for (suppressions_type::const_iterator s = suppressions().begin();
803  s != suppressions().end();
804  ++s)
807  *suppr))
808  return true;
809 
810  return false;
811  }
812 
813  /// Clear all the data that must absolutely be cleared at the end of
814  /// the parsing of a translation unit.
815  void
816  clear_per_translation_unit_data()
817  {
818  }
819 
820  /// Clear all the data that must absolutely be cleared at the end of
821  /// the parsing of an ABI corpus.
822  void
823  clear_per_corpus_data()
824  {
825  clear_type_map();
826  clear_types_to_canonicalize();
827  clear_xml_node_decl_map();
828  clear_id_xml_node_map();
829  clear_decls_stack();
830  }
831 
832 #ifdef WITH_DEBUG_SELF_COMPARISON
833  /// Perform a debugging routine for the "self-comparison" mode.
834  ///
835  /// This is done when this command is on:
836  ///
837  /// "abidw --debug-abidiff".
838  ///
839  /// Consider a type 't' built from an XML element from the abixml
840  /// reader and that has just been canonicalized.
841  ///
842  /// This function checks if the canonical type of 't' is the same as
843  /// the canonical type of the type which was saved into the abixml
844  /// with the same "type-id" as the one of 't'.
845  ///
846  /// Note that at abixml saving time, a debugging file was saved on
847  /// disk to record the mapping of canonical type pointers and their
848  /// type-ids. Right before reading the abixml again, that file was
849  /// read again and the mapping was loaded in the map returned by
850  /// environment::get_type_id_canonical_type_map().
851  void
852  maybe_check_abixml_canonical_type_stability(type_base_sptr& t)
853  {
854  if (!get_environment().self_comparison_debug_is_on()
855  || get_environment().get_type_id_canonical_type_map().empty())
856  return ;
857 
858  if (class_decl_sptr c = is_class_type(t))
859  if (odr_is_relevant(*c) && c->get_is_declaration_only())
860  // Declaration-only classes don't have canonical types in
861  // environments where ODR is relevant (like in C++).
862  return;
863 
864  // Let's get the type-id of this type as recorded in the
865  // originating abixml file.
866  string type_id =
867  get_environment().get_type_id_from_pointer(reinterpret_cast<uintptr_t>(t.get()));
868 
869  if (!type_id.empty())
870  {
871  // Now let's get the canonical type that initially led to the
872  // serialization of a type with this type-id, when the abixml
873  // was being serialized.
874  auto j = get_environment().get_type_id_canonical_type_map().find(type_id);
875  if (j == get_environment().get_type_id_canonical_type_map().end())
876  {
877  if (t->get_naked_canonical_type())
878  std::cerr << "error: no type with type-id: '"
879  << type_id
880  << "' could be read back from the typeid file\n";
881  }
882  else if (j->second
883  != reinterpret_cast<uintptr_t>(t->get_canonical_type().get()))
884  // So the canonical type of 't' (at abixml de-serialization
885  // time) is different from the canonical type that led to
886  // the serialization of 't' at abixml serialization time.
887  // Report this because it needs further debugging.
888  std::cerr << "error: canonical type for type '"
889  << t->get_pretty_representation(/*internal=*/true,
890  /*qualified=*/true)
891  << "' of type-id '" << type_id
892  << "' changed from '" << std::hex
893  << j->second << "' to '" << std::hex
894  << reinterpret_cast<uintptr_t>(t->get_canonical_type().get())
895  << std::dec
896  << "'\n";
897  }
898  }
899 #endif
900 
901  /// Test if a type should be canonicalized early. If so,
902  /// canonicalize it right away. Otherwise, schedule it for late
903  /// canonicalizing; that is, schedule it so that it's going to be
904  /// canonicalized when the translation unit is fully read.
905  ///
906  /// @param t the type to consider for canonicalizing.
907  void
908  maybe_canonicalize_type(type_base_sptr t,
909  bool force_delay = false)
910  {
911  if (!t)
912  return;
913 
914  if (t->get_canonical_type())
915  return;
916 
917  // If this class has some non-canonicalized sub type, then wait
918  // for the when we've read all the translation unit to
919  // canonicalize all of its non-canonicalized sub types and then we
920  // can canonicalize this one.
921  //
922  // Also, if this is a declaration-only class, wait for the end of
923  // the translation unit reading so that we have its definition and
924  // then we'll use that for canonicalizing it.
925  if (!force_delay
927  && !is_class_type(t)
928  && !is_union_type(t)
929  // Below are types that *must* be canonicalized only after
930  // they are added to their context; but then this function
931  // might be called to early, before they are actually added to
932  // their context.
933  //
934  // TODO: make sure this function is called after types are
935  // added to their context, so that we can try to
936  // early-canonicalize some of these types, reducing the size
937  // of the set of types to put on the side, waiting for being
938  // canonicalized.
939  && !is_method_type(t)
940  && !is_reference_type(t)
941  && !is_pointer_type(t)
942  && !is_array_type(t)
943  && !is_qualified_type(t)
944  && !is_typedef(t)
945  && !is_enum_type(t)
946  && !is_function_type(t))
947  {
948  canonicalize(t);
949 #ifdef WITH_DEBUG_SELF_COMPARISON
950  maybe_check_abixml_canonical_type_stability(t);
951 #endif
952  }
953  else
954  {
955  // We do not want to try to canonicalize a class type that
956  // hasn't been properly added to its context.
957  if (class_decl_sptr c = is_class_type(t))
958  ABG_ASSERT(c->get_scope());
959 
960  schedule_type_for_late_canonicalizing(t);
961  }
962  }
963 
964  /// Schedule a type for being canonicalized after the current
965  /// translation unit is read.
966  ///
967  /// @param t the type to consider for canonicalization.
968  void
969  schedule_type_for_late_canonicalizing(type_base_sptr t)
970  {m_types_to_canonicalize.push_back(t);}
971 
972  /// Perform the canonicalizing of types that ought to be done after
973  /// the current translation unit is read. This function is called
974  /// when the current corpus is fully built.
975  void
976  perform_late_type_canonicalizing()
977  {
978  for (vector<type_base_sptr>::iterator i = m_types_to_canonicalize.begin();
979  i != m_types_to_canonicalize.end();
980  ++i)
981  {
982  canonicalize(*i);
983 #ifdef WITH_DEBUG_SELF_COMPARISON
984  maybe_check_abixml_canonical_type_stability(*i);
985 #endif
986  }
987  }
988 
989  /// Test whether if a given function suppression matches a function
990  /// designated by a regular expression that describes its name.
991  ///
992  /// @param s the suppression specification to evaluate to see if it
993  /// matches a given function name.
994  ///
995  /// @param fn_name the name of the function of interest. Note that
996  /// this name must be *non* qualified.
997  ///
998  /// @return true iff the suppression specification @p s matches the
999  /// function whose name is @p fn_name.
1000  bool
1001  suppression_matches_function_name(const suppr::function_suppression_sptr& s,
1002  const string& fn_name) const
1003  {
1004  if (!s)
1005  return false;
1006  return suppression_matches_function_name(*s, fn_name);
1007  }
1008 
1009  /// Tests if a suppression specification can match ABI artifacts
1010  /// coming from the ABI corpus being analyzed.
1011  ///
1012  /// This tests if the suppression matches the soname of and binary
1013  /// name of the corpus being analyzed.
1014  ///
1015  /// @param s the suppression specification to consider.
1016  bool
1018  {
1019  corpus_sptr corp = corpus();
1020 
1021  if (!s.priv_->matches_soname(corp->get_soname()))
1023  // The suppression has some SONAME related properties, but
1024  // none of them match the SONAME of the current binary. So
1025  // the suppression cannot match the current binary.
1026  return false;
1027 
1028  if (!s.priv_->matches_binary_name(corp->get_path()))
1030  // The suppression has some file_name related properties, but
1031  // none of them match the file name of the current binary. So
1032  // the suppression cannot match the current binary.
1033  return false;
1034 
1035  return true;
1036  }
1037 
1038  /// Test whether if a given function suppression matches a function
1039  /// designated by a regular expression that describes its name.
1040  ///
1041  /// @param s the suppression specification to evaluate to see if it
1042  /// matches a given function name.
1043  ///
1044  /// @param fn_name the name of the function of interest. Note that
1045  /// this name must be *non* qualified.
1046  ///
1047  /// @return true iff the suppression specification @p s matches the
1048  /// function whose name is @p fn_name.
1049  bool
1050  suppression_matches_function_name(const suppr::function_suppression& s,
1051  const string& fn_name) const
1052  {
1053  if (!s.get_drops_artifact_from_ir()
1054  || !suppression_can_match(s))
1055  return false;
1056 
1057  return suppr::suppression_matches_function_name(s, fn_name);
1058  }
1059 
1060  /// Test if a given type suppression specification matches a type
1061  /// designated by its name and location.
1062  ///
1063  /// @param s the suppression specification to consider.
1064  ///
1065  /// @param type_name the fully qualified type name to consider.
1066  ///
1067  /// @param type_location the type location to consider.
1068  ///
1069  /// @return true iff the type suppression specification matches a
1070  /// type of a given name and location.
1071  bool
1073  const string& type_name,
1074  const location& type_location) const
1075  {
1076  if (!suppression_can_match(s))
1077  return false;
1078 
1080  type_location);
1081  }
1082 
1083  virtual ir::corpus_sptr
1084  read_corpus(fe_iface::status& status)
1085  {
1086  corpus_sptr nil;
1087 
1088  xml::reader_sptr xml_reader = get_libxml_reader();
1089  if (!xml_reader)
1090  return nil;
1091 
1092  // This is to remember to call xmlTextReaderNext if we ever call
1093  // xmlTextReaderExpand.
1094  bool call_reader_next = false;
1095 
1096  xmlNodePtr node = get_corpus_node();
1097  if (!node)
1098  {
1099  // The document must start with the abi-corpus node.
1100  int status = 1;
1101  while (status == 1
1102  && XML_READER_GET_NODE_TYPE(xml_reader) != XML_READER_TYPE_ELEMENT)
1103  status = advance_cursor (*this);
1104 
1105  if (status != 1 || !xmlStrEqual (XML_READER_GET_NODE_NAME(xml_reader).get(),
1106  BAD_CAST("abi-corpus")))
1107  return nil;
1108 
1109 #ifdef WITH_DEBUG_SELF_COMPARISON
1110  if (get_environment().self_comparison_debug_is_on())
1111  get_environment().set_self_comparison_debug_input(corpus());
1112 #endif
1113 
1114  if (!corpus_group())
1115  clear_per_corpus_data();
1116 
1117  ir::corpus& corp = *corpus();
1118 
1119  corp.set_origin(corpus::NATIVE_XML_ORIGIN);
1120 
1121  handle_version_attribute(xml_reader, corp);
1122 
1123  xml::xml_char_sptr path_str = XML_READER_GET_ATTRIBUTE(xml_reader, "path");
1124  string path;
1125 
1126  if (path_str)
1127  {
1128  path = reinterpret_cast<char*>(path_str.get());
1129  corpus_path(path);
1130  corp.set_path(path);
1131  }
1132 
1133  xml::xml_char_sptr architecture_str =
1134  XML_READER_GET_ATTRIBUTE(xml_reader, "architecture");
1135  if (architecture_str)
1137  (reinterpret_cast<char*>(architecture_str.get()));
1138 
1139  xml::xml_char_sptr soname_str =
1140  XML_READER_GET_ATTRIBUTE(xml_reader, "soname");
1141  string soname;
1142 
1143  if (soname_str)
1144  {
1145  soname = reinterpret_cast<char*>(soname_str.get());
1146  dt_soname(soname);
1147  corp.set_soname(soname);
1148  }
1149 
1150  // Apply suppression specifications here to honour:
1151  //
1152  // [suppress_file]
1153  // (soname_regexp
1154  // |soname_not_regexp
1155  // |file_name_regexp
1156  // |file_name_not_regexp) = <soname-or-file-name>
1157  if ((!soname.empty() || !path.empty())
1158  && corpus_is_suppressed_by_soname_or_filename(soname, path))
1159  return nil;
1160 
1161  node = xmlTextReaderExpand(xml_reader.get());
1162  if (!node)
1163  return nil;
1164 
1165  call_reader_next = true;
1166  }
1167  else
1168  {
1169 #ifdef WITH_DEBUG_SELF_COMPARISON
1170  if (get_environment().self_comparison_debug_is_on())
1171  get_environment().set_self_comparison_debug_input(corpus());
1172 #endif
1173 
1174  if (!corpus_group())
1175  clear_per_corpus_data();
1176 
1177  ir::corpus& corp = *corpus();
1178  corp.set_origin(corpus::NATIVE_XML_ORIGIN);
1179 
1180  xml::xml_char_sptr path_str = XML_NODE_GET_ATTRIBUTE(node, "path");
1181  if (path_str)
1182  corp.set_path(reinterpret_cast<char*>(path_str.get()));
1183 
1184  xml::xml_char_sptr architecture_str =
1185  XML_NODE_GET_ATTRIBUTE(node, "architecture");
1186  if (architecture_str)
1188  (reinterpret_cast<char*>(architecture_str.get()));
1189 
1190  xml::xml_char_sptr soname_str =
1191  XML_NODE_GET_ATTRIBUTE(node, "soname");
1192  if (soname_str)
1193  corp.set_soname(reinterpret_cast<char*>(soname_str.get()));
1194  }
1195 
1196  // If the corpus element node has children nodes, make
1197  // get_corpus_node() returns the first child element node of
1198  // the corpus element that *needs* to be processed.
1199  if (node->children)
1200  {
1201  xmlNodePtr n = xmlFirstElementChild(node);
1202  set_corpus_node(n);
1203  }
1204 
1205  ir::corpus& corp = *corpus();
1206 
1207  walk_xml_node_to_map_type_ids(*this, node);
1208 
1209  // Read the needed element
1210  vector<string> needed;
1211  read_elf_needed_from_input(*this, needed);
1212  if (!needed.empty())
1213  corp.set_needed(needed);
1214 
1215  string_elf_symbols_map_sptr fn_sym_db, var_sym_db;
1216 
1217  // Read the symbol databases.
1218  read_symbol_db_from_input(*this, fn_sym_db, var_sym_db);
1219 
1220  // Note that it's possible that both fn_sym_db and var_sym_db are nil,
1221  // due to potential suppression specifications. That's fine.
1222  corp.set_symtab(symtab_reader::symtab::load(fn_sym_db, var_sym_db));
1223 
1224  get_environment().canonicalization_is_done(false);
1225 
1226  // Read the translation units.
1227  while (read_translation_unit_from_input(*this))
1228  ;
1229 
1230  if (tracking_non_reachable_types())
1231  {
1232  bool is_tracking_non_reachable_types = false;
1233  read_tracking_non_reachable_types(node, is_tracking_non_reachable_types);
1234 
1235  ABG_ASSERT
1237  == is_tracking_non_reachable_types);
1238  }
1239 
1240 
1242  if (do_log())
1243  {
1244  std::cerr << "perform late type canonicalization ...\n";
1245  t.start();
1246  }
1247 
1248  perform_late_type_canonicalizing();
1249 
1250  if (do_log())
1251  {
1252  t.stop();
1253  std::cerr << "late type canonicalization DONE@"
1254  << corpus()->get_path()
1255  << ":" << t << "\n";
1256  }
1257 
1258  get_environment().canonicalization_is_done(true);
1259 
1260  if (call_reader_next)
1261  {
1262  // This is the necessary counter-part of the xmlTextReaderExpand()
1263  // call at the beginning of the function.
1264  xmlTextReaderNext(xml_reader.get());
1265  // The call above invalidates the xml node returned by
1266  // xmlTextReaderExpand, which is can still be accessed via
1267  // set_corpus_node.
1268  set_corpus_node(0);
1269  }
1270  else
1271  {
1272  node = get_corpus_node();
1273  node = xmlNextElementSibling(node);
1274  if (!node)
1275  {
1276  node = get_corpus_node();
1277  if (node)
1278  node = xmlNextElementSibling(node->parent);
1279  }
1280  set_corpus_node(node);
1281  }
1282 
1283  status = STATUS_OK;
1284  return corpus();
1285  }
1286 };// end class reader
1287 
1288 typedef shared_ptr<reader> reader_sptr;
1289 
1290 static int advance_cursor(reader&);
1291 static bool read_translation_unit(fe_iface&, translation_unit&, xmlNodePtr);
1292 static translation_unit_sptr get_or_read_and_add_translation_unit(reader&, xmlNodePtr);
1293 static translation_unit_sptr read_translation_unit_from_input(fe_iface&);
1294 static bool read_symbol_db_from_input(reader&,
1297 static bool read_location(const reader&, xmlNodePtr, location&);
1298 static bool read_artificial_location(const reader&,
1299  xmlNodePtr, location&);
1300 static bool maybe_set_artificial_location(const reader&,
1301  xmlNodePtr,
1303 static bool read_visibility(xmlNodePtr, decl_base::visibility&);
1304 static bool read_binding(xmlNodePtr, decl_base::binding&);
1305 static bool read_access(xmlNodePtr, access_specifier&);
1306 static bool read_size_and_alignment(xmlNodePtr, size_t&, size_t&);
1307 static bool read_static(xmlNodePtr, bool&);
1308 static bool read_offset_in_bits(xmlNodePtr, size_t&);
1309 static bool read_cdtor_const(xmlNodePtr, bool&, bool&, bool&);
1310 static bool read_is_virtual(xmlNodePtr, bool&);
1311 static bool read_is_struct(xmlNodePtr, bool&);
1312 static bool read_is_anonymous(xmlNodePtr, bool&);
1313 static bool read_elf_symbol_type(xmlNodePtr, elf_symbol::type&);
1314 static bool read_elf_symbol_binding(xmlNodePtr, elf_symbol::binding&);
1315 static bool read_elf_symbol_visibility(xmlNodePtr,
1317 
1318 static namespace_decl_sptr
1319 build_namespace_decl(reader&, const xmlNodePtr, bool);
1320 
1321 // <build a c++ class from an instance of xmlNodePtr>
1322 //
1323 // Note that whenever a new function to build a type is added here,
1324 // you should make sure to call it from the build_type function, which
1325 // should be the last function of the list of declarated function
1326 // below.
1327 
1328 static elf_symbol_sptr
1329 build_elf_symbol(reader&, const xmlNodePtr, bool);
1330 
1331 static elf_symbol_sptr
1332 build_elf_symbol_from_reference(reader&, const xmlNodePtr);
1333 
1335 build_elf_symbol_db(reader&, const xmlNodePtr, bool);
1336 
1338 build_function_parameter (reader&, const xmlNodePtr);
1339 
1340 static function_decl_sptr
1341 build_function_decl(reader&, const xmlNodePtr,
1342  class_or_union_sptr, bool);
1343 
1344 static function_decl_sptr
1345 build_function_decl_if_not_suppressed(reader&, const xmlNodePtr,
1346  class_or_union_sptr, bool);
1347 
1348 static bool
1349 function_is_suppressed(const reader& rdr,
1350  xmlNodePtr node);
1351 
1352 static var_decl_sptr
1353 build_var_decl_if_not_suppressed(reader&, const xmlNodePtr, bool);
1354 
1355 static var_decl_sptr
1356 build_var_decl(reader&, const xmlNodePtr, bool);
1357 
1358 static bool
1359 variable_is_suppressed(const reader& rdr,
1360  xmlNodePtr node);
1361 
1362 static shared_ptr<type_decl>
1363 build_type_decl(reader&, const xmlNodePtr, bool);
1364 
1365 static qualified_type_def_sptr
1366 build_qualified_type_decl(reader&, const xmlNodePtr, bool);
1367 
1368 static shared_ptr<pointer_type_def>
1369 build_pointer_type_def(reader&, const xmlNodePtr, bool);
1370 
1371 static shared_ptr<reference_type_def>
1372 build_reference_type_def(reader&, const xmlNodePtr, bool);
1373 
1374 static shared_ptr<function_type>
1375 build_function_type(reader&, const xmlNodePtr, bool);
1376 
1378 build_subrange_type(reader&, const xmlNodePtr, bool);
1379 
1380 static array_type_def_sptr
1381 build_array_type_def(reader&, const xmlNodePtr, bool);
1382 
1383 static enum_type_decl_sptr
1384 build_enum_type_decl(reader&, const xmlNodePtr, bool);
1385 
1386 static shared_ptr<typedef_decl>
1387 build_typedef_decl(reader&, const xmlNodePtr, bool);
1388 
1389 static class_decl_sptr
1390 build_class_decl(reader&, const xmlNodePtr, bool);
1391 
1392 static union_decl_sptr
1393 build_union_decl(reader&, const xmlNodePtr, bool);
1394 
1395 static shared_ptr<function_tdecl>
1396 build_function_tdecl(reader&, const xmlNodePtr, bool);
1397 
1398 static shared_ptr<class_tdecl>
1399 build_class_tdecl(reader&, const xmlNodePtr, bool);
1400 
1401 static type_tparameter_sptr
1402 build_type_tparameter(reader&, const xmlNodePtr,
1403  unsigned, template_decl_sptr);
1404 
1405 static type_composition_sptr
1406 build_type_composition(reader&, const xmlNodePtr,
1407  unsigned, template_decl_sptr);
1408 
1410 build_non_type_tparameter(reader&, const xmlNodePtr,
1411  unsigned, template_decl_sptr);
1412 
1414 build_template_tparameter(reader&, const xmlNodePtr,
1415  unsigned, template_decl_sptr);
1416 
1418 build_template_parameter(reader&, const xmlNodePtr,
1419  unsigned, template_decl_sptr);
1420 
1421 // Please make this build_type function be the last one of the list.
1422 // Note that it should call each type-building function above. So
1423 // please make sure to update it accordingly, whenever a new
1424 // type-building function is added here.
1425 static shared_ptr<type_base>
1426 build_type(reader&, const xmlNodePtr, bool);
1427 // </build a c++ class from an instance of xmlNodePtr>
1428 
1429 static type_or_decl_base_sptr handle_element_node(reader&, xmlNodePtr, bool);
1430 static decl_base_sptr handle_type_decl(reader&, xmlNodePtr, bool);
1431 static decl_base_sptr handle_namespace_decl(reader&, xmlNodePtr, bool);
1432 static decl_base_sptr handle_qualified_type_decl(reader&,
1433  xmlNodePtr, bool);
1434 static decl_base_sptr handle_pointer_type_def(reader&,
1435  xmlNodePtr, bool);
1436 static decl_base_sptr handle_reference_type_def(reader&,
1437  xmlNodePtr, bool);
1438 static type_base_sptr handle_function_type(reader&,
1439  xmlNodePtr, bool);
1440 static decl_base_sptr handle_array_type_def(reader&,
1441  xmlNodePtr, bool);
1442 static decl_base_sptr handle_enum_type_decl(reader&, xmlNodePtr, bool);
1443 static decl_base_sptr handle_typedef_decl(reader&, xmlNodePtr, bool);
1444 static decl_base_sptr handle_var_decl(reader&, xmlNodePtr, bool);
1445 static decl_base_sptr handle_function_decl(reader&, xmlNodePtr, bool);
1446 static decl_base_sptr handle_class_decl(reader&, xmlNodePtr, bool);
1447 static decl_base_sptr handle_union_decl(reader&, xmlNodePtr, bool);
1448 static decl_base_sptr handle_function_tdecl(reader&, xmlNodePtr, bool);
1449 static decl_base_sptr handle_class_tdecl(reader&, xmlNodePtr, bool);
1450 
1451 #ifdef WITH_SHOW_TYPE_USE_IN_ABILINT
1452 #define RECORD_ARTIFACT_AS_USED_BY(rdr, used, user) \
1453  rdr.record_artifact_as_used_by(used,user)
1454 #define RECORD_ARTIFACTS_AS_USED_IN_FN_DECL(rdr, fn) \
1455  rdr.record_artifacts_as_used_in_fn_decl(fn)
1456 #define RECORD_ARTIFACTS_AS_USED_IN_FN_TYPE(rdr, fn_type)\
1457  rdr.record_artifacts_as_used_in_fn_type(fn_type)
1458 #else
1459 #define RECORD_ARTIFACT_AS_USED_BY(rdr, used, user)
1460 #define RECORD_ARTIFACTS_AS_USED_IN_FN_DECL(rdr, fn)
1461 #define RECORD_ARTIFACTS_AS_USED_IN_FN_TYPE(rdr, fn_type)
1462 #endif
1463 
1464 /// Get the IR node representing the scope for a given XML node.
1465 ///
1466 /// This function might trigger the building of a full sub-tree of IR.
1467 ///
1468 /// @param node the XML for which to return the scope decl. If its
1469 /// parent XML node has no corresponding IR node, that IR node is constructed.
1470 ///
1471 /// @param access the access specifier of the node in its scope, if
1472 /// applicable. If the node doesn't have any access specifier
1473 /// provided in its scope, then the parameter is set to no_access.
1474 ///
1475 /// @return the IR node representing the scope of the IR node for the
1476 /// XML node given in argument.
1478 reader::get_scope_for_node(xmlNodePtr node,
1479  access_specifier& access)
1480 {
1481  scope_decl_sptr nil, scope;
1482  if (!node)
1483  return nil;
1484 
1485  xmlNodePtr parent = node->parent;
1486  access = no_access;
1487  if (parent
1488  && (xmlStrEqual(parent->name, BAD_CAST("data-member"))
1489  || xmlStrEqual(parent->name, BAD_CAST("member-type"))
1490  || xmlStrEqual(parent->name, BAD_CAST("member-function"))
1491  || xmlStrEqual(parent->name, BAD_CAST("member-template"))
1492  || xmlStrEqual(parent->name, BAD_CAST("array-type-def"))))
1493  {
1494  read_access(parent, access);
1495  parent = parent->parent;
1496  }
1497 
1498  xml_node_decl_base_sptr_map::const_iterator i =
1499  get_xml_node_decl_map().find(parent);
1500  if (i == get_xml_node_decl_map().end())
1501  {
1502  if (xmlStrEqual(parent->name, BAD_CAST("abi-instr")))
1503  {
1505  get_or_read_and_add_translation_unit(*this, parent);
1506  return tu->get_global_scope();
1507  }
1508 
1509  access_specifier a = no_access;
1510  scope_decl_sptr parent_scope = get_scope_for_node(parent, a);
1511  push_decl(parent_scope);
1512  scope = dynamic_pointer_cast<scope_decl>
1513  (handle_element_node(*this, parent, /*add_decl_to_scope=*/true));
1514  ABG_ASSERT(scope);
1515  pop_scope_or_abort(parent_scope);
1516  }
1517  else
1518  scope = dynamic_pointer_cast<scope_decl>(i->second);
1519 
1520  return scope;
1521 }
1522 
1523 /// Get the type declaration IR node that matches a given XML type node ID.
1524 ///
1525 /// If no IR node has been built for this ID, this function builds the
1526 /// type declaration IR node and returns it. Subsequent invocation of
1527 /// this function with this ID will just return that ID previously returned.
1528 ///
1529 /// @param id the XML node ID to consider.
1530 ///
1531 /// @return the type declaration for the ID given in parameter.
1532 type_base_sptr
1533 reader::build_or_get_type_decl(const string& id,
1534  bool add_decl_to_scope)
1535 {
1536  type_base_sptr t = get_type_decl(id);
1537 
1538  if (!t)
1539  {
1540  xmlNodePtr n = get_xml_node_from_id(id);
1541  ABG_ASSERT(n);
1542 
1543  scope_decl_sptr scope;
1544  access_specifier access = no_access;
1545  if (add_decl_to_scope)
1546  {
1547  scope = get_scope_for_node(n, access);
1548  /// In some cases, if for instance the scope of 'n' is a
1549  /// namespace, get_scope_for_node() can trigger the building
1550  /// of what is underneath of the namespace, if that has not
1551  /// already been done. So after that, the IR node for 'n'
1552  /// might have been built; let's try to see if we are in
1553  /// that case. Otherwise, we'll just build the IR node for
1554  /// 'n' ourselves.
1555  if ((t = get_type_decl(id)))
1556  return t;
1557  ABG_ASSERT(scope);
1558  push_decl(scope);
1559  }
1560 
1561  t = build_type(*this, n, add_decl_to_scope);
1562  ABG_ASSERT(t);
1563  if (is_member_type(t) && access != no_access)
1564  {
1566  decl_base_sptr d = get_type_declaration(t);
1567  ABG_ASSERT(d);
1568  set_member_access_specifier(d, access);
1569  }
1570  map_xml_node_to_decl(n, get_type_declaration(t));
1571 
1572  if (add_decl_to_scope)
1573  pop_scope_or_abort(scope);
1574 
1575  maybe_canonicalize_type(t, !add_decl_to_scope);
1576  }
1577  return t;
1578 }
1579 
1580 /// Moves the xmlTextReader cursor to the next xml node in the input
1581 /// document. Return 1 of the parsing was successful, 0 if no input
1582 /// xml token is left, or -1 in case of error.
1583 ///
1584 /// @param rdr the ABIXML reader
1585 ///
1586 static int
1587 advance_cursor(reader& rdr)
1588 {
1589  xml::reader_sptr reader = rdr.get_libxml_reader();
1590  return xmlTextReaderRead(reader.get());
1591 }
1592 
1593 /// Walk an entire XML sub-tree to build a map where the key is the
1594 /// the value of the 'id' attribute (for type definitions) and the value
1595 /// is the xml node containing the 'id' attribute.
1596 ///
1597 /// @param rdr the context of the reader.
1598 ///
1599 /// @param node the XML sub-tree node to walk. It must be an element
1600 /// node.
1601 static void
1602 walk_xml_node_to_map_type_ids(reader& rdr,
1603  xmlNodePtr node)
1604 {
1605  xmlNodePtr n = node;
1606 
1607  if (!n || n->type != XML_ELEMENT_NODE)
1608  return;
1609 
1610  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(n, "id"))
1611  {
1612  string id = CHAR_STR(s);
1613  rdr.map_id_and_node(id, n);
1614  }
1615 
1616  for (n = xmlFirstElementChild(n); n; n = xmlNextElementSibling(n))
1617  walk_xml_node_to_map_type_ids(rdr, n);
1618 }
1619 
1620 static bool
1621 read_translation_unit(fe_iface& iface, translation_unit& tu, xmlNodePtr node)
1622 {
1623  abixml::reader& rdr = dynamic_cast<abixml::reader&>(iface);
1624 
1625  if (!rdr.corpus()->is_empty())
1626  tu.set_corpus(rdr.corpus().get());
1627 
1628  xml::xml_char_sptr addrsize_str =
1629  XML_NODE_GET_ATTRIBUTE(node, "address-size");
1630  if (addrsize_str)
1631  {
1632  char address_size = atoi(reinterpret_cast<char*>(addrsize_str.get()));
1633  tu.set_address_size(address_size);
1634  }
1635 
1636  xml::xml_char_sptr path_str = XML_NODE_GET_ATTRIBUTE(node, "path");
1637  if (path_str)
1638  tu.set_path(reinterpret_cast<char*>(path_str.get()));
1639 
1640  xml::xml_char_sptr comp_dir_path_str =
1641  XML_NODE_GET_ATTRIBUTE(node, "comp-dir-path");
1642  if (comp_dir_path_str)
1643  tu.set_compilation_dir_path(reinterpret_cast<char*>
1644  (comp_dir_path_str.get()));
1645 
1646  xml::xml_char_sptr language_str = XML_NODE_GET_ATTRIBUTE(node, "language");
1647  if (language_str)
1649  (reinterpret_cast<char*>(language_str.get())));
1650 
1651 
1652  // We are at global scope, as we've just seen the top-most
1653  // "abi-instr" element.
1654  rdr.push_decl(tu.get_global_scope());
1655  rdr.map_xml_node_to_decl(node, tu.get_global_scope());
1656 
1657  if (rdr.get_id_xml_node_map().empty()
1658  || !rdr.corpus())
1659  walk_xml_node_to_map_type_ids(rdr, node);
1660 
1661  for (xmlNodePtr n = xmlFirstElementChild(node);
1662  n;
1663  n = xmlNextElementSibling(n))
1664  handle_element_node(rdr, n, /*add_decl_to_scope=*/true);
1665 
1666  rdr.pop_scope_or_abort(tu.get_global_scope());
1667 
1668  xml::reader_sptr reader = rdr.get_libxml_reader();
1669  if (!reader)
1670  return false;
1671 
1672  rdr.clear_per_translation_unit_data();
1673 
1674  return true;
1675 }
1676 
1677 /// Read a given xml node representing a tranlsation unit.
1678 ///
1679 /// If the current corpus already contains a translation unit of the
1680 /// path of the xml node we need to look at, then return that
1681 /// translation unit. Otherwise, read the translation unit, build a
1682 /// @ref translation_unit out of it, add it to the current corpus and
1683 /// return it.
1684 ///
1685 /// @param rdr the ABIXML reader.
1686 ///
1687 /// @param node the XML node to consider.
1688 ///
1689 /// @return the resulting translation unit.
1690 static translation_unit_sptr
1691 get_or_read_and_add_translation_unit(reader& rdr, xmlNodePtr node)
1692 {
1693  corpus_sptr corp = rdr.corpus();
1694 
1696  string tu_path;
1697  xml::xml_char_sptr path_str = XML_NODE_GET_ATTRIBUTE(node, "path");
1698 
1699  if (path_str)
1700  {
1701  tu_path = reinterpret_cast<char*>(path_str.get());
1702  ABG_ASSERT(!tu_path.empty());
1703 
1704  if (corp && !corp->is_empty())
1705  tu = corp->find_translation_unit(tu_path);
1706 
1707  if (tu)
1708  return tu;
1709  }
1710 
1711  tu.reset(new translation_unit(rdr.get_environment(), tu_path));
1712  if (corp && !corp->is_empty())
1713  corp->add(tu);
1714 
1715  if (read_translation_unit(rdr, *tu, node))
1716  return tu;
1717 
1718  return translation_unit_sptr();
1719 }
1720 
1721 /// Parse the input XML document containing a translation_unit,
1722 /// represented by an 'abi-instr' element node, associated to the current
1723 /// context.
1724 ///
1725 /// @param rdr the current input context
1726 ///
1727 /// @return the translation unit resulting from the parsing upon
1728 /// successful completion, or nil.
1729 static translation_unit_sptr
1730 read_translation_unit_from_input(fe_iface& iface)
1731 {
1732  translation_unit_sptr tu, nil;
1733 
1734  abixml::reader& rdr = dynamic_cast<abixml::reader&>(iface);
1735 
1736  xmlNodePtr node = rdr.get_corpus_node();
1737  if (!node)
1738  {
1739  xml::reader_sptr reader = rdr.get_libxml_reader();
1740  if (!reader)
1741  return nil;
1742 
1743  // The document must start with the abi-instr node.
1744  int status = 1;
1745  while (status == 1
1746  && XML_READER_GET_NODE_TYPE(reader) != XML_READER_TYPE_ELEMENT)
1747  status = advance_cursor (rdr);
1748 
1749  if (status != 1 || !xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
1750  BAD_CAST("abi-instr")))
1751  return nil;
1752 
1753  node = xmlTextReaderExpand(reader.get());
1754  if (!node)
1755  return nil;
1756  }
1757  else
1758  {
1759  node = 0;
1760  for (xmlNodePtr n = rdr.get_corpus_node();
1761  n;
1762  n = xmlNextElementSibling(n))
1763  {
1764  if (!xmlStrEqual(n->name, BAD_CAST("abi-instr")))
1765  return nil;
1766  node = n;
1767  break;
1768  }
1769  }
1770 
1771  if (node == 0)
1772  return nil;
1773 
1774  tu = get_or_read_and_add_translation_unit(rdr, node);
1775 
1776  if (rdr.get_corpus_node())
1777  {
1778  // We are not in the mode where the current corpus node came
1779  // from a local invocation of xmlTextReaderExpand. So let's set
1780  // rdr.get_corpus_node to the next child element node of the
1781  // corpus that needs to be processed.
1782  node = xmlNextElementSibling(node);
1783  rdr.set_corpus_node(node);
1784  }
1785 
1786  return tu;
1787 }
1788 
1789 /// Parse the input XML document that may contain function symbol and
1790 /// variable symbol databases.
1791 ///
1792 /// A function symbols database is an XML element named
1793 /// "elf-function-symbols" and a variable symbols database is an XML
1794 /// element named "elf-variable-symbols." They contains "elf-symbol"
1795 /// XML elements.
1796 ///
1797 /// @param rdr the reader to use for the parsing.
1798 ///
1799 /// @param fn_symdb any resulting function symbol database object, if
1800 /// elf-function-symbols was present.
1801 ///
1802 /// @param var_symdb any resulting variable symbol database object, if
1803 /// elf-variable-symbols was present.
1804 ///
1805 /// @return true upon successful parsing, false otherwise.
1806 static bool
1807 read_symbol_db_from_input(reader& rdr,
1808  string_elf_symbols_map_sptr& fn_symdb,
1809  string_elf_symbols_map_sptr& var_symdb)
1810 {
1811  xml::reader_sptr reader = rdr.get_libxml_reader();
1812  if (!reader)
1813  return false;
1814 
1815  if (!rdr.get_corpus_node())
1816  for (;;)
1817  {
1818  int status = 1;
1819  while (status == 1
1820  && XML_READER_GET_NODE_TYPE(reader) != XML_READER_TYPE_ELEMENT)
1821  status = advance_cursor (rdr);
1822 
1823  if (status != 1)
1824  return false;
1825 
1826  bool has_fn_syms = false, has_var_syms = false;
1827  if (xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
1828  BAD_CAST("elf-function-symbols")))
1829  has_fn_syms = true;
1830  else if (xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
1831  BAD_CAST("elf-variable-symbols")))
1832  has_var_syms = true;
1833  else
1834  break;
1835 
1836  xmlNodePtr node = xmlTextReaderExpand(reader.get());
1837  if (!node)
1838  return false;
1839 
1840  if (has_fn_syms)
1841  fn_symdb = build_elf_symbol_db(rdr, node, true);
1842  else if (has_var_syms)
1843  var_symdb = build_elf_symbol_db(rdr, node, false);
1844 
1845  xmlTextReaderNext(reader.get());
1846  }
1847  else
1848  for (xmlNodePtr n = rdr.get_corpus_node(); n; n = xmlNextElementSibling(n))
1849  {
1850  bool has_fn_syms = false, has_var_syms = false;
1851  if (xmlStrEqual(n->name, BAD_CAST("elf-function-symbols")))
1852  has_fn_syms = true;
1853  else if (xmlStrEqual(n->name, BAD_CAST("elf-variable-symbols")))
1854  has_var_syms = true;
1855  else
1856  {
1857  rdr.set_corpus_node(n);
1858  break;
1859  }
1860 
1861  if (has_fn_syms)
1862  fn_symdb = build_elf_symbol_db(rdr, n, true);
1863  else if (has_var_syms)
1864  var_symdb = build_elf_symbol_db(rdr, n, false);
1865  else
1866  break;
1867  }
1868 
1869  return true;
1870 }
1871 
1872 /// From an "elf-needed" XML_ELEMENT node, build a vector of strings
1873 /// representing the vector of the dependencies needed by a given
1874 /// corpus.
1875 ///
1876 /// @param node the XML_ELEMENT node of name "elf-needed".
1877 ///
1878 /// @param needed the output vector of string to populate with the
1879 /// vector of dependency names found on the xml node @p node.
1880 ///
1881 /// @return true upon successful completion, false otherwise.
1882 static bool
1883 build_needed(xmlNode* node, vector<string>& needed)
1884 {
1885  if (!node || !xmlStrEqual(node->name,BAD_CAST("elf-needed")))
1886  return false;
1887 
1888  for (xmlNodePtr n = xmlFirstElementChild(node);
1889  n;
1890  n = xmlNextElementSibling(n))
1891  {
1892  if (!xmlStrEqual(n->name, BAD_CAST("dependency")))
1893  continue;
1894 
1895  string name;
1896  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(n, "name"))
1898 
1899  if (!name.empty())
1900  needed.push_back(name);
1901  }
1902 
1903  return true;
1904 }
1905 
1906 /// Move to the next xml element node and expext it to be named
1907 /// "elf-needed". Then read the sub-tree to made of that node and
1908 /// extracts a vector of needed dependencies name from it.
1909 ///
1910 /// @param rdr the ABIXML reader used to the xml reading.
1911 ///
1912 /// @param needed the resulting vector of dependency names.
1913 ///
1914 /// @return true upon successful completion, false otherwise.
1915 static bool
1916 read_elf_needed_from_input(reader& rdr,
1917  vector<string>& needed)
1918 {
1919  xml::reader_sptr reader = rdr.get_libxml_reader();
1920  if (!reader)
1921  return false;
1922 
1923  xmlNodePtr node = 0;
1924 
1925  if (rdr.get_corpus_node() == 0)
1926  {
1927  int status = 1;
1928  while (status == 1
1929  && XML_READER_GET_NODE_TYPE(reader) != XML_READER_TYPE_ELEMENT)
1930  status = advance_cursor (rdr);
1931 
1932  if (status != 1)
1933  return false;
1934 
1935  if (!xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
1936  BAD_CAST("elf-needed")))
1937  return false;
1938 
1939  node = xmlTextReaderExpand(reader.get());
1940  if (!node)
1941  return false;
1942  }
1943  else
1944  {
1945  for (xmlNodePtr n = rdr.get_corpus_node();
1946  n;
1947  n = xmlNextElementSibling(n))
1948  {
1949  if (!xmlStrEqual(n->name, BAD_CAST("elf-needed")))
1950  return false;
1951  node = n;
1952  break;
1953  }
1954  }
1955 
1956  bool result = false;
1957  if (node)
1958  {
1959  result = build_needed(node, needed);
1960  node = xmlNextElementSibling(node);
1961  rdr.set_corpus_node(node);
1962  }
1963 
1964  return result;
1965 }
1966 
1967 /// Add suppressions specifications to the set of suppressions to be
1968 /// used during the construction of the ABI internal representation
1969 /// (the ABI corpus) from ELF and DWARF.
1970 ///
1971 /// During the construction of the ABI corpus, ABI artifacts that
1972 /// match the a given suppression specification are dropped on the
1973 /// floor; that is, they are discarded and won't be part of the final
1974 /// ABI corpus. This is a way to reduce the amount of data held by
1975 /// the final ABI corpus.
1976 ///
1977 /// Note that the suppression specifications provided to this function
1978 /// are only considered during the construction of the ABI corpus.
1979 /// For instance, they are not taken into account during e.g
1980 /// comparisons of two ABI corpora that might happen later. If you
1981 /// want to apply suppression specifications to the comparison (or
1982 /// reporting) of ABI corpora please refer to the documentation of the
1983 /// @ref diff_context type to learn how to set suppressions that are
1984 /// to be used in that context.
1985 ///
1986 /// @param rdr the context that is going to be used by functions that
1987 /// read types and declarations information to construct and ABI
1988 /// corpus.
1989 ///
1990 /// @param supprs the suppression specifications to be applied during
1991 /// the construction of the ABI corpus.
1992 void
1994  const suppr::suppressions_type& supprs)
1995 {
1996  for (suppr::suppressions_type::const_iterator i = supprs.begin();
1997  i != supprs.end();
1998  ++i)
1999  if ((*i)->get_drops_artifact_from_ir())
2000  rdr.suppressions().push_back(*i);
2001 }
2002 
2003 /// Configure the @ref reader so that types not reachable from
2004 /// public interface are taken into account when the abixml file is
2005 /// read.
2006 ///
2007 /// @param rdr the @reader to consider.
2008 ///
2009 /// @param flag if yes, then types not reachable from public interface
2010 /// are taken into account when the abixml file is read.
2011 void
2013  bool flag)
2014 {
2015  abixml::reader& rdr = dynamic_cast<abixml::reader&>(iface);
2016  rdr.tracking_non_reachable_types(flag);
2017 }
2018 
2019 #ifdef WITH_SHOW_TYPE_USE_IN_ABILINT
2020 /// Get the vector of types that have a given type-id.
2021 ///
2022 /// This function is available only if the project has been configured
2023 /// with --enable-show-type-use-in-abilint.
2024 ///
2025 /// @param rdr the abixml text reader context to use.
2026 ///
2027 /// @param type_id the type-id to consider.
2028 vector<type_base_sptr>*
2029 get_types_from_type_id(fe_iface& iface, const string& type_id)
2030 {
2031  xml_reader::reader& rdr = dynamic_cast<xml_reader::reader&>(iface);
2032  auto it = rdr.m_types_map.find(type_id);
2033  if (it == rdr.m_types_map.end())
2034  return nullptr;
2035  return &it->second;
2036 }
2037 
2038 /// Get the map that associates an artififact to its users.
2039 ///
2040 /// This function is available only if the project has been configured
2041 /// with --enable-show-type-use-in-abilint.
2042 ///
2043 /// @param rdr the abixml text reader context to use.
2044 unordered_map<type_or_decl_base*, vector<type_or_decl_base*>>*
2045 get_artifact_used_by_relation_map(fe_iface& iface)
2046 {
2047  xml_reader::reader& rdr = dynamic_cast<xml_reader::reader&>(iface);
2048  return &rdr.m_artifact_used_by_map;
2049 }
2050 #endif
2051 
2052 /// Read the "version" attribute from the current XML element which is
2053 /// supposed to be a corpus or a corpus group and set the format
2054 /// version to the corpus object accordingly.
2055 ///
2056 /// Note that this is a subroutine of read_corpus_from_input and
2057 /// read_corpus_group_from_input.
2058 ///
2059 /// @param reader the XML reader to consider. That reader must be
2060 /// set to an XML element representing a corpus or a corpus group.
2061 ///
2062 /// @param corp output parameter. The corpus object which format
2063 /// version string is going to be set according to the value of the
2064 /// "version" attribute found on the current XML element.
2065 static void
2066 handle_version_attribute(xml::reader_sptr& reader, corpus& corp)
2067 {
2068  string version_string;
2069  if (xml_char_sptr s = XML_READER_GET_ATTRIBUTE(reader, "version"))
2070  xml::xml_char_sptr_to_string(s, version_string);
2071 
2072  vector<string> v;
2073  if (version_string.empty())
2074  {
2075  v.push_back("1");
2076  v.push_back("0");
2077  }
2078  else
2079  tools_utils::split_string(version_string, ".", v);
2080  corp.set_format_major_version_number(v[0]);
2081  corp.set_format_minor_version_number(v[1]);
2082 }
2083 
2084 /// Parse the input XML document containing an ABI corpus group,
2085 /// represented by an 'abi-corpus-group' element node, associated to
2086 /// the current context.
2087 ///
2088 /// @param rdr the current input context.
2089 ///
2090 /// @return the corpus group resulting from the parsing
2091 corpus_group_sptr
2093 {
2094  corpus_group_sptr nil;
2095 
2096  abixml::reader& rdr = dynamic_cast<abixml::reader&>(iface);
2097  xml::reader_sptr reader = rdr.get_libxml_reader();
2098  if (!reader)
2099  return nil;
2100 
2101  // The document must start with the abi-corpus-group node.
2102  int status = 1;
2103  while (status == 1
2104  && XML_READER_GET_NODE_TYPE(reader) != XML_READER_TYPE_ELEMENT)
2105  status = advance_cursor (rdr);
2106 
2107  if (status != 1 || !xmlStrEqual (XML_READER_GET_NODE_NAME(reader).get(),
2108  BAD_CAST("abi-corpus-group")))
2109  return nil;
2110 
2111  if (!rdr.corpus_group())
2112  {
2113  corpus_group_sptr g(new corpus_group(rdr.get_environment(),
2114  rdr.get_path()));
2115  g->set_origin(corpus::NATIVE_XML_ORIGIN);
2116  rdr.corpus_group(g);
2117  }
2118 
2119  corpus_group_sptr group = rdr.corpus_group();
2120 
2121  handle_version_attribute(reader, *group);
2122 
2123  xml::xml_char_sptr path_str = XML_READER_GET_ATTRIBUTE(reader, "path");
2124  if (path_str)
2125  group->set_path(reinterpret_cast<char*>(path_str.get()));
2126 
2127  xmlNodePtr node = xmlTextReaderExpand(reader.get());
2128  if (!node)
2129  return nil;
2130 
2131  node = xmlFirstElementChild(node);
2132  rdr.set_corpus_node(node);
2133 
2134  corpus_sptr corp;
2135  fe_iface::status sts;
2136  while ((corp = rdr.read_corpus(sts)))
2137  rdr.corpus_group()->add_corpus(corp);
2138 
2139  xmlTextReaderNext(reader.get());
2140 
2141  return rdr.corpus_group();
2142 }
2143 
2144 /// De-serialize an ABI corpus group from an input XML document which
2145 /// root node is 'abi-corpus-group'.
2146 ///
2147 /// @param in the input stream to read the XML document from.
2148 ///
2149 /// @param env the environment to use. Note that the life time of
2150 /// this environment must be greater than the lifetime of the
2151 /// resulting corpus as the corpus uses resources that are allocated
2152 /// in the environment.
2153 ///
2154 /// @return the resulting corpus group de-serialized from the parsing.
2155 /// This is non-null iff the parsing resulted in a valid corpus group.
2156 corpus_group_sptr
2158  environment& env)
2159 {
2160  fe_iface_sptr rdr = create_reader(in, env);
2161  return read_corpus_group_from_input(*rdr);
2162 }
2163 
2164 /// De-serialize an ABI corpus group from an XML document file which
2165 /// root node is 'abi-corpus-group'.
2166 ///
2167 /// @param path the path to the input file to read the XML document
2168 /// from.
2169 ///
2170 /// @param env the environment to use. Note that the life time of
2171 /// this environment must be greater than the lifetime of the
2172 /// resulting corpus as the corpus uses resources that are allocated
2173 /// in the environment.
2174 ///
2175 /// @return the resulting corpus group de-serialized from the parsing.
2176 /// This is non-null if the parsing successfully resulted in a corpus
2177 /// group.
2178 corpus_group_sptr
2180  environment& env)
2181 {
2182  fe_iface_sptr rdr = create_reader(path, env);
2183  corpus_group_sptr group = read_corpus_group_from_input(*rdr);
2184  return group;
2185 }
2186 
2187 /// Parse an ABI instrumentation file (in XML format) at a given path.
2188 ///
2189 /// @param input_file a path to the file containing the xml document
2190 /// to parse.
2191 ///
2192 /// @param env the environment to use.
2193 ///
2194 /// @return the translation unit resulting from the parsing upon
2195 /// successful completion, or nil.
2197 read_translation_unit_from_file(const string& input_file,
2198  environment& env)
2199 {
2200  reader rdr(xml::new_reader_from_file(input_file), env);
2201  translation_unit_sptr tu = read_translation_unit_from_input(rdr);
2202  env.canonicalization_is_done(false);
2203  rdr.perform_late_type_canonicalizing();
2204  env.canonicalization_is_done(true);
2205  return tu;
2206 }
2207 
2208 /// Parse an ABI instrumentation file (in XML format) from an
2209 /// in-memory buffer.
2210 ///
2211 /// @param buffer the in-memory buffer containing the xml document to
2212 /// parse.
2213 ///
2214 /// @param env the environment to use.
2215 ///
2216 /// @return the translation unit resulting from the parsing upon
2217 /// successful completion, or nil.
2220  environment& env)
2221 {
2222  reader rdr(xml::new_reader_from_buffer(buffer), env);
2223  translation_unit_sptr tu = read_translation_unit_from_input(rdr);
2224  env.canonicalization_is_done(false);
2225  rdr.perform_late_type_canonicalizing();
2226  env.canonicalization_is_done(true);
2227  return tu;
2228 }
2229 
2230 /// Parse a translation unit from an abixml input from a given
2231 /// context.
2232 ///
2233 /// @param rdr the @ref reader to consider.
2234 ///
2235 /// @return the constructed @ref translation_unit from the content of
2236 /// the input abixml.
2238 read_translation_unit(fe_iface& iface)
2239 {
2240  abixml::reader& rdr = dynamic_cast<abixml::reader&>(iface);
2241  translation_unit_sptr tu = read_translation_unit_from_input(rdr);
2242  rdr.options().env.canonicalization_is_done(false);
2243  rdr.perform_late_type_canonicalizing();
2244  rdr.options().env.canonicalization_is_done(true);
2245  return tu;
2246 }
2247 
2248 /// This function is called by @ref read_translation_unit_from_input.
2249 /// It handles the current xml element node of the reading context.
2250 /// The result of the "handling" is to build the representation of the
2251 /// xml node and tied it to the current translation unit.
2252 ///
2253 /// @param rdr the current parsing context.
2254 ///
2255 /// @return true upon successful completion, false otherwise.
2257 handle_element_node(reader& rdr, xmlNodePtr node,
2258  bool add_to_current_scope)
2259 {
2261  if (!node)
2262  return decl;
2263 
2264  ((decl = handle_namespace_decl(rdr, node, add_to_current_scope))
2265  ||(decl = handle_type_decl(rdr, node, add_to_current_scope))
2266  ||(decl = handle_qualified_type_decl(rdr, node,
2267  add_to_current_scope))
2268  ||(decl = handle_pointer_type_def(rdr, node,
2269  add_to_current_scope))
2270  || (decl = handle_reference_type_def(rdr, node, add_to_current_scope))
2271  || (decl = handle_function_type(rdr, node, add_to_current_scope))
2272  || (decl = handle_array_type_def(rdr, node, add_to_current_scope))
2273  || (decl = handle_enum_type_decl(rdr, node,
2274  add_to_current_scope))
2275  || (decl = handle_typedef_decl(rdr, node,
2276  add_to_current_scope))
2277  || (decl = handle_var_decl(rdr, node,
2278  add_to_current_scope))
2279  || (decl = handle_function_decl(rdr, node,
2280  add_to_current_scope))
2281  || (decl = handle_class_decl(rdr, node,
2282  add_to_current_scope))
2283  || (decl = handle_union_decl(rdr, node,
2284  add_to_current_scope))
2285  || (decl = handle_function_tdecl(rdr, node,
2286  add_to_current_scope))
2287  || (decl = handle_class_tdecl(rdr, node,
2288  add_to_current_scope)));
2289 
2290  // If the user wants us to track non-reachable types, then read the
2291  // 'is-non-reachable-type' attribute on type elements and record
2292  // reachable types accordingly.
2293  if (rdr.tracking_non_reachable_types())
2294  {
2295  if (type_base_sptr t = is_type(decl))
2296  {
2297  corpus_sptr abi = rdr.corpus();
2298  ABG_ASSERT(abi);
2299  bool is_non_reachable_type = false;
2300  read_is_non_reachable_type(node, is_non_reachable_type);
2301  if (!is_non_reachable_type)
2302  abi->record_type_as_reachable_from_public_interfaces(*t);
2303  }
2304  }
2305 
2306  return decl;
2307 }
2308 
2309 /// Parses location attributes on an xmlNodePtr.
2310 ///
2311 ///@param rdr the current parsing context
2312 ///
2313 ///@param loc the resulting location.
2314 ///
2315 /// @return true upon sucessful parsing, false otherwise.
2316 static bool
2317 read_location(const reader& rdr,
2318  xmlNodePtr node,
2319  location& loc)
2320 {
2321  string file_path;
2322  size_t line = 0, column = 0;
2323 
2324  if (xml_char_sptr f = xml::build_sptr(xmlGetProp(node, BAD_CAST("filepath"))))
2325  file_path = CHAR_STR(f);
2326 
2327  if (file_path.empty())
2328  return read_artificial_location(rdr, node, loc);
2329 
2330  if (xml_char_sptr l = xml::build_sptr(xmlGetProp(node, BAD_CAST("line"))))
2331  line = atoi(CHAR_STR(l));
2332  else
2333  return read_artificial_location(rdr, node, loc);
2334 
2335  if (xml_char_sptr c = xml::build_sptr(xmlGetProp(node, BAD_CAST("column"))))
2336  column = atoi(CHAR_STR(c));
2337 
2338  reader& c = const_cast<reader&>(rdr);
2339  loc = c.get_translation_unit()->get_loc_mgr().create_new_location(file_path,
2340  line,
2341  column);
2342  return true;
2343 }
2344 
2345 /// Parses the artificial location attributes on an xmlNodePtr.
2346 ///
2347 /// The artificial location is the line number of the xmlNode as well
2348 /// as the URI of the node.
2349 ///
2350 ///@param rdr the current parsing context
2351 ///
2352 ///@param loc the resulting location.
2353 ///
2354 /// @return true upon sucessful parsing, false otherwise.
2355 static bool
2356 read_artificial_location(const reader& rdr,
2357  xmlNodePtr node,
2358  location& loc)
2359 {
2360  if (!node)
2361  return false;
2362 
2363  string file_path;
2364  size_t line = 0, column = 0;
2365 
2366  line = node->line;
2367 
2368  if (node->doc)
2369  file_path = reinterpret_cast<const char*>(node->doc->URL);
2370 
2371  reader& c = const_cast<reader&>(rdr);
2372  loc =
2373  c.get_translation_unit()->get_loc_mgr().create_new_location(file_path,
2374  line, column);
2375  loc.set_is_artificial(true);
2376  return true;
2377 }
2378 
2379 /// Set the artificial location of a xmlNode to an artifact.
2380 ///
2381 /// The artificial location is the line number of the xmlNode as well
2382 /// as the URI of the node.
2383 ///
2384 /// The function sets the artificial location only if the artifact
2385 /// doesn"t already have one.
2386 ///
2387 ///@param rdr the current parsing context
2388 ///
2389 ///@param node the XML node to consider.
2390 ///
2391 ///@param artifact the ABI artifact.
2392 ///
2393 /// @return true iff the location was set on the artifact.
2394 static bool
2395 maybe_set_artificial_location(const reader& rdr,
2396  xmlNodePtr node,
2397  type_or_decl_base_sptr artefact)
2398 {
2399  if (artefact && !artefact->has_artificial_location())
2400  {
2401  location l;
2402  if (read_artificial_location(rdr, node, l))
2403  {
2404  artefact->set_artificial_location(l);
2405  return true;
2406  }
2407  }
2408  return false;
2409 }
2410 
2411 /// Parse the visibility attribute.
2412 ///
2413 /// @param node the xml node to read from.
2414 ///
2415 /// @param vis the resulting visibility.
2416 ///
2417 /// @return true upon successful completion, false otherwise.
2418 static bool
2419 read_visibility(xmlNodePtr node, decl_base::visibility& vis)
2420 {
2421  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "visibility"))
2422  {
2423  string v = CHAR_STR(s);
2424 
2425  if (v == "default")
2426  vis = decl_base::VISIBILITY_DEFAULT;
2427  else if (v == "hidden")
2428  vis = decl_base::VISIBILITY_HIDDEN;
2429  else if (v == "internal")
2430  vis = decl_base::VISIBILITY_INTERNAL;
2431  else if (v == "protected")
2432  vis = decl_base::VISIBILITY_PROTECTED;
2433  else
2434  vis = decl_base::VISIBILITY_DEFAULT;
2435  return true;
2436  }
2437  return false;
2438 }
2439 
2440 /// Parse the "binding" attribute on the current element.
2441 ///
2442 /// @param node the xml node to build parse the bind from.
2443 ///
2444 /// @param bind the resulting binding attribute.
2445 ///
2446 /// @return true upon successful completion, false otherwise.
2447 static bool
2448 read_binding(xmlNodePtr node, decl_base::binding& bind)
2449 {
2450  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "binding"))
2451  {
2452  string b = CHAR_STR(s);
2453 
2454  if (b == "global")
2455  bind = decl_base::BINDING_GLOBAL;
2456  else if (b == "local")
2457  bind = decl_base::BINDING_LOCAL;
2458  else if (b == "weak")
2459  bind = decl_base::BINDING_WEAK;
2460  else
2461  bind = decl_base::BINDING_GLOBAL;
2462  return true;
2463  }
2464 
2465  return false;
2466 }
2467 
2468 /// Read the 'access' attribute on the current xml node.
2469 ///
2470 /// @param node the xml node to consider.
2471 ///
2472 /// @param access the access attribute. Set iff the function returns true.
2473 ///
2474 /// @return true upon sucessful completion, false otherwise.
2475 static bool
2476 read_access(xmlNodePtr node, access_specifier& access)
2477 {
2478  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "access"))
2479  {
2480  string a = CHAR_STR(s);
2481 
2482  if (a == "private")
2483  access = private_access;
2484  else if (a == "protected")
2485  access = protected_access;
2486  else if (a == "public")
2487  access = public_access;
2488  else
2489  /// If there is an access specifier of an unsupported value,
2490  /// we should not assume anything and abort.
2491  abort();
2492 
2493  return true;
2494  }
2495  return false;
2496 }
2497 
2498 /// Parse 'size-in-bits' and 'alignment-in-bits' attributes of a given
2499 /// xmlNodePtr reprensting an xml element.
2500 ///
2501 /// @param node the xml element node to consider.
2502 ///
2503 /// @param size_in_bits the resulting value for the 'size-in-bits'
2504 /// attribute. This set only if this function returns true and the if
2505 /// the attribute was present on the xml element node.
2506 ///
2507 /// @param align_in_bits the resulting value for the
2508 /// 'alignment-in-bits' attribute. This set only if this function
2509 /// returns true and the if the attribute was present on the xml
2510 /// element node.
2511 ///
2512 /// @return true if either one of the two attributes above were set,
2513 /// false otherwise.
2514 static bool
2515 read_size_and_alignment(xmlNodePtr node,
2516  size_t& size_in_bits,
2517  size_t& align_in_bits)
2518 {
2519 
2520  bool got_something = false;
2521  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "size-in-bits"))
2522  {
2523  size_in_bits = atoll(CHAR_STR(s));
2524  got_something = true;
2525  }
2526 
2527  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "alignment-in-bits"))
2528  {
2529  align_in_bits = atoll(CHAR_STR(s));
2530  got_something = true;
2531  }
2532  return got_something;
2533 }
2534 
2535 /// Parse the 'static' attribute of a given xml element node.
2536 ///
2537 /// @param node the xml element node to consider.
2538 ///
2539 /// @param is_static the resulting the parsing. Is set if the
2540 /// function returns true.
2541 ///
2542 /// @return true if the xml element node has the 'static' attribute
2543 /// set, false otherwise.
2544 static bool
2545 read_static(xmlNodePtr node, bool& is_static)
2546 {
2547  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "static"))
2548  {
2549  string b = CHAR_STR(s);
2550  is_static = b == "yes";
2551  return true;
2552  }
2553  return false;
2554 }
2555 
2556 /// Parse the 'layout-offset-in-bits' attribute of a given xml element node.
2557 ///
2558 /// @param offset_in_bits set to true if the element node contains the
2559 /// attribute.
2560 ///
2561 /// @return true iff the xml element node contains the attribute.
2562 static bool
2563 read_offset_in_bits(xmlNodePtr node,
2564  size_t& offset_in_bits)
2565 {
2566  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "layout-offset-in-bits"))
2567  {
2568  offset_in_bits = strtoull(CHAR_STR(s), 0, 0);
2569  return true;
2570  }
2571  return false;
2572 }
2573 
2574 /// Parse the 'constructor', 'destructor' and 'const' attribute of a
2575 /// given xml node.
2576 ///
2577 /// @param is_constructor the resulting value of the parsing of the
2578 /// 'constructor' attribute. Is set if the xml node contains the
2579 /// attribute and if the function returns true.
2580 ///
2581 /// @param is_destructor the resulting value of the parsing of the
2582 /// 'destructor' attribute. Is set if the xml node contains the
2583 /// attribute and if the function returns true.
2584 ///
2585 /// @param is_const the resulting value of the parsing of the 'const'
2586 /// attribute. Is set if the xml node contains the attribute and if
2587 /// the function returns true.
2588 ///
2589 /// @return true if at least of the attributes above is set, false
2590 /// otherwise.
2591 ///
2592 /// Note that callers of this function should initialize
2593 /// is_constructor, is_destructor and is_const prior to passing them
2594 /// to this function.
2595 static bool
2596 read_cdtor_const(xmlNodePtr node,
2597  bool& is_constructor,
2598  bool& is_destructor,
2599  bool& is_const)
2600 {
2601  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "constructor"))
2602  {
2603  string b = CHAR_STR(s);
2604  if (b == "yes")
2605  is_constructor = true;
2606  else
2607  is_constructor = false;
2608 
2609  return true;
2610  }
2611 
2612  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "destructor"))
2613  {
2614  string b = CHAR_STR(s);
2615  if (b == "yes")
2616  is_destructor = true;
2617  else
2618  is_destructor = false;
2619 
2620  return true;
2621  }
2622 
2623  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "const"))
2624  {
2625  string b = CHAR_STR(s);
2626  if (b == "yes")
2627  is_const = true;
2628  else
2629  is_const = false;
2630 
2631  return true;
2632  }
2633 
2634  return false;
2635 }
2636 
2637 /// Read the "is-declaration-only" attribute of the current xml node.
2638 ///
2639 /// @param node the xml node to consider.
2640 ///
2641 /// @param is_decl_only is set to true iff the "is-declaration-only" attribute
2642 /// is present and set to "yes".
2643 ///
2644 /// @return true iff the is_decl_only attribute was set.
2645 static bool
2646 read_is_declaration_only(xmlNodePtr node, bool& is_decl_only)
2647 {
2648  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "is-declaration-only"))
2649  {
2650  string str = CHAR_STR(s);
2651  if (str == "yes")
2652  is_decl_only = true;
2653  else
2654  is_decl_only = false;
2655  return true;
2656  }
2657  return false;
2658 }
2659 
2660 /// Read the "is-artificial" attribute of the current XML node.
2661 ///
2662 /// @param node the XML node to consider.
2663 ///
2664 /// @param is_artificial this output parameter is set to true iff the
2665 /// "is-artificial" parameter is present and set to 'yes'.
2666 ///
2667 /// @return true iff the "is-artificial" parameter was present on the
2668 /// XML node.
2669 static bool
2670 read_is_artificial(xmlNodePtr node, bool& is_artificial)
2671 {
2672  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "is-artificial"))
2673  {
2674  string is_artificial_str = CHAR_STR(s) ? CHAR_STR(s) : "";
2675  is_artificial = is_artificial_str == "yes";
2676  return true;
2677  }
2678  return false;
2679 }
2680 
2681 /// Read the 'tracking-non-reachable-types' attribute on the current
2682 /// XML element.
2683 ///
2684 /// @param node the current XML element.
2685 ///
2686 /// @param tracking_non_reachable_types output parameter. This is set
2687 /// to true iff the 'tracking-non-reachable-types' attribute is
2688 /// present on the current XML node and set to 'yes'. In that case,
2689 /// the function returns true.
2690 ///
2691 /// @return true iff the 'tracking-non-reachable-types' attribute is
2692 /// present on the current XML node and set to 'yes'.
2693 static bool
2694 read_tracking_non_reachable_types(xmlNodePtr node,
2695  bool& tracking_non_reachable_types)
2696 {
2697  if (xml_char_sptr s =
2698  XML_NODE_GET_ATTRIBUTE(node, "tracking-non-reachable-types"))
2699  {
2700  string tracking_non_reachable_types_str = CHAR_STR(s) ? CHAR_STR(s) : "";
2701  tracking_non_reachable_types =
2702  (tracking_non_reachable_types_str == "yes")
2703  ? true
2704  : false;
2705  return true;
2706  }
2707  return false;
2708 }
2709 
2710 /// Read the 'is-non-reachable' attribute on the current XML element.
2711 ///
2712 /// @param node the current XML element.
2713 ///
2714 /// @param is_non_reachable_type output parameter. This is set to true
2715 /// iff the 'is-non-reachable' attribute is present on the current XML
2716 /// element with a value se to 'yes'.
2717 ///
2718 /// @return true iff the 'is-non-reachable' attribute is present on
2719 /// the current XML element with a value se to 'yes'.
2720 static bool
2721 read_is_non_reachable_type(xmlNodePtr node, bool& is_non_reachable_type)
2722 {
2723  if (xml_char_sptr s =
2724  XML_NODE_GET_ATTRIBUTE(node, "is-non-reachable"))
2725  {
2726  string is_non_reachable_type_str = CHAR_STR(s) ? CHAR_STR(s) : "";
2727  is_non_reachable_type =
2728  (is_non_reachable_type_str == "yes")
2729  ? true
2730  : false;
2731  return true;
2732  }
2733  return false;
2734 }
2735 
2736 /// Read the "naming-typedef-id" property from an XML node.
2737 ///
2738 /// @param node the XML node to consider.
2739 ///
2740 /// @param naming_typedef_id output parameter. It's set to the
2741 /// content of the "naming-typedef-id" property, if it's present.
2742 ///
2743 /// @return true iff the "naming-typedef-id" property exists and was
2744 /// read from @p node.
2745 static bool
2746 read_naming_typedef_id_string(xmlNodePtr node, string& naming_typedef_id)
2747 {
2748  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "naming-typedef-id"))
2749  {
2750  naming_typedef_id = xml::unescape_xml_string(CHAR_STR(s));
2751  return true;
2752  }
2753  return false;
2754 }
2755 
2756 /// Read the "is-virtual" attribute of the current xml node.
2757 ///
2758 /// @param node the xml node to read the attribute from
2759 ///
2760 /// @param is_virtual is set to true iff the "is-virtual" attribute is
2761 /// present and set to "yes".
2762 ///
2763 /// @return true iff the is-virtual attribute is present.
2764 static bool
2765 read_is_virtual(xmlNodePtr node, bool& is_virtual)
2766 {
2767  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "is-virtual"))
2768  {
2769  string str = CHAR_STR(s);
2770  if (str == "yes")
2771  is_virtual = true;
2772  else
2773  is_virtual = false;
2774  return true;
2775  }
2776  return false;
2777 }
2778 
2779 /// Read the 'is-struct' attribute.
2780 ///
2781 /// @param node the xml node to read the attribute from.
2782 ///
2783 /// @param is_struct is set to true iff the "is-struct" attribute is
2784 /// present and set to "yes".
2785 ///
2786 /// @return true iff the "is-struct" attribute is present.
2787 static bool
2788 read_is_struct(xmlNodePtr node, bool& is_struct)
2789 {
2790  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "is-struct"))
2791  {
2792  string str = CHAR_STR(s);
2793  if (str == "yes")
2794  is_struct = true;
2795  else
2796  is_struct = false;
2797  return true;
2798  }
2799  return false;
2800 }
2801 
2802 /// Read the 'is-anonymous' attribute.
2803 ///
2804 /// @param node the xml node to read the attribute from.
2805 ///
2806 /// @param is_anonymous is set to true iff the "is-anonymous" is present
2807 /// and set to "yes".
2808 ///
2809 /// @return true iff the "is-anonymous" attribute is present.
2810 static bool
2811 read_is_anonymous(xmlNodePtr node, bool& is_anonymous)
2812 {
2813  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "is-anonymous"))
2814  {
2815  string str = CHAR_STR(s);
2816  is_anonymous = (str == "yes");
2817  return true;
2818  }
2819  return false;
2820 }
2821 
2822 /// Read the 'type' attribute of the 'elf-symbol' element.
2823 ///
2824 /// @param node the XML node to read the attribute from.
2825 ///
2826 /// @param t the resulting elf_symbol::type.
2827 ///
2828 /// @return true iff the function completed successfully.
2829 static bool
2830 read_elf_symbol_type(xmlNodePtr node, elf_symbol::type& t)
2831 {
2832  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type"))
2833  {
2834  string str;
2836  if (!string_to_elf_symbol_type(str, t))
2837  return false;
2838  return true;
2839  }
2840  return false;
2841 }
2842 
2843 /// Read the 'binding' attribute of the of the 'elf-symbol' element.
2844 ///
2845 /// @param node the XML node to read the attribute from.
2846 ///
2847 /// @param b the XML the resulting elf_symbol::binding.
2848 ///
2849 /// @return true iff the function completed successfully.
2850 static bool
2851 read_elf_symbol_binding(xmlNodePtr node, elf_symbol::binding& b)
2852 {
2853  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "binding"))
2854  {
2855  string str;
2857  if (!string_to_elf_symbol_binding(str, b))
2858  return false;
2859  return true;
2860  }
2861  return false;
2862 }
2863 
2864 /// Read the 'visibility' attribute of the of the 'elf-symbol'
2865 /// element.
2866 ///
2867 /// @param node the XML node to read the attribute from.
2868 ///
2869 /// @param b the XML the resulting elf_symbol::visibility.
2870 ///
2871 /// @return true iff the function completed successfully.
2872 static bool
2873 read_elf_symbol_visibility(xmlNodePtr node, elf_symbol::visibility& v)
2874 {
2875  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "visibility"))
2876  {
2877  string str;
2879  if (!string_to_elf_symbol_visibility(str, v))
2880  return false;
2881  return true;
2882  }
2883  return false;
2884 }
2885 
2886 #ifdef WITH_DEBUG_SELF_COMPARISON
2887 /// Read the value of the 'id' attribute from a given XML node.
2888 ///
2889 /// @param node the XML node to consider.
2890 ///
2891 /// @param type_id the string to set the 'id' to.
2892 ///
2893 /// @return true iff @p type_id was successfully set.
2894 static bool
2895 read_type_id_string(xmlNodePtr node, string& type_id)
2896 {
2897  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
2898  {
2899  type_id = CHAR_STR(s);
2900  return true;
2901  }
2902  return false;
2903 }
2904 
2905 /// Associate a type-id string with the type that was constructed from
2906 /// it.
2907 ///
2908 /// Note that if we are not in "self comparison debugging" mode or if
2909 /// the type we are looking at is not canonicalized, then this
2910 /// function does nothing.
2911 ///
2912 /// @param t the type built from the a type XML node that has a
2913 /// particular type-id.
2914 ///
2915 /// @param type_id the type-id of type @p t.
2916 ///
2917 /// @return true if the association was performed.
2918 static bool
2919 maybe_map_type_with_type_id(const type_base_sptr& t,
2920  const string& type_id)
2921 {
2922  if (!t)
2923  return false;
2924 
2925  const environment& env = t->get_environment();
2926  if (!env.self_comparison_debug_is_on()
2927  || is_non_canonicalized_type(t.get()))
2928  return false;
2929 
2930  const_cast<environment&>(env).
2931  get_pointer_type_id_map()[reinterpret_cast<uintptr_t>(t.get())] = type_id;
2932 
2933  return true;
2934 }
2935 
2936 /// Associate a type-id string with the type that was constructed from
2937 /// it.
2938 ///
2939 /// Note that if we are not in "self comparison debugging" mode or if
2940 /// the type we are looking at is not canonicalized, then this
2941 /// function does nothing.
2942 ///
2943 /// @param t the type built from the a type XML node that has a
2944 /// particular type-id.
2945 ///
2946 /// @param type_id the type-id of type @p t.
2947 ///
2948 /// @return true if the association was performed.
2949 static bool
2950 maybe_map_type_with_type_id(const type_base_sptr& t,
2951  xmlNodePtr node)
2952 {
2953  if (!t)
2954  return false;
2955 
2956  const environment&env = t->get_environment();
2957  if (!env.self_comparison_debug_is_on()
2958  || is_non_canonicalized_type(t.get()))
2959  return false;
2960 
2961  string type_id;
2962  if (!read_type_id_string(node, type_id) || type_id.empty())
2963  return false;
2964 
2965  return maybe_map_type_with_type_id(t, type_id);
2966 }
2967 
2968 #endif
2969 
2970 /// Set the naming typedef to a given decl depending on the content of
2971 /// the "naming-typedef-id" property of its descriptive XML element.
2972 ///
2973 /// @param rdr the current ABIXML reader.
2974 ///
2975 /// @param node the XML node to read from.
2976 ///
2977 /// @param decl the decl to set the naming typedef to.
2978 static void
2979 maybe_set_naming_typedef(reader& rdr,
2980  xmlNodePtr node,
2981  const decl_base_sptr& decl)
2982 {
2983  string naming_typedef_id;
2984  read_naming_typedef_id_string(node, naming_typedef_id);
2985  if (!naming_typedef_id.empty())
2986  {
2987  typedef_decl_sptr naming_typedef =
2988  is_typedef(rdr.build_or_get_type_decl(naming_typedef_id, true));
2989  ABG_ASSERT(naming_typedef);
2990  decl->set_naming_typedef(naming_typedef);
2991  }
2992 }
2993 
2994 /// Build a @ref namespace_decl from an XML element node which name is
2995 /// "namespace-decl". Note that this function recursively reads the
2996 /// content of the namespace and builds the proper IR nodes
2997 /// accordingly.
2998 ///
2999 /// @param rdr the ABIXML reader to use.
3000 ///
3001 /// @param node the XML node to consider. It must constain the
3002 /// content of the namespace, that is, children XML nodes representing
3003 /// what is inside the namespace, unless the namespace is empty.
3004 ///
3005 /// @param add_to_current_scope if set to yes, the resulting
3006 /// namespace_decl is added to the IR being currently built.
3007 ///
3008 /// @return a pointer to the the resulting @ref namespace_decl.
3009 static namespace_decl_sptr
3010 build_namespace_decl(reader& rdr,
3011  const xmlNodePtr node,
3012  bool add_to_current_scope)
3013 {
3014  namespace_decl_sptr nil;
3015  if (!node || !xmlStrEqual(node->name, BAD_CAST("namespace-decl")))
3016  return nil;
3017 
3018  if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
3019  {
3020  namespace_decl_sptr result = dynamic_pointer_cast<namespace_decl>(d);
3021  ABG_ASSERT(result);
3022  return result;
3023  }
3024 
3025  string name;
3026  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
3027  name = xml::unescape_xml_string(CHAR_STR(s));
3028 
3029  location loc;
3030  read_location(rdr, node, loc);
3031 
3032  const environment& env = rdr.get_environment();
3033  namespace_decl_sptr decl(new namespace_decl(env, name, loc));
3034  maybe_set_artificial_location(rdr, node, decl);
3035  rdr.push_decl_to_current_scope(decl, add_to_current_scope);
3036  rdr.map_xml_node_to_decl(node, decl);
3037 
3038  for (xmlNodePtr n = xmlFirstElementChild(node);
3039  n;
3040  n = xmlNextElementSibling(n))
3041  handle_element_node(rdr, n, /*add_to_current_scope=*/true);
3042 
3043  rdr.pop_scope_or_abort(decl);
3044 
3045  return decl;
3046 }
3047 
3048 /// Build an instance of @ref elf_symbol from an XML element node
3049 /// which name is 'elf-symbol'.
3050 ///
3051 /// @param rdr the context used for reading the XML input.
3052 ///
3053 /// @param node the XML node to read.
3054 ///
3055 /// @param drop_if_suppressed if the elf symbol was suppressed by a
3056 /// suppression specification then do not build it.
3057 ///
3058 /// @return the @ref elf_symbol built, or nil if it couldn't be built.
3059 static elf_symbol_sptr
3060 build_elf_symbol(reader& rdr, const xmlNodePtr node,
3061  bool drop_if_suppressed)
3062 {
3063  elf_symbol_sptr nil;
3064 
3065  if (!node
3066  || node->type != XML_ELEMENT_NODE
3067  || !xmlStrEqual(node->name, BAD_CAST("elf-symbol")))
3068  return nil;
3069 
3070  string name;
3071  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
3073 
3074  size_t size = 0;
3075  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "size"))
3076  size = strtol(CHAR_STR(s), NULL, 0);
3077 
3078  bool is_defined = true;
3079  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "is-defined"))
3080  {
3081  string value;
3082  xml::xml_char_sptr_to_string(s, value);
3083  if (value == "true" || value == "yes")
3084  is_defined = true;
3085  else
3086  is_defined = false;
3087  }
3088 
3089  bool is_common = false;
3090  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "is-common"))
3091  {
3092  string value;
3093  xml::xml_char_sptr_to_string(s, value);
3094  if (value == "true" || value == "yes")
3095  is_common = true;
3096  else
3097  is_common = false;
3098  }
3099 
3100  string version_string;
3101  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "version"))
3102  xml::xml_char_sptr_to_string(s, version_string);
3103 
3104  bool is_default_version = false;
3105  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "is-default-version"))
3106  {
3107  string value;
3108  xml::xml_char_sptr_to_string(s, value);
3109  if (value == "true" || value == "yes")
3110  is_default_version = true;
3111  }
3112 
3113  elf_symbol::type type = elf_symbol::NOTYPE_TYPE;
3114  read_elf_symbol_type(node, type);
3115 
3116  elf_symbol::binding binding = elf_symbol::GLOBAL_BINDING;
3117  read_elf_symbol_binding(node, binding);
3118 
3119  elf_symbol::visibility visibility = elf_symbol::DEFAULT_VISIBILITY;
3120  read_elf_symbol_visibility(node, visibility);
3121 
3122  elf_symbol::version version(version_string, is_default_version);
3123 
3124  const bool is_suppressed = suppr::is_elf_symbol_suppressed(rdr, name, type);
3125  if (drop_if_suppressed && is_suppressed)
3126  return elf_symbol_sptr();
3127 
3128  const environment& env = rdr.get_environment();
3129  elf_symbol_sptr e = elf_symbol::create(env, /*index=*/0,
3130  size, name, type, binding,
3131  is_defined, is_common,
3132  version, visibility);
3133 
3134  e->set_is_suppressed(is_suppressed);
3135 
3136  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "crc"))
3137  e->set_crc(strtoull(CHAR_STR(s), NULL, 0));
3138 
3139  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "namespace"))
3140  {
3141  std::string ns;
3143  e->set_namespace(ns);
3144  }
3145 
3146  return e;
3147 }
3148 
3149 /// Build and instance of elf_symbol from an XML attribute named
3150 /// 'elf-symbol-id' which value is the ID of a symbol that should
3151 /// present in the symbol db of the corpus associated to the current
3152 /// context.
3153 ///
3154 /// @param rdr the current context to consider.
3155 ///
3156 /// @param node the xml element node to consider.
3157 ///
3158 /// @param function_symbol is true if we should look for a function
3159 /// symbol, is false if we should look for a variable symbol.
3160 ///
3161 /// @return a shared pointer the resutling elf_symbol.
3162 static elf_symbol_sptr
3163 build_elf_symbol_from_reference(reader& rdr, const xmlNodePtr node)
3164 {
3165  elf_symbol_sptr nil;
3166 
3167  if (!node)
3168  return nil;
3169 
3170  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "elf-symbol-id"))
3171  {
3172  string sym_id;
3173  xml::xml_char_sptr_to_string(s, sym_id);
3174  if (sym_id.empty())
3175  return nil;
3176 
3177  string name, ver;
3178  elf_symbol::get_name_and_version_from_id(sym_id, name, ver);
3179  if (name.empty())
3180  return nil;
3181 
3182  const elf_symbols& symbols =
3183  rdr.corpus()->get_symtab()->lookup_symbol(name);
3184 
3185  for (const auto& symbol : symbols)
3186  if (symbol->get_id_string() == sym_id)
3187  return symbol;
3188  }
3189 
3190  return nil;
3191 }
3192 
3193 /// Build an instance of string_elf_symbols_map_type from an XML
3194 /// element representing either a function symbols data base, or a
3195 /// variable symbols database.
3196 ///
3197 /// @param rdr the context to take in account.
3198 ///
3199 /// @param node the XML node to consider.
3200 ///
3201 /// @param function_syms true if we should look for a function symbols
3202 /// data base, false if we should look for a variable symbols data
3203 /// base.
3205 build_elf_symbol_db(reader& rdr,
3206  const xmlNodePtr node,
3207  bool function_syms)
3208 {
3209  string_elf_symbols_map_sptr map, nil;
3211 
3212  if (!node)
3213  return nil;
3214 
3215  if (function_syms
3216  && !xmlStrEqual(node->name, BAD_CAST("elf-function-symbols")))
3217  return nil;
3218 
3219  if (!function_syms
3220  && !xmlStrEqual(node->name, BAD_CAST("elf-variable-symbols")))
3221  return nil;
3222 
3223  rdr.set_corpus_node(node);
3224 
3225  typedef std::unordered_map<xmlNodePtr, elf_symbol_sptr>
3226  xml_node_ptr_elf_symbol_sptr_map_type;
3227  xml_node_ptr_elf_symbol_sptr_map_type xml_node_ptr_elf_symbol_map;
3228 
3229  elf_symbol_sptr sym;
3230  for (xmlNodePtr n = xmlFirstElementChild(node);
3231  n;
3232  n = xmlNextElementSibling(n))
3233  if ((sym = build_elf_symbol(rdr, n, /*drop_if_suppress=*/false)))
3234  {
3235  id_sym_map[sym->get_id_string()] = sym;
3236  xml_node_ptr_elf_symbol_map[n] = sym;
3237  }
3238 
3239  if (id_sym_map.empty())
3240  return nil;
3241 
3242  map.reset(new string_elf_symbols_map_type);
3243  string_elf_symbols_map_type::iterator it;
3244  for (string_elf_symbol_sptr_map_type::const_iterator i = id_sym_map.begin();
3245  i != id_sym_map.end();
3246  ++i)
3247  (*map)[i->second->get_name()].push_back(i->second);
3248 
3249  // Now build the alias relations
3250  for (xml_node_ptr_elf_symbol_sptr_map_type::const_iterator x =
3251  xml_node_ptr_elf_symbol_map.begin();
3252  x != xml_node_ptr_elf_symbol_map.end();
3253  ++x)
3254  {
3255  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(x->first, "alias"))
3256  {
3257  string alias_id = CHAR_STR(s);
3258 
3259  // Symbol aliases can be multiple separated by comma(,), split them
3260  std::vector<std::string> elems;
3261  std::stringstream aliases(alias_id);
3262  std::string item;
3263  while (std::getline(aliases, item, ','))
3264  elems.push_back(item);
3265  for (std::vector<string>::iterator alias = elems.begin();
3266  alias != elems.end(); ++alias)
3267  {
3268  string_elf_symbol_sptr_map_type::const_iterator i =
3269  id_sym_map.find(*alias);
3270  ABG_ASSERT(i != id_sym_map.end());
3271  ABG_ASSERT(i->second->is_main_symbol());
3272 
3273  x->second->get_main_symbol()->add_alias(i->second);
3274  }
3275  }
3276  }
3277 
3278  return map;
3279 }
3280 
3281 /// Build a function parameter from a 'parameter' xml element node.
3282 ///
3283 /// @param rdr the contexte of the xml parsing.
3284 ///
3285 /// @param node the xml 'parameter' element node to de-serialize from.
3286 static shared_ptr<function_decl::parameter>
3287 build_function_parameter(reader& rdr, const xmlNodePtr node)
3288 {
3289  shared_ptr<function_decl::parameter> nil;
3290 
3291  if (!node || !xmlStrEqual(node->name, BAD_CAST("parameter")))
3292  return nil;
3293 
3294  bool is_variadic = false;
3295  string is_variadic_str;
3296  if (xml_char_sptr s =
3297  xml::build_sptr(xmlGetProp(node, BAD_CAST("is-variadic"))))
3298  {
3299  is_variadic_str = CHAR_STR(s) ? CHAR_STR(s) : "";
3300  is_variadic = is_variadic_str == "yes";
3301  }
3302 
3303  bool is_artificial = false;
3304  read_is_artificial(node, is_artificial);
3305 
3306  string type_id;
3307  if (xml_char_sptr a = xml::build_sptr(xmlGetProp(node, BAD_CAST("type-id"))))
3308  type_id = CHAR_STR(a);
3309 
3310  type_base_sptr type;
3311  if (is_variadic)
3312  type = rdr.get_environment().get_variadic_parameter_type();
3313  else
3314  {
3315  ABG_ASSERT(!type_id.empty());
3316  type = rdr.build_or_get_type_decl(type_id, true);
3317  }
3318  ABG_ASSERT(type);
3319 
3320  string name;
3321  if (xml_char_sptr a = xml::build_sptr(xmlGetProp(node, BAD_CAST("name"))))
3322  name = CHAR_STR(a);
3323 
3324  location loc;
3325  read_location(rdr, node, loc);
3326 
3328  (new function_decl::parameter(type, name, loc,
3329  is_variadic, is_artificial));
3330 
3331  return p;
3332 }
3333 
3334 /// Build a function_decl from a 'function-decl' xml node.
3335 ///
3336 /// @param rdr the context of the parsing.
3337 ///
3338 /// @param node the xml node to build the function_decl from.
3339 ///
3340 /// @param as_method_decl if this is set to a class_decl pointer, it
3341 /// means that the 'function-decl' xml node should be parsed as a
3342 /// method_decl. The class_decl pointer is the class decl to which
3343 /// the resulting method_decl is a member function of. The resulting
3344 /// shared_ptr<function_decl> that is returned is then really a
3345 /// shared_ptr<method_decl>.
3346 ///
3347 /// @param add_to_current_scope if set to yes, the resulting of
3348 /// this function is added to its current scope.
3349 ///
3350 /// @return a pointer to a newly created function_decl upon successful
3351 /// completion, a null pointer otherwise.
3352 static function_decl_sptr
3353 build_function_decl(reader& rdr,
3354  const xmlNodePtr node,
3355  class_or_union_sptr as_method_decl,
3356  bool add_to_current_scope)
3357 {
3358  function_decl_sptr nil;
3359 
3360  if (!xmlStrEqual(node->name, BAD_CAST("function-decl")))
3361  return nil;
3362 
3363  string name;
3364  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
3365  name = xml::unescape_xml_string(CHAR_STR(s));
3366 
3367  string mangled_name;
3368  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "mangled-name"))
3369  mangled_name = xml::unescape_xml_string(CHAR_STR(s));
3370 
3371  string inline_prop;
3372  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "declared-inline"))
3373  inline_prop = CHAR_STR(s);
3374  bool declared_inline = inline_prop == "yes";
3375 
3376  decl_base::visibility vis = decl_base::VISIBILITY_NONE;
3377  read_visibility(node, vis);
3378 
3379  decl_base::binding bind = decl_base::BINDING_NONE;
3380  read_binding(node, bind);
3381 
3382  size_t size = rdr.get_translation_unit()->get_address_size(), align = 0;
3383  read_size_and_alignment(node, size, align);
3384 
3385  location loc;
3386  read_location(rdr, node, loc);
3387 
3388  const environment& env = rdr.get_environment();
3389 
3390  std::vector<function_decl::parameter_sptr> parms;
3391  type_base_sptr return_type = env.get_void_type();
3392 
3393  for (xmlNodePtr n = xmlFirstElementChild(node);
3394  n ;
3395  n = xmlNextElementSibling(n))
3396  {
3397  if (xmlStrEqual(n->name, BAD_CAST("parameter")))
3398  {
3400  build_function_parameter(rdr, n))
3401  parms.push_back(p);
3402  }
3403  else if (xmlStrEqual(n->name, BAD_CAST("return")))
3404  {
3405  string type_id;
3406  if (xml_char_sptr s =
3407  xml::build_sptr(xmlGetProp(n, BAD_CAST("type-id"))))
3408  type_id = CHAR_STR(s);
3409  if (!type_id.empty())
3410  return_type = rdr.build_or_get_type_decl(type_id, true);
3411  }
3412  }
3413 
3414  function_type_sptr fn_type(as_method_decl
3415  ? new method_type(return_type, as_method_decl,
3416  parms, /*is_const=*/false,
3417  size, align)
3418  : new function_type(return_type,
3419  parms, size, align));
3420 
3421  ABG_ASSERT(fn_type);
3422 
3423  fn_type->set_is_artificial(true);
3424 
3425  function_decl_sptr fn_decl(as_method_decl
3426  ? new method_decl (name, fn_type,
3427  declared_inline, loc,
3428  mangled_name, vis, bind)
3429  : new function_decl(name, fn_type,
3430  declared_inline, loc,
3431  mangled_name, vis,
3432  bind));
3433 
3434  maybe_set_artificial_location(rdr, node, fn_decl);
3435  rdr.push_decl_to_current_scope(fn_decl, add_to_current_scope);
3436  RECORD_ARTIFACTS_AS_USED_IN_FN_DECL(rdr, fn_decl);
3437 
3438  elf_symbol_sptr sym = build_elf_symbol_from_reference(rdr, node);
3439  if (sym)
3440  fn_decl->set_symbol(sym);
3441 
3442  if (fn_decl->get_symbol() && fn_decl->get_symbol()->is_public())
3443  fn_decl->set_is_in_public_symbol_table(true);
3444 
3445  rdr.get_translation_unit()->bind_function_type_life_time(fn_type);
3446 
3447  rdr.maybe_canonicalize_type(fn_type, !add_to_current_scope);
3448 
3449  rdr.maybe_add_fn_to_exported_decls(fn_decl.get());
3450 
3451  return fn_decl;
3452 }
3453 
3454 /// Build a function_decl from a 'function-decl' xml node if it's not
3455 /// been suppressed by a suppression specification that is in the
3456 /// context.
3457 ///
3458 /// @param rdr the context of the parsing.
3459 ///
3460 /// @param node the xml node to build the function_decl from.
3461 ///
3462 /// @param as_method_decl if this is set to a class_or_union pointer,
3463 /// it means that the 'function-decl' xml node should be parsed as a
3464 /// method_decl. The class_or_union pointer is the class or union the
3465 /// resulting method_decl is a member function of. The resulting @ref
3466 /// function_decl_sptr that is returned is then really a @ref
3467 /// method_decl_sptr.
3468 ///
3469 /// @param add_to_current_scope if set to yes, the resulting of
3470 /// this function is added to its current scope.
3471 ///
3472 /// @return a pointer to a newly created function_decl upon successful
3473 /// completion. If the function was suppressed by a suppression
3474 /// specification then returns nil.
3475 static function_decl_sptr
3476 build_function_decl_if_not_suppressed(reader& rdr,
3477  const xmlNodePtr node,
3478  class_or_union_sptr as_method_decl,
3479  bool add_to_current_scope)
3480 {
3481  function_decl_sptr fn;
3482 
3483  if (function_is_suppressed(rdr, node))
3484  // The function was suppressed by at least one suppression
3485  // specification associated to the current ABIXML reader. So
3486  // don't build any IR for it.
3487  ;
3488  else
3489  fn = build_function_decl(rdr, node, as_method_decl,
3490  add_to_current_scope);
3491  return fn;
3492 }
3493 
3494 /// Test if a given function denoted by its name and linkage name is
3495 /// suppressed by any of the suppression specifications associated to
3496 /// a given context of native xml reading.
3497 ///
3498 /// @param rdr the native xml reading context of interest.
3499 ///
3500 /// @param note the XML node that represents the fucntion.
3501 /// match.
3502 ///
3503 /// @return true iff at least one function specification matches the
3504 /// function denoted by the node @p node.
3505 static bool
3506 function_is_suppressed(const reader& rdr, xmlNodePtr node)
3507 {
3508  string fname;
3509  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
3510  fname = xml::unescape_xml_string(CHAR_STR(s));
3511 
3512  string flinkage_name;
3513  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "mangled-name"))
3514  flinkage_name = xml::unescape_xml_string(CHAR_STR(s));
3515 
3516  scope_decl* scope = rdr.get_cur_scope();
3517 
3518  string qualified_name = build_qualified_name(scope, fname);
3519 
3520  return suppr::is_function_suppressed(rdr, qualified_name, flinkage_name);
3521 }
3522 
3523 /// Test if a type denoted by its name, context and location is
3524 /// suppressed by the suppression specifications that are associated
3525 /// to a given ABIXML reader.
3526 ///
3527 /// @param rdr the ABIXML reader to consider.
3528 ///
3529 /// @param note the XML node that represents the type.
3530 ///
3531 /// @return true iff the type designated by @p node is suppressed by
3532 /// at least of suppression specifications associated to the current
3533 /// ABIXML reader.
3534 static bool
3535 type_is_suppressed(const reader& rdr, xmlNodePtr node)
3536 {
3537  string type_name;
3538  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
3539  type_name = xml::unescape_xml_string(CHAR_STR(s));
3540 
3541  location type_location;
3542  read_location(rdr, node, type_location);
3543 
3544  scope_decl* scope = rdr.get_cur_scope();
3545 
3546  string qualified_name = build_qualified_name(scope, type_name);
3547 
3548  bool type_is_private = false;
3549  return suppr::is_type_suppressed(rdr, qualified_name, type_location,
3550  type_is_private,
3551  /*require_drop_property=*/true);
3552 }
3553 
3554 /// Build a @ref var_decl out of a an XML node that describes it iff
3555 /// the variable denoted by the XML node is not suppressed by a
3556 /// suppression specification associated to the current ABIXML reader.
3557 ///
3558 /// @param rdr the ABIXML reader to use.
3559 ///
3560 /// @param node the XML node for the variable to consider.
3561 ///
3562 /// @parm add_to_current_scope whether to add the built @ref var_decl
3563 /// to the current scope or not.
3564 ///
3565 /// @return true iff the @ref var_decl was built.
3566 static var_decl_sptr
3567 build_var_decl_if_not_suppressed(reader& rdr,
3568  const xmlNodePtr node,
3569  bool add_to_current_scope)
3570 {
3571  var_decl_sptr var;
3572  if (!variable_is_suppressed(rdr, node))
3573  var = build_var_decl(rdr, node, add_to_current_scope);
3574  return var;
3575 }
3576 
3577 /// Test if a variable denoted by its XML node is suppressed by a
3578 /// suppression specification that is present in a given ABIXML reader.
3579 ///
3580 /// @param rdr the ABIXML reader to consider.
3581 ///
3582 /// @param node the XML node of the variable to consider.
3583 ///
3584 /// @return true iff the variable denoted by @p node is suppressed.
3585 static bool
3586 variable_is_suppressed(const reader& rdr, xmlNodePtr node)
3587 {
3588  string name;
3589  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
3590  name = xml::unescape_xml_string(CHAR_STR(s));
3591 
3592  string linkage_name;
3593  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "mangled-name"))
3594  linkage_name = xml::unescape_xml_string(CHAR_STR(s));
3595 
3596  scope_decl* scope = rdr.get_cur_scope();
3597 
3598  string qualified_name = build_qualified_name(scope, name);
3599 
3600  return suppr::is_variable_suppressed(rdr, qualified_name, linkage_name);
3601 }
3602 
3603 /// Test if a variable in a particular scope is suppressed by a
3604 /// suppression specification that is present in a given ABIXML reader.
3605 ///
3606 /// @parm rdr the ABIXML reader to consider.
3607 ///
3608 /// @param scope the scope of the variable to consider.
3609 ///
3610 /// @param v the variable to consider.
3611 ///
3612 /// @return true iff the variable @p v is suppressed.
3613 static bool
3614 variable_is_suppressed(const reader& rdr,
3615  const scope_decl* scope,
3616  const var_decl& v)
3617 {
3618  string qualified_name = build_qualified_name(scope, v.get_name());
3619  return suppr::is_variable_suppressed(rdr, qualified_name,
3620  v.get_linkage_name());
3621 }
3622 
3623 /// Build pointer to var_decl from a 'var-decl' xml Node
3624 ///
3625 /// @param rdr the context of the parsing.
3626 ///
3627 /// @param node the xml node to build the var_decl from.
3628 ///
3629 /// @return a pointer to a newly built var_decl upon successful
3630 /// completion, a null pointer otherwise.
3631 static shared_ptr<var_decl>
3632 build_var_decl(reader& rdr,
3633  const xmlNodePtr node,
3634  bool add_to_current_scope)
3635 {
3636  shared_ptr<var_decl> nil;
3637 
3638  if (!xmlStrEqual(node->name, BAD_CAST("var-decl")))
3639  return nil;
3640 
3641  string name;
3642  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
3643  name = xml::unescape_xml_string(CHAR_STR(s));
3644 
3645  string type_id;
3646  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
3647  type_id = CHAR_STR(s);
3648  type_base_sptr underlying_type = rdr.build_or_get_type_decl(type_id,
3649  true);
3650  ABG_ASSERT(underlying_type);
3651 
3652  string mangled_name;
3653  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "mangled-name"))
3654  mangled_name = xml::unescape_xml_string(CHAR_STR(s));
3655 
3656  decl_base::visibility vis = decl_base::VISIBILITY_NONE;
3657  read_visibility(node, vis);
3658 
3659  decl_base::binding bind = decl_base::BINDING_NONE;
3660  read_binding(node, bind);
3661 
3662  location locus;
3663  read_location(rdr, node, locus);
3664 
3665  var_decl_sptr decl(new var_decl(name, underlying_type,
3666  locus, mangled_name,
3667  vis, bind));
3668  maybe_set_artificial_location(rdr, node, decl);
3669 
3670  elf_symbol_sptr sym = build_elf_symbol_from_reference(rdr, node);
3671  if (sym)
3672  decl->set_symbol(sym);
3673 
3674  rdr.push_decl_to_current_scope(decl, add_to_current_scope);
3675  if (add_to_current_scope)
3676  {
3677  // This variable is really being kept in the IR, so let's record
3678  // that it's using its type.
3679  RECORD_ARTIFACT_AS_USED_BY(rdr, underlying_type, decl);
3680  }
3681 
3682  if (decl->get_symbol() && decl->get_symbol()->is_public())
3683  decl->set_is_in_public_symbol_table(true);
3684 
3685  return decl;
3686 }
3687 
3688 /// Build a type_decl from a "type-decl" XML Node.
3689 ///
3690 /// @param rdr the context of the parsing.
3691 ///
3692 /// @param node the XML node to build the type_decl from.
3693 ///
3694 /// @param add_to_current_scope if set to yes, the resulting of
3695 /// this function is added to its current scope.
3696 ///
3697 /// @return a pointer to type_decl upon successful completion, a null
3698 /// pointer otherwise.
3699 static shared_ptr<type_decl>
3700 build_type_decl(reader& rdr,
3701  const xmlNodePtr node,
3702  bool add_to_current_scope)
3703 {
3704  shared_ptr<type_decl> nil;
3705 
3706  if (!xmlStrEqual(node->name, BAD_CAST("type-decl")))
3707  return nil;
3708 
3709  if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
3710  {
3711  type_decl_sptr result = dynamic_pointer_cast<type_decl>(d);
3712  ABG_ASSERT(result);
3713  return result;
3714  }
3715 
3716  string name;
3717  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
3718  name = xml::unescape_xml_string(CHAR_STR(s));
3719 
3720  string id;
3721  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
3722  id = CHAR_STR(s);
3723  ABG_ASSERT(!id.empty());
3724 
3725  size_t size_in_bits= 0;
3726  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "size-in-bits"))
3727  size_in_bits = atoi(CHAR_STR(s));
3728 
3729  size_t alignment_in_bits = 0;
3730  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "alignment-in-bits"))
3731  alignment_in_bits = atoi(CHAR_STR(s));
3732 
3733  bool is_decl_only = false;
3734  read_is_declaration_only(node, is_decl_only);
3735 
3736  location loc;
3737  read_location(rdr, node, loc);
3738 
3739  bool is_anonymous = false;
3740  read_is_anonymous(node, is_anonymous);
3741 
3742  if (type_base_sptr d = rdr.get_type_decl(id))
3743  {
3744  // I've seen instances of DSOs where a type_decl would appear
3745  // several times. Hugh.
3746  type_decl_sptr ty = dynamic_pointer_cast<type_decl>(d);
3747  ABG_ASSERT(ty);
3748  ABG_ASSERT(!name.empty());
3749  ABG_ASSERT(!ty->get_name().empty());
3750  ABG_ASSERT(ty->get_size_in_bits() == size_in_bits);
3751  ABG_ASSERT(ty->get_alignment_in_bits() == alignment_in_bits);
3752  return ty;
3753  }
3754 
3755  const environment& env = rdr.get_environment();
3756  type_decl_sptr decl;
3757  if (name == env.get_variadic_parameter_type_name())
3758  decl = is_type_decl(env.get_variadic_parameter_type());
3759  else
3760  decl.reset(new type_decl(env, name, size_in_bits,
3761  alignment_in_bits, loc));
3762  maybe_set_artificial_location(rdr, node, decl);
3763  decl->set_is_anonymous(is_anonymous);
3764  decl->set_is_declaration_only(is_decl_only);
3765  if (rdr.push_and_key_type_decl(decl, id, add_to_current_scope))
3766  {
3767  rdr.map_xml_node_to_decl(node, decl);
3768  return decl;
3769  }
3770 
3771  return nil;
3772 }
3773 
3774 /// Build a qualified_type_def from a 'qualified-type-def' xml node.
3775 ///
3776 /// @param rdr the context of the parsing.
3777 ///
3778 /// @param node the xml node to build the qualified_type_def from.
3779 ///
3780 /// @param add_to_current_scope if set to yes, the resulting of this
3781 /// function is added to its current scope.
3782 ///
3783 /// @return a pointer to a newly built qualified_type_def upon
3784 /// successful completion, a null pointer otherwise.
3785 static qualified_type_def_sptr
3786 build_qualified_type_decl(reader& rdr,
3787  const xmlNodePtr node,
3788  bool add_to_current_scope)
3789 {
3790  qualified_type_def_sptr nil;
3791  if (!xmlStrEqual(node->name, BAD_CAST("qualified-type-def")))
3792  return nil;
3793 
3794  if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
3795  {
3796  qualified_type_def_sptr result =
3797  dynamic_pointer_cast<qualified_type_def>(d);
3798  ABG_ASSERT(result);
3799  return result;
3800  }
3801 
3802  string id;
3803  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE (node, "id"))
3804  id = CHAR_STR(s);
3805 
3806  ABG_ASSERT(!id.empty());
3807 
3808  location loc;
3809  read_location(rdr, node, loc);
3810 
3811  qualified_type_def::CV cv = qualified_type_def::CV_NONE;
3812  string const_str;
3813  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "const"))
3814  const_str = CHAR_STR(s);
3815  bool const_cv = const_str == "yes";
3816 
3817  string volatile_str;
3818  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "volatile"))
3819  volatile_str = CHAR_STR(s);
3820  bool volatile_cv = volatile_str == "yes";
3821 
3822  string restrict_str;
3823  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "restrict"))
3824  restrict_str = CHAR_STR(s);
3825  bool restrict_cv = restrict_str == "yes";
3826 
3827  if (const_cv)
3828  cv = cv | qualified_type_def::CV_CONST;
3829  if (volatile_cv)
3830  cv = cv | qualified_type_def::CV_VOLATILE;
3831  if (restrict_cv)
3832  cv = cv | qualified_type_def::CV_RESTRICT;
3833 
3834  string type_id;
3835  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
3836  type_id = CHAR_STR(s);
3837  ABG_ASSERT(!type_id.empty());
3838 
3839  shared_ptr<type_base> underlying_type =
3840  rdr.build_or_get_type_decl(type_id, true);
3841  ABG_ASSERT(underlying_type);
3842 
3843  qualified_type_def_sptr decl;
3844  if (type_base_sptr t = rdr.get_type_decl(id))
3845  {
3846  decl = is_qualified_type(t);
3847  ABG_ASSERT(decl);
3848  }
3849  else
3850  {
3851  decl.reset(new qualified_type_def(underlying_type, cv, loc));
3852  maybe_set_artificial_location(rdr, node, decl);
3853  rdr.push_and_key_type_decl(decl, id, add_to_current_scope);
3854  RECORD_ARTIFACT_AS_USED_BY(rdr, underlying_type, decl);
3855  }
3856 
3857  rdr.map_xml_node_to_decl(node, decl);
3858 
3859  return decl;
3860 }
3861 
3862 /// Build a pointer_type_def from a 'pointer-type-def' xml node.
3863 ///
3864 /// @param rdr the context of the parsing.
3865 ///
3866 /// @param node the xml node to build the pointer_type_def from.
3867 ///
3868 /// @param add_to_current_scope if set to yes, the resulting of
3869 /// this function is added to its current scope.
3870 ///
3871 /// @return a pointer to a newly built pointer_type_def upon
3872 /// successful completion, a null pointer otherwise.
3873 static pointer_type_def_sptr
3874 build_pointer_type_def(reader& rdr,
3875  const xmlNodePtr node,
3876  bool add_to_current_scope)
3877 {
3878 
3879  shared_ptr<pointer_type_def> nil;
3880 
3881  if (!xmlStrEqual(node->name, BAD_CAST("pointer-type-def")))
3882  return nil;
3883 
3884  if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
3885  {
3886  pointer_type_def_sptr result =
3887  dynamic_pointer_cast<pointer_type_def>(d);
3888  ABG_ASSERT(result);
3889  return result;
3890  }
3891 
3892  string id;
3893  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
3894  id = CHAR_STR(s);
3895  ABG_ASSERT(!id.empty());
3896 
3897  if (type_base_sptr t = rdr.get_type_decl(id))
3898  {
3900  ABG_ASSERT(result);
3901  return result;
3902  }
3903 
3904  string type_id;
3905  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
3906  type_id = CHAR_STR(s);
3907 
3908  size_t size_in_bits = rdr.get_translation_unit()->get_address_size();
3909  size_t alignment_in_bits = 0;
3910  read_size_and_alignment(node, size_in_bits, alignment_in_bits);
3911  location loc;
3912  read_location(rdr, node, loc);
3913 
3914  // Create the pointer type /before/ the pointed-to type. After the
3915  // creation, the type is 'keyed' using rdr.push_and_key_type_decl.
3916  // This means that the type can be retrieved from its type ID. This
3917  // is so that if the pointed-to type indirectly uses this pointer
3918  // type (via recursion) then that is made possible.
3919  pointer_type_def_sptr t(new pointer_type_def(rdr.get_environment(),
3920  size_in_bits,
3921  alignment_in_bits,
3922  loc));
3923  maybe_set_artificial_location(rdr, node, t);
3924 
3925  if (rdr.push_and_key_type_decl(t, id, add_to_current_scope))
3926  rdr.map_xml_node_to_decl(node, t);
3927 
3928  type_base_sptr pointed_to_type =
3929  rdr.build_or_get_type_decl(type_id, true);
3930  ABG_ASSERT(pointed_to_type);
3931 
3932  t->set_pointed_to_type(pointed_to_type);
3933  RECORD_ARTIFACT_AS_USED_BY(rdr, pointed_to_type, t);
3934  return t;
3935 }
3936 
3937 /// Build a reference_type_def from a pointer to 'reference-type-def'
3938 /// xml node.
3939 ///
3940 /// @param rdr the context of the parsing.
3941 ///
3942 /// @param node the xml node to build the reference_type_def from.
3943 ///
3944 /// @param add_to_current_scope if set to yes, the resulting of
3945 /// this function is added to its current scope.
3946 ///
3947 /// @return a pointer to a newly built reference_type_def upon
3948 /// successful completio, a null pointer otherwise.
3949 static shared_ptr<reference_type_def>
3950 build_reference_type_def(reader& rdr,
3951  const xmlNodePtr node,
3952  bool add_to_current_scope)
3953 {
3954  shared_ptr<reference_type_def> nil;
3955 
3956  if (!xmlStrEqual(node->name, BAD_CAST("reference-type-def")))
3957  return nil;
3958 
3959  if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
3960  {
3961  reference_type_def_sptr result =
3962  dynamic_pointer_cast<reference_type_def>(d);
3963  ABG_ASSERT(result);
3964  return result;
3965  }
3966 
3967  string id;
3968  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
3969  id = CHAR_STR(s);
3970  ABG_ASSERT(!id.empty());
3971 
3972  if (type_base_sptr d = rdr.get_type_decl(id))
3973  {
3975  ABG_ASSERT(ty);
3976  return ty;
3977  }
3978 
3979  location loc;
3980  read_location(rdr, node, loc);
3981  string kind;
3982  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "kind"))
3983  kind = CHAR_STR(s); // this should be either "lvalue" or "rvalue".
3984  bool is_lvalue = kind == "lvalue";
3985 
3986  size_t size_in_bits = rdr.get_translation_unit()->get_address_size();
3987  size_t alignment_in_bits = 0;
3988  read_size_and_alignment(node, size_in_bits, alignment_in_bits);
3989 
3990  string type_id;
3991  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
3992  type_id = CHAR_STR(s);
3993  ABG_ASSERT(!type_id.empty());
3994 
3995  // Create the reference type /before/ the pointed-to type. After
3996  // the creation, the type is 'keyed' using
3997  // rdr.push_and_key_type_decl. This means that the type can be
3998  // retrieved from its type ID. This is so that if the pointed-to
3999  // type indirectly uses this reference type (via recursion) then
4000  // that is made possible.
4001  reference_type_def_sptr t(new reference_type_def(rdr.get_environment(),
4002  is_lvalue, size_in_bits,
4003  alignment_in_bits, loc));
4004  maybe_set_artificial_location(rdr, node, t);
4005  if (rdr.push_and_key_type_decl(t, id, add_to_current_scope))
4006  rdr.map_xml_node_to_decl(node, t);
4007 
4008  type_base_sptr pointed_to_type =
4009  rdr.build_or_get_type_decl(type_id,/*add_to_current_scope=*/ true);
4010  ABG_ASSERT(pointed_to_type);
4011  t->set_pointed_to_type(pointed_to_type);
4012  RECORD_ARTIFACT_AS_USED_BY(rdr, pointed_to_type, t);
4013 
4014  return t;
4015 }
4016 
4017 /// Build a function_type from a pointer to 'function-type'
4018 /// xml node.
4019 ///
4020 /// @param rdr the context of the parsing.
4021 ///
4022 /// @param node the xml node to build the function_type from.
4023 ///
4024 /// @param add_to_current_scope if set to yes, the result of
4025 /// this function is added to its current scope.
4026 ///
4027 /// @return a pointer to a newly built function_type upon
4028 /// successful completion, a null pointer otherwise.
4029 static function_type_sptr
4030 build_function_type(reader& rdr,
4031  const xmlNodePtr node,
4032  bool /*add_to_current_scope*/)
4033 {
4034  function_type_sptr nil;
4035 
4036  if (!xmlStrEqual(node->name, BAD_CAST("function-type")))
4037  return nil;
4038 
4039  string id;
4040  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
4041  id = CHAR_STR(s);
4042  ABG_ASSERT(!id.empty());
4043 
4044  string method_class_id;
4045  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "method-class-id"))
4046  method_class_id = CHAR_STR(s);
4047 
4048  bool is_method_t = !method_class_id.empty();
4049 
4050  size_t size = rdr.get_translation_unit()->get_address_size(), align = 0;
4051  read_size_and_alignment(node, size, align);
4052 
4053  const environment& env = rdr.get_environment();
4054  std::vector<shared_ptr<function_decl::parameter> > parms;
4055  type_base_sptr return_type = env.get_void_type();
4056 
4057  class_or_union_sptr method_class_type;
4058  if (is_method_t)
4059  {
4060  method_class_type =
4061  is_class_or_union_type(rdr.build_or_get_type_decl(method_class_id,
4062  /*add_decl_to_scope=*/true));
4063  ABG_ASSERT(method_class_type);
4064  }
4065 
4066  function_type_sptr fn_type(is_method_t
4067  ? new method_type(method_class_type,
4068  /*is_const=*/false,
4069  size, align)
4070  : new function_type(return_type,
4071  parms, size, align));
4072 
4073  rdr.get_translation_unit()->bind_function_type_life_time(fn_type);
4074  rdr.key_type_decl(fn_type, id);
4075  RECORD_ARTIFACTS_AS_USED_IN_FN_TYPE(rdr, fn_type);
4076 
4077  for (xmlNodePtr n = xmlFirstElementChild(node);
4078  n;
4079  n = xmlNextElementSibling(n))
4080  {
4081  if (xmlStrEqual(n->name, BAD_CAST("parameter")))
4082  {
4084  build_function_parameter(rdr, n))
4085  parms.push_back(p);
4086  }
4087  else if (xmlStrEqual(n->name, BAD_CAST("return")))
4088  {
4089  string type_id;
4090  if (xml_char_sptr s =
4091  xml::build_sptr(xmlGetProp(n, BAD_CAST("type-id"))))
4092  type_id = CHAR_STR(s);
4093  if (!type_id.empty())
4094  fn_type->set_return_type(rdr.build_or_get_type_decl
4095  (type_id, true));
4096  }
4097  }
4098 
4099  fn_type->set_parameters(parms);
4100 
4101  return fn_type;
4102 }
4103 
4104 /// Build a array_type_def::subrange_type from a 'subrange' xml node.
4105 ///
4106 /// @param rdr the context of the parsing.
4107 ///
4108 /// @param node the xml node to build the
4109 /// array_type_def::subrange_type from.
4110 ///
4111 ///
4112 /// @return a pointer to a newly built array_type_def::subrange_type
4113 /// upon successful completion, a null pointer otherwise.
4115 build_subrange_type(reader& rdr,
4116  const xmlNodePtr node,
4117  bool add_to_current_scope)
4118 {
4120 
4121  if (!node || !xmlStrEqual(node->name, BAD_CAST("subrange")))
4122  return nil;
4123 
4124  if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
4125  {
4127  dynamic_pointer_cast<array_type_def::subrange_type>(d);
4128  ABG_ASSERT(result);
4129  return result;
4130  }
4131 
4132  string id;
4133  // Note that in early implementations, the subrange didn't carry its
4134  // own ID as the subrange was just a detail of an array. So we
4135  // still need to support the abixml emitted by those early
4136  // implementations.
4137  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
4138  id = CHAR_STR(s);
4139 
4140  if (!id.empty())
4141  if (type_base_sptr d = rdr.get_type_decl(id))
4142  {
4144  ABG_ASSERT(ty);
4145  return ty;
4146  }
4147 
4148  string name;
4149  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
4150  name = CHAR_STR(s);
4151 
4152  uint64_t length = 0;
4153  string length_str;
4154  bool is_infinite = false;
4155  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "length"))
4156  {
4157  if (string(CHAR_STR(s)) == "infinite" || string(CHAR_STR(s)) == "unknown")
4158  is_infinite = true;
4159  else
4160  length = strtoull(CHAR_STR(s), NULL, 0);
4161  }
4162 
4163  int64_t lower_bound = 0, upper_bound = 0;
4164  bool bounds_present = false;
4165  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "lower-bound"))
4166  {
4167  lower_bound = strtoll(CHAR_STR(s), NULL, 0);
4168  s = XML_NODE_GET_ATTRIBUTE(node, "upper-bound");
4169  if (!string(CHAR_STR(s)).empty())
4170  upper_bound = strtoll(CHAR_STR(s), NULL, 0);
4171  bounds_present = true;
4172  ABG_ASSERT(is_infinite
4173  || (length == (uint64_t) upper_bound - lower_bound + 1));
4174  }
4175 
4176  string underlying_type_id;
4177  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
4178  underlying_type_id = CHAR_STR(s);
4179 
4180  type_base_sptr underlying_type;
4181  if (!underlying_type_id.empty())
4182  {
4183  underlying_type = rdr.build_or_get_type_decl(underlying_type_id, true);
4184  ABG_ASSERT(underlying_type);
4185  }
4186 
4187  location loc;
4188  read_location(rdr, node, loc);
4189 
4190  // Note that DWARF would actually have a lower_bound of -1 for an
4191  // array of length 0.
4192  array_type_def::subrange_type::bound_value max_bound;
4193  array_type_def::subrange_type::bound_value min_bound;
4194  if (!is_infinite)
4195  if (length > 0)
4196  // By default, if no 'lower-bound/upper-bound' attributes are
4197  // set, we assume that the lower bound is 0 and the upper bound
4198  // is length - 1.
4199  max_bound.set_signed(length - 1);
4200 
4201  if (bounds_present)
4202  {
4203  // So lower_bound/upper_bound are set. Let's set them rather
4204  // than assume that mind_bound is zero.
4205  min_bound.set_signed(lower_bound);
4206  max_bound.set_signed(upper_bound);
4207  }
4208 
4210  (new array_type_def::subrange_type(rdr.get_environment(),
4211  name, min_bound, max_bound,
4212  underlying_type, loc));
4213  maybe_set_artificial_location(rdr, node, p);
4214  p->is_infinite(is_infinite);
4215 
4216  if (rdr.push_and_key_type_decl(p, id, add_to_current_scope))
4217  rdr.map_xml_node_to_decl(node, p);
4218 
4219  return p;
4220 }
4221 
4222 /// Build a array_type_def from a 'array-type-def' xml node.
4223 ///
4224 /// @param rdr the context of the parsing.
4225 ///
4226 /// @param node the xml node to build the array_type_def from.
4227 ///
4228 /// @param add_to_current_scope if set to yes, the resulting of
4229 /// this function is added to its current scope.
4230 ///
4231 /// @return a pointer to a newly built array_type_def upon
4232 /// successful completion, a null pointer otherwise.
4233 static array_type_def_sptr
4234 build_array_type_def(reader& rdr,
4235  const xmlNodePtr node,
4236  bool add_to_current_scope)
4237 {
4238 
4239  array_type_def_sptr nil;
4240 
4241  if (!xmlStrEqual(node->name, BAD_CAST("array-type-def")))
4242  return nil;
4243 
4244  if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
4245  {
4246  array_type_def_sptr result =
4247  dynamic_pointer_cast<array_type_def>(d);
4248  ABG_ASSERT(result);
4249  return result;
4250  }
4251 
4252  string id;
4253  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
4254  id = CHAR_STR(s);
4255  ABG_ASSERT(!id.empty());
4256 
4257  if (type_base_sptr d = rdr.get_type_decl(id))
4258  {
4260  ABG_ASSERT(ty);
4261  return ty;
4262  }
4263 
4264  int dimensions = 0;
4265  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "dimensions"))
4266  dimensions = atoi(CHAR_STR(s));
4267 
4268  string type_id;
4269  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
4270  type_id = CHAR_STR(s);
4271 
4272  // maybe building the type of array elements triggered building this
4273  // one in the mean time ...
4274  if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
4275  {
4276  array_type_def_sptr result =
4277  dynamic_pointer_cast<array_type_def>(d);
4278  ABG_ASSERT(result);
4279  return result;
4280  }
4281 
4282  size_t size_in_bits = 0, alignment_in_bits = 0;
4283  bool has_size_in_bits = false;
4284  char *endptr;
4285 
4286  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "size-in-bits"))
4287  {
4288  size_in_bits = strtoull(CHAR_STR(s), &endptr, 0);
4289  if (*endptr != '\0')
4290  {
4291  if (!strcmp(CHAR_STR(s), "infinite")
4292  ||!strcmp(CHAR_STR(s), "unknown"))
4293  size_in_bits = (size_t) -1;
4294  else
4295  return nil;
4296  }
4297  has_size_in_bits = true;
4298  }
4299 
4300  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "alignment-in-bits"))
4301  {
4302  alignment_in_bits = strtoull(CHAR_STR(s), &endptr, 0);
4303  if (*endptr != '\0')
4304  return nil;
4305  }
4306 
4307  location loc;
4308  read_location(rdr, node, loc);
4310 
4311  for (xmlNodePtr n = xmlFirstElementChild(node);
4312  n;
4313  n = xmlNextElementSibling(n))
4314  if (xmlStrEqual(n->name, BAD_CAST("subrange")))
4315  {
4317  build_subrange_type(rdr, n, /*add_to_current_scope=*/true))
4318  {
4319  MAYBE_MAP_TYPE_WITH_TYPE_ID(s, n);
4320  if (add_to_current_scope)
4321  {
4322  add_decl_to_scope(s, rdr.get_cur_scope());
4323  rdr.maybe_canonicalize_type(s);
4324  }
4325  subranges.push_back(s);
4326  }
4327  }
4328 
4329  // The type of array elements.
4330  type_base_sptr type =
4331  rdr.build_or_get_type_decl(type_id, true);
4332  ABG_ASSERT(type);
4333 
4334  array_type_def_sptr ar_type(new array_type_def(type, subranges, loc));
4335  maybe_set_artificial_location(rdr, node, ar_type);
4336  if (rdr.push_and_key_type_decl(ar_type, id, add_to_current_scope))
4337  rdr.map_xml_node_to_decl(node, ar_type);
4338  RECORD_ARTIFACT_AS_USED_BY(rdr, type, ar_type);
4339 
4340  if (dimensions != ar_type->get_dimension_count()
4341  || (alignment_in_bits
4342  != ar_type->get_element_type()->get_alignment_in_bits()))
4343  return nil;
4344 
4345  if (has_size_in_bits && size_in_bits != (size_t) -1
4346  && size_in_bits != ar_type->get_size_in_bits())
4347  {
4348  // We have a potential discrepancy between calculated and recorded sizes.
4349  size_t element_size = ar_type->get_element_type()->get_size_in_bits();
4350  if (element_size && element_size != (size_t)-1)
4351  {
4352  // Older versions miscalculated multidimensional array sizes.
4353  size_t bad_count = 0;
4354  for (vector<array_type_def::subrange_sptr>::const_iterator i =
4355  subranges.begin();
4356  i != subranges.end();
4357  ++i)
4358  bad_count += (*i)->get_length();
4359  if (size_in_bits == bad_count * element_size)
4360  {
4361  static bool reported = false;
4362  if (!reported)
4363  {
4364  std::cerr << "notice: Found incorrectly calculated array "
4365  << "sizes in XML - this is benign.\nOlder versions "
4366  << "of libabigail miscalculated multidimensional "
4367  << "array sizes." << std::endl;
4368  reported = true;
4369  }
4370  }
4371  else
4372  {
4373  std::cerr << "error: Found incorrectly calculated array size in "
4374  << "XML (id=\"" << id << "\")." << std::endl;
4376  }
4377  }
4378  }
4379 
4380  return ar_type;
4381 }
4382 
4383 /// Build an @ref enum_type_decl from the XML node that represents it,
4384 /// if it was not suppressed by a supression specification present in
4385 /// the current reader.
4386 ///
4387 /// @param rdr the reader to take into account.
4388 ///
4389 /// @param node the XML node representing the @ref enum_type_decl to
4390 /// build.
4391 ///
4392 /// @param add_to_current_scope whether to add the built @ref
4393 /// enum_type_decl to the current scope.
4394 ///
4395 /// @return the newly built @ref enum_type_decl iff it was effectively
4396 /// built.
4397 static enum_type_decl_sptr
4398 build_enum_type_decl_if_not_suppressed(reader& rdr,
4399  const xmlNodePtr node,
4400  bool add_to_current_scope)
4401 {
4402  enum_type_decl_sptr enum_type;
4403  if (!type_is_suppressed(rdr, node))
4404  enum_type = build_enum_type_decl(rdr, node, add_to_current_scope);
4405  return enum_type;
4406 }
4407 
4408 /// Build an enum_type_decl from an 'enum-type-decl' xml node.
4409 ///
4410 /// @param rdr the context of the parsing.
4411 ///
4412 /// @param node the xml node to build the enum_type_decl from.
4413 ///
4414 /// param add_to_current_scope if set to yes, the resulting of this
4415 /// function is added to its current scope.
4416 ///
4417 /// @return a pointer to a newly built enum_type_decl upon successful
4418 /// completion, a null pointer otherwise.
4419 static enum_type_decl_sptr
4420 build_enum_type_decl(reader& rdr,
4421  const xmlNodePtr node,
4422  bool add_to_current_scope)
4423 {
4424  enum_type_decl_sptr nil;
4425 
4426  if (!xmlStrEqual(node->name, BAD_CAST("enum-decl")))
4427  return nil;
4428 
4429  if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
4430  {
4431  enum_type_decl_sptr result =
4432  dynamic_pointer_cast<enum_type_decl>(d);
4433  ABG_ASSERT(result);
4434  return result;
4435  }
4436 
4437  string name;
4438  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
4439  name = xml::unescape_xml_string(CHAR_STR(s));
4440 
4441  string linkage_name;
4442  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "linkage-name"))
4443  linkage_name = xml::unescape_xml_string(CHAR_STR(s));
4444 
4445  location loc;
4446  read_location(rdr, node, loc);
4447 
4448  bool is_decl_only = false;
4449  read_is_declaration_only(node, is_decl_only);
4450 
4451  bool is_anonymous = false;
4452  read_is_anonymous(node, is_anonymous);
4453 
4454  bool is_artificial = false;
4455  read_is_artificial(node, is_artificial);
4456 
4457  string id;
4458  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
4459  id = CHAR_STR(s);
4460 
4461  ABG_ASSERT(!id.empty());
4462 
4463  string base_type_id;
4465  for (xmlNodePtr n = xmlFirstElementChild(node);
4466  n;
4467  n = xmlNextElementSibling(n))
4468  {
4469  if (xmlStrEqual(n->name, BAD_CAST("underlying-type")))
4470  {
4471  xml_char_sptr a = xml::build_sptr(xmlGetProp(n, BAD_CAST("type-id")));
4472  if (a)
4473  base_type_id = CHAR_STR(a);
4474  continue;
4475  }
4476  else if (xmlStrEqual(n->name, BAD_CAST("enumerator")))
4477  {
4478  string name;
4479  int64_t value = 0;
4480 
4481  xml_char_sptr a = xml::build_sptr(xmlGetProp(n, BAD_CAST("name")));
4482  if (a)
4483  name = xml::unescape_xml_string(CHAR_STR(a));
4484 
4485  a = xml::build_sptr(xmlGetProp(n, BAD_CAST("value")));
4486  if (a)
4487  {
4488  value = strtoll(CHAR_STR(a), NULL, 0);
4489  // when strtoll encounters overflow or underflow, errno
4490  // is set to ERANGE and the returned value is either
4491  // LLONG_MIN or LLONG_MAX.
4492  if ((errno == ERANGE)
4493  && (value == LLONG_MIN || value == LLONG_MAX))
4494  return nil;
4495  }
4496 
4497  enums.push_back(enum_type_decl::enumerator(name, value));
4498  }
4499  }
4500 
4501  type_base_sptr underlying_type =
4502  rdr.build_or_get_type_decl(base_type_id, true);
4503  ABG_ASSERT(underlying_type);
4504 
4505  enum_type_decl_sptr t(new enum_type_decl(name, loc,
4506  underlying_type,
4507  enums, linkage_name));
4508  maybe_set_artificial_location(rdr, node, t);
4509  t->set_is_anonymous(is_anonymous);
4510  t->set_is_artificial(is_artificial);
4511  t->set_is_declaration_only(is_decl_only);
4512  if (rdr.push_and_key_type_decl(t, id, add_to_current_scope))
4513  {
4514  maybe_set_naming_typedef(rdr, node, t);
4515  rdr.map_xml_node_to_decl(node, t);
4516  RECORD_ARTIFACT_AS_USED_BY(rdr, underlying_type, t);
4517  return t;
4518  }
4519 
4520  return nil;
4521 }
4522 
4523 /// Build a typedef_decl from a 'typedef-decl' xml node.
4524 ///
4525 /// @param rdr the context of the parsing.
4526 ///
4527 /// @param node the xml node to build the typedef_decl from.
4528 ///
4529 /// @return a pointer to a newly built typedef_decl upon successful
4530 /// completion, a null pointer otherwise.
4531 static shared_ptr<typedef_decl>
4532 build_typedef_decl(reader& rdr,
4533  const xmlNodePtr node,
4534  bool add_to_current_scope)
4535 {
4536  shared_ptr<typedef_decl> nil;
4537 
4538  if (!xmlStrEqual(node->name, BAD_CAST("typedef-decl")))
4539  return nil;
4540 
4541  if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
4542  {
4543  typedef_decl_sptr result = is_typedef(d);
4544  ABG_ASSERT(result);
4545  return result;
4546  }
4547 
4548  string id;
4549  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
4550  id = CHAR_STR(s);
4551  ABG_ASSERT(!id.empty());
4552 
4553  if (type_base_sptr t = rdr.get_type_decl(id))
4554  {
4555  typedef_decl_sptr result = is_typedef(t);
4556  ABG_ASSERT(result);
4557  return result;
4558  }
4559 
4560  string name;
4561  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
4562  name = xml::unescape_xml_string(CHAR_STR(s));
4563 
4564  location loc;
4565  read_location(rdr, node, loc);
4566 
4567  string type_id;
4568  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
4569  type_id = CHAR_STR(s);
4570  ABG_ASSERT(!type_id.empty());
4571 
4572  type_base_sptr underlying_type(rdr.build_or_get_type_decl(type_id, true));
4573  ABG_ASSERT(underlying_type);
4574 
4575  typedef_decl_sptr t(new typedef_decl(name, underlying_type, loc));
4576  maybe_set_artificial_location(rdr, node, t);
4577  rdr.push_and_key_type_decl(t, id, add_to_current_scope);
4578  rdr.map_xml_node_to_decl(node, t);
4579  RECORD_ARTIFACT_AS_USED_BY(rdr, underlying_type, t);
4580 
4581  return t;
4582 }
4583 
4584 /// Build a class from its XML node if it is not suppressed by a
4585 /// suppression specification that is present in the ABIXML reader.
4586 ///
4587 /// @param rdr the ABIXML reader to consider.
4588 ///
4589 /// @param node the XML node to consider.
4590 ///
4591 /// @param add_to_current_scope whether to add the built class to the
4592 /// current context or not.
4593 ///
4594 /// @return true iff the class was built.
4595 static class_decl_sptr
4596 build_class_decl_if_not_suppressed(reader& rdr,
4597  const xmlNodePtr node,
4598  bool add_to_current_scope)
4599 {
4600  class_decl_sptr class_type;
4601  if (!type_is_suppressed(rdr, node))
4602  class_type = build_class_decl(rdr, node, add_to_current_scope);
4603  return class_type;
4604 }
4605 
4606 /// Build a @ref union_decl from its XML node if it is not suppressed
4607 /// by a suppression specification that is present in the read
4608 /// context.
4609 ///
4610 /// @param rdr the ABIXML reader to consider.
4611 ///
4612 /// @param node the XML node to consider.
4613 ///
4614 /// @param add_to_current_scope whether to add the built @ref
4615 /// union_decl to the current context or not.
4616 ///
4617 /// @return true iff the @ref union_decl was built.
4618 static union_decl_sptr
4619 build_union_decl_if_not_suppressed(reader& rdr,
4620  const xmlNodePtr node,
4621  bool add_to_current_scope)
4622 {
4623  union_decl_sptr union_type;
4624  if (!type_is_suppressed(rdr, node))
4625  union_type = build_union_decl(rdr, node, add_to_current_scope);
4626  return union_type;
4627 }
4628 
4629 /// Build a class_decl from a 'class-decl' xml node.
4630 ///
4631 /// @param rdr the context of the parsing.
4632 ///
4633 /// @param node the xml node to build the class_decl from.
4634 ///
4635 /// @param add_to_current_scope if yes, the resulting class node
4636 /// hasn't triggered voluntarily the adding of the resulting
4637 /// class_decl_sptr to the current scope.
4638 ///
4639 /// @return a pointer to class_decl upon successful completion, a null
4640 /// pointer otherwise.
4641 static class_decl_sptr
4642 build_class_decl(reader& rdr,
4643  const xmlNodePtr node,
4644  bool add_to_current_scope)
4645 {
4646  class_decl_sptr nil;
4647 
4648  if (!xmlStrEqual(node->name, BAD_CAST("class-decl")))
4649  return nil;
4650 
4651  if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
4652  {
4653  class_decl_sptr result = dynamic_pointer_cast<class_decl>(d);
4654  ABG_ASSERT(result);
4655  return result;
4656  }
4657 
4658  string name;
4659  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
4660  name = xml::unescape_xml_string(CHAR_STR(s));
4661 
4662  size_t size_in_bits = 0, alignment_in_bits = 0;
4663  read_size_and_alignment(node, size_in_bits, alignment_in_bits);
4664 
4665  decl_base::visibility vis = decl_base::VISIBILITY_NONE;
4666  read_visibility(node, vis);
4667 
4668  bool is_artificial = false;
4669  read_is_artificial(node, is_artificial);
4670 
4671  string id;
4672  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
4673  id = CHAR_STR(s);
4674 
4675  location loc;
4676  read_location(rdr, node, loc);
4677 
4679  class_decl::data_members data_mbrs;
4680  class_decl::member_functions mbr_functions;
4681  class_decl::base_specs bases;
4682 
4683  class_decl_sptr decl;
4684 
4685  bool is_decl_only = false;
4686  read_is_declaration_only(node, is_decl_only);
4687 
4688  bool is_struct = false;
4689  read_is_struct(node, is_struct);
4690 
4691  bool is_anonymous = false;
4692  read_is_anonymous(node, is_anonymous);
4693 
4694  ABG_ASSERT(!id.empty());
4695 
4696  class_decl_sptr previous_definition, previous_declaration;
4697  if (!is_anonymous)
4698  if (type_base_sptr t = rdr.get_type_decl(id))
4699  {
4700  previous_definition = is_class_type(t);
4701  ABG_ASSERT(previous_definition);
4702  }
4703 
4704  const vector<type_base_sptr> *types_ptr = 0;
4705  if (!is_anonymous && !previous_definition)
4706  types_ptr = rdr.get_all_type_decls(id);
4707  if (types_ptr)
4708  {
4709  // Lets look at the previous declarations and the first previous
4710  // definition of this type that we've already seen while parsing
4711  // this corpus.
4712  for (vector<type_base_sptr>::const_iterator i = types_ptr->begin();
4713  i != types_ptr->end();
4714  ++i)
4715  {
4716  class_decl_sptr klass = is_class_type(*i);
4717  ABG_ASSERT(klass);
4718  if (klass->get_is_declaration_only()
4719  && !klass->get_definition_of_declaration())
4720  previous_declaration = klass;
4721  else if (!klass->get_is_declaration_only()
4722  && !previous_definition)
4723  previous_definition = klass;
4724  if (previous_definition && previous_declaration)
4725  break;
4726  }
4727 
4728  if (previous_declaration)
4729  ABG_ASSERT(previous_declaration->get_name() == name);
4730 
4731  if (previous_definition)
4732  ABG_ASSERT(previous_definition->get_name() == name);
4733 
4734  if (is_decl_only && previous_declaration)
4735  return previous_declaration;
4736  }
4737 
4738  const environment& env = rdr.get_environment();
4739 
4740  if (!is_decl_only && previous_definition)
4741  // We are in the case where we've read this class definition
4742  // before, but we might need to update it to add some new stuff to
4743  // it; we might thus find the new stuff to add in the current
4744  // (new) incarnation of that definition that we are currently
4745  // reading.
4746  decl = previous_definition;
4747  else
4748  {
4749  if (is_decl_only)
4750  {
4751  decl.reset(new class_decl(env, name, is_struct));
4752  if (size_in_bits)
4753  decl->set_size_in_bits(size_in_bits);
4754  if (is_anonymous)
4755  decl->set_is_anonymous(is_anonymous);
4756  decl->set_location(loc);
4757  }
4758  else
4759  decl.reset(new class_decl(env, name, size_in_bits, alignment_in_bits,
4760  is_struct, loc, vis, bases, mbrs,
4761  data_mbrs, mbr_functions, is_anonymous));
4762  }
4763 
4764  maybe_set_artificial_location(rdr, node, decl);
4765  decl->set_is_artificial(is_artificial);
4766 
4767  string def_id;
4768  bool is_def_of_decl = false;
4769  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "def-of-decl-id"))
4770  def_id = CHAR_STR(s);
4771 
4772  if (!def_id.empty())
4773  {
4774  decl_base_sptr d = is_decl(rdr.get_type_decl(def_id));
4775  if (d && d->get_is_declaration_only())
4776  {
4777  is_def_of_decl = true;
4778  decl->set_earlier_declaration(d);
4779  d->set_definition_of_declaration(decl);
4780  }
4781  }
4782 
4783  if (!is_decl_only
4784  && decl
4785  && !decl->get_is_declaration_only()
4786  && previous_declaration)
4787  {
4788  // decl is the definition of the previous declaration
4789  // previous_declaration.
4790  //
4791  // Let's link them.
4792  decl->set_earlier_declaration(is_decl(previous_declaration));
4793  for (vector<type_base_sptr>::const_iterator i = types_ptr->begin();
4794  i != types_ptr->end();
4795  ++i)
4796  {
4798  ABG_ASSERT(d);
4799  if (d->get_is_declaration_only()
4800  && !d->get_definition_of_declaration())
4801  {
4802  previous_declaration->set_definition_of_declaration(decl);
4803  is_def_of_decl = true;
4804  }
4805  }
4806  }
4807 
4808  if (is_decl_only && previous_definition)
4809  {
4810  // decl is a declaration of the previous definition
4811  // previous_definition. Let's link them.
4812  ABG_ASSERT(decl->get_is_declaration_only()
4813  && !decl->get_definition_of_declaration());
4814  decl->set_definition_of_declaration(previous_definition);
4815  }
4816 
4817  ABG_ASSERT(!is_decl_only || !is_def_of_decl);
4818 
4819  rdr.push_decl_to_current_scope(decl, add_to_current_scope);
4820 
4821  rdr.map_xml_node_to_decl(node, decl);
4822  rdr.key_type_decl(decl, id);
4823 
4824  // If this class has a naming typedef, get it and refer to it.
4825  maybe_set_naming_typedef(rdr, node, decl);
4826 
4827  for (xmlNodePtr n = xmlFirstElementChild(node);
4828  !is_decl_only && n;
4829  n = xmlNextElementSibling(n))
4830  {
4831  if (xmlStrEqual(n->name, BAD_CAST("base-class")))
4832  {
4833  access_specifier access =
4834  is_struct
4835  ? public_access
4836  : private_access;
4837  read_access(n, access);
4838 
4839  string type_id;
4840  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(n, "type-id"))
4841  type_id = CHAR_STR(s);
4842  shared_ptr<class_decl> b =
4843  dynamic_pointer_cast<class_decl>
4844  (rdr.build_or_get_type_decl(type_id, true));
4845  ABG_ASSERT(b);
4846 
4847  if (decl->find_base_class(b->get_qualified_name()))
4848  // We are in updating mode for this class. The version of
4849  // the class we have already has this base class, so we
4850  // are not going to add it again.
4851  continue;
4852 
4853  size_t offset_in_bits = 0;
4854  bool offset_present = read_offset_in_bits (n, offset_in_bits);
4855 
4856  bool is_virtual = false;
4857  read_is_virtual (n, is_virtual);
4858 
4859  shared_ptr<class_decl::base_spec> base (new class_decl::base_spec
4860  (b, access,
4861  offset_present
4862  ? (long) offset_in_bits
4863  : -1,
4864  is_virtual));
4865  decl->add_base_specifier(base);
4866  }
4867  else if (xmlStrEqual(n->name, BAD_CAST("member-type")))
4868  {
4869  access_specifier access =
4870  is_struct
4871  ? public_access
4872  : private_access;
4873  read_access(n, access);
4874 
4875  rdr.map_xml_node_to_decl(n, decl);
4876 
4877  for (xmlNodePtr p = xmlFirstElementChild(n);
4878  p;
4879  p = xmlNextElementSibling(p))
4880  {
4881  if (type_base_sptr t =
4882  build_type(rdr, p, /*add_to_current_scope=*/true))
4883  {
4884  decl_base_sptr td = get_type_declaration(t);
4885  ABG_ASSERT(td);
4886  set_member_access_specifier(td, access);
4887  rdr.maybe_canonicalize_type(t, !add_to_current_scope);
4889  string id = CHAR_STR(i);
4890  ABG_ASSERT(!id.empty());
4891  rdr.key_type_decl(t, id);
4892  rdr.map_xml_node_to_decl(p, td);
4893  }
4894  }
4895  }
4896  else if (xmlStrEqual(n->name, BAD_CAST("data-member")))
4897  {
4898  rdr.map_xml_node_to_decl(n, decl);
4899 
4900  access_specifier access =
4901  is_struct
4902  ? public_access
4903  : private_access;
4904  read_access(n, access);
4905 
4906  bool is_laid_out = false;
4907  size_t offset_in_bits = 0;
4908  if (read_offset_in_bits(n, offset_in_bits))
4909  is_laid_out = true;
4910 
4911  bool is_static = false;
4912  read_static(n, is_static);
4913 
4914  for (xmlNodePtr p = xmlFirstElementChild(n);
4915  p;
4916  p = xmlNextElementSibling(p))
4917  {
4918  if (var_decl_sptr v =
4919  build_var_decl(rdr, p, /*add_to_cur_scope=*/false))
4920  {
4921  if (decl->find_data_member(v))
4922  {
4923  // We are in updating mode and the current
4924  // version of this class already has this data
4925  // member, so we are not going to add it again.
4926  // So we need to discard the data member we have
4927  // built (and that was pushed to the current
4928  // stack of decls built) and move on.
4929  decl_base_sptr d = rdr.pop_decl();
4930  ABG_ASSERT(is_var_decl(d));
4931  continue;
4932  }
4933 
4934  if (!variable_is_suppressed(rdr, decl.get(), *v))
4935  {
4936  decl->add_data_member(v, access,
4937  is_laid_out,
4938  is_static,
4939  offset_in_bits);
4940  if (is_static)
4941  rdr.maybe_add_var_to_exported_decls(v.get());
4942  // Now let's record the fact that the data
4943  // member uses its type and that the class being
4944  // built uses the data member.
4945  if (is_anonymous_data_member(v))
4946  // This data member is anonymous so recording
4947  // that it uses its type is useless because we
4948  // can't name it. Rather, let's record that
4949  // the class being built uses the type of the
4950  // (anonymous) data member.
4951  RECORD_ARTIFACT_AS_USED_BY(rdr, v->get_type(), decl);
4952  else
4953  {
4954  RECORD_ARTIFACT_AS_USED_BY(rdr, v->get_type(), v);
4955  RECORD_ARTIFACT_AS_USED_BY(rdr, v, decl);
4956  }
4957  }
4958  }
4959  }
4960  }
4961  else if (xmlStrEqual(n->name, BAD_CAST("member-function")))
4962  {
4963  rdr.map_xml_node_to_decl(n, decl);
4964 
4965  access_specifier access =
4966  is_struct
4967  ? public_access
4968  : private_access;
4969  read_access(n, access);
4970 
4971  bool is_virtual = false;
4972  ssize_t vtable_offset = -1;
4973  if (xml_char_sptr s =
4974  XML_NODE_GET_ATTRIBUTE(n, "vtable-offset"))
4975  {
4976  is_virtual = true;
4977  vtable_offset = atoi(CHAR_STR(s));
4978  }
4979 
4980  bool is_static = false;
4981  read_static(n, is_static);
4982 
4983  bool is_ctor = false, is_dtor = false, is_const = false;
4984  read_cdtor_const(n, is_ctor, is_dtor, is_const);
4985 
4986  for (xmlNodePtr p = xmlFirstElementChild(n);
4987  p;
4988  p = xmlNextElementSibling(p))
4989  {
4990  if (function_decl_sptr f =
4991  build_function_decl_if_not_suppressed(rdr, p, decl,
4992  /*add_to_cur_sc=*/true))
4993  {
4994  method_decl_sptr m = is_method_decl(f);
4995  ABG_ASSERT(m);
4996  set_member_access_specifier(m, access);
4997  set_member_is_static(m, is_static);
4998  if (vtable_offset != -1)
4999  set_member_function_vtable_offset(m, vtable_offset);
5000  set_member_function_is_virtual(m, is_virtual);
5001  set_member_function_is_ctor(m, is_ctor);
5002  set_member_function_is_dtor(m, is_dtor);
5003  set_member_function_is_const(m, is_const);
5004  break;
5005  }
5006  }
5007  }
5008  else if (xmlStrEqual(n->name, BAD_CAST("member-template")))
5009  {
5010  rdr.map_xml_node_to_decl(n, decl);
5011 
5012  access_specifier access =
5013  is_struct
5014  ? public_access
5015  : private_access;
5016  read_access(n, access);
5017 
5018  bool is_static = false;
5019  read_static(n, is_static);
5020 
5021  bool is_ctor = false, is_dtor = false, is_const = false;
5022  read_cdtor_const(n, is_ctor, is_dtor, is_const);
5023 
5024  for (xmlNodePtr p = xmlFirstElementChild(n);
5025  p;
5026  p = xmlNextElementSibling(p))
5027  {
5028  if (shared_ptr<function_tdecl> f =
5029  build_function_tdecl(rdr, p,
5030  /*add_to_current_scope=*/true))
5031  {
5032  shared_ptr<member_function_template> m
5033  (new member_function_template(f, access, is_static,
5034  is_ctor, is_const));
5035  ABG_ASSERT(f->get_scope());
5036  decl->add_member_function_template(m);
5037  }
5038  else if (shared_ptr<class_tdecl> c =
5039  build_class_tdecl(rdr, p,
5040  /*add_to_current_scope=*/true))
5041  {
5042  member_class_template_sptr m(new member_class_template(c,
5043  access,
5044  is_static));
5045  ABG_ASSERT(c->get_scope());
5046  decl->add_member_class_template(m);
5047  }
5048  }
5049  }
5050  }
5051 
5052  rdr.pop_scope_or_abort(decl);
5053 
5054  return decl;
5055 }
5056 
5057 /// Build a union_decl from a 'union-decl' xml node.
5058 ///
5059 /// @param rdr the context of the parsing.
5060 ///
5061 /// @param node the xml node to build the union_decl from.
5062 ///
5063 /// @param add_to_current_scope if yes, the resulting union node
5064 /// hasn't triggered voluntarily the adding of the resulting
5065 /// union_decl_sptr to the current scope.
5066 ///
5067 /// @return a pointer to union_decl upon successful completion, a null
5068 /// pointer otherwise.
5069 static union_decl_sptr
5070 build_union_decl(reader& rdr,
5071  const xmlNodePtr node,
5072  bool add_to_current_scope)
5073 {
5074  union_decl_sptr nil;
5075 
5076  if (!xmlStrEqual(node->name, BAD_CAST("union-decl")))
5077  return nil;
5078 
5079  if (decl_base_sptr d = rdr.get_decl_for_xml_node(node))
5080  {
5081  union_decl_sptr result = dynamic_pointer_cast<union_decl>(d);
5082  ABG_ASSERT(result);
5083  return result;
5084  }
5085 
5086  string name;
5087  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
5088  name = xml::unescape_xml_string(CHAR_STR(s));
5089 
5090  size_t size_in_bits = 0, alignment_in_bits = 0;
5091  read_size_and_alignment(node, size_in_bits, alignment_in_bits);
5092 
5093  decl_base::visibility vis = decl_base::VISIBILITY_NONE;
5094  read_visibility(node, vis);
5095 
5096  bool is_artificial = false;
5097  read_is_artificial(node, is_artificial);
5098 
5099  string id;
5100  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
5101  id = CHAR_STR(s);
5102 
5103  location loc;
5104  read_location(rdr, node, loc);
5105 
5107  union_decl::data_members data_mbrs;
5108  union_decl::member_functions mbr_functions;
5109 
5110  union_decl_sptr decl;
5111 
5112  bool is_decl_only = false;
5113  read_is_declaration_only(node, is_decl_only);
5114 
5115  bool is_anonymous = false;
5116  read_is_anonymous(node, is_anonymous);
5117 
5118  ABG_ASSERT(!id.empty());
5119  union_decl_sptr previous_definition, previous_declaration;
5120  const vector<type_base_sptr> *types_ptr = 0;
5121  if (!is_anonymous)
5122  types_ptr = rdr.get_all_type_decls(id);
5123  if (types_ptr)
5124  {
5125  // Lets look at the previous declarations and the first previous
5126  // definition of this type that we've already seen while parsing
5127  // this corpus.
5128  for (vector<type_base_sptr>::const_iterator i = types_ptr->begin();
5129  i != types_ptr->end();
5130  ++i)
5131  {
5132  union_decl_sptr onion = is_union_type(*i);
5133  ABG_ASSERT(onion);
5134  if (onion->get_is_declaration_only()
5135  && !onion->get_definition_of_declaration())
5136  previous_declaration = onion;
5137  else if (!onion->get_is_declaration_only()
5138  && !previous_definition)
5139  previous_definition = onion;
5140  if (previous_definition && previous_declaration)
5141  break;
5142  }
5143 
5144  if (previous_declaration)
5145  ABG_ASSERT(previous_declaration->get_name() == name);
5146 
5147  if (previous_definition)
5148  ABG_ASSERT(previous_definition->get_name() == name);
5149 
5150  if (is_decl_only && previous_declaration)
5151  return previous_declaration;
5152  }
5153 
5154  const environment& env = rdr.get_environment();
5155 
5156  if (!is_decl_only && previous_definition)
5157  // We are in the case where we've read this class definition
5158  // before, but we might need to update it to add some new stuff to
5159  // it; we might thus find the new stuff to add in the current
5160  // (new) incarnation of that definition that we are currently
5161  // reading.
5162  decl = previous_definition;
5163  else
5164  {
5165  if (is_decl_only)
5166  decl.reset(new union_decl(env, name));
5167  else
5168  decl.reset(new union_decl(env, name,
5169  size_in_bits,
5170  loc, vis, mbrs,
5171  data_mbrs,
5172  mbr_functions,
5173  is_anonymous));
5174  }
5175 
5176  maybe_set_artificial_location(rdr, node, decl);
5177  decl->set_is_artificial(is_artificial);
5178 
5179  string def_id;
5180  bool is_def_of_decl = false;
5181  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "def-of-decl-id"))
5182  def_id = CHAR_STR(s);
5183 
5184  if (!def_id.empty())
5185  {
5186  class_decl_sptr d =
5187  dynamic_pointer_cast<class_decl>(rdr.get_type_decl(def_id));
5188  if (d && d->get_is_declaration_only())
5189  {
5190  is_def_of_decl = true;
5191  decl->set_earlier_declaration(d);
5192  d->set_definition_of_declaration(decl);
5193  }
5194  }
5195 
5196  if (!is_decl_only
5197  && decl
5198  && !decl->get_is_declaration_only()
5199  && previous_declaration)
5200  {
5201  // decl is the definition of the previous declaration
5202  // previous_declaration.
5203  //
5204  // Let's link them.
5205  decl->set_earlier_declaration(previous_declaration);
5206  for (vector<type_base_sptr>::const_iterator i = types_ptr->begin();
5207  i != types_ptr->end();
5208  ++i)
5209  {
5210  union_decl_sptr d = is_union_type(*i);
5211  ABG_ASSERT(d);
5212  if (d->get_is_declaration_only()
5213  && !d->get_definition_of_declaration())
5214  {
5215  previous_declaration->set_definition_of_declaration(decl);
5216  is_def_of_decl = true;
5217  }
5218  }
5219  }
5220 
5221  if (is_decl_only && previous_definition)
5222  {
5223  // decl is a declaration of the previous definition
5224  // previous_definition. Let's link them.
5225  ABG_ASSERT(decl->get_is_declaration_only()
5226  && !decl->get_definition_of_declaration());
5227  decl->set_definition_of_declaration(previous_definition);
5228  }
5229 
5230  ABG_ASSERT(!is_decl_only || !is_def_of_decl);
5231 
5232  rdr.push_decl_to_current_scope(decl, add_to_current_scope);
5233 
5234  rdr.map_xml_node_to_decl(node, decl);
5235  rdr.key_type_decl(decl, id);
5236 
5237  maybe_set_naming_typedef(rdr, node, decl);
5238 
5239  for (xmlNodePtr n = xmlFirstElementChild(node);
5240  !is_decl_only && n;
5241  n = xmlNextElementSibling(n))
5242  {
5243  if (xmlStrEqual(n->name, BAD_CAST("member-type")))
5244  {
5245  access_specifier access = private_access;
5246  read_access(n, access);
5247 
5248  rdr.map_xml_node_to_decl(n, decl);
5249 
5250  for (xmlNodePtr p = xmlFirstElementChild(n);
5251  p;
5252  p = xmlNextElementSibling(p))
5253  {
5254  if (type_base_sptr t =
5255  build_type(rdr, p, /*add_to_current_scope=*/true))
5256  {
5257  decl_base_sptr td = get_type_declaration(t);
5258  ABG_ASSERT(td);
5259  set_member_access_specifier(td, access);
5260  rdr.maybe_canonicalize_type(t, !add_to_current_scope);
5262  string id = CHAR_STR(i);
5263  ABG_ASSERT(!id.empty());
5264  rdr.key_type_decl(t, id);
5265  rdr.map_xml_node_to_decl(p, td);
5266  }
5267  }
5268  }
5269  else if (xmlStrEqual(n->name, BAD_CAST("data-member")))
5270  {
5271  rdr.map_xml_node_to_decl(n, decl);
5272 
5273  access_specifier access = private_access;
5274  read_access(n, access);
5275 
5276  bool is_laid_out = true;
5277  size_t offset_in_bits = 0;
5278  bool is_static = false;
5279  read_static(n, is_static);
5280 
5281  for (xmlNodePtr p = xmlFirstElementChild(n);
5282  p;
5283  p = xmlNextElementSibling(p))
5284  {
5285  if (var_decl_sptr v =
5286  build_var_decl(rdr, p, /*add_to_cur_scope=*/false))
5287  {
5288  if (decl->find_data_member(v))
5289  {
5290  // We are in updating mode and the current
5291  // version of this class already has this data
5292  // member, so we are not going to add it again.
5293  // So we need to discard the data member we have
5294  // built (and that was pushed to the current
5295  // stack of decls built) and move on.
5296  decl_base_sptr d = rdr.pop_decl();
5297  ABG_ASSERT(is_var_decl(d));
5298  continue;
5299  }
5300  if (!is_static
5301  || !variable_is_suppressed(rdr, decl.get(), *v))
5302  {
5303  decl->add_data_member(v, access,
5304  is_laid_out,
5305  is_static,
5306  offset_in_bits);
5307  // Now let's record the fact that the data
5308  // member uses its type and that the union being
5309  // built uses the data member.
5310  if (is_anonymous_data_member(v))
5311  // This data member is anonymous so recording
5312  // that it uses its type is useless because we
5313  // can't name it. Rather, let's record that
5314  // the class being built uses the type of the
5315  // (anonymous) data member.
5316  RECORD_ARTIFACT_AS_USED_BY(rdr, v->get_type(), decl);
5317  else
5318  {
5319  RECORD_ARTIFACT_AS_USED_BY(rdr, v->get_type(), v);
5320  RECORD_ARTIFACT_AS_USED_BY(rdr, v, decl);
5321  }
5322  }
5323  }
5324  }
5325  }
5326  else if (xmlStrEqual(n->name, BAD_CAST("member-function")))
5327  {
5328  rdr.map_xml_node_to_decl(n, decl);
5329 
5330  access_specifier access = private_access;
5331  read_access(n, access);
5332 
5333  bool is_static = false;
5334  read_static(n, is_static);
5335 
5336  bool is_ctor = false, is_dtor = false, is_const = false;
5337  read_cdtor_const(n, is_ctor, is_dtor, is_const);
5338 
5339  for (xmlNodePtr p = xmlFirstElementChild(n);
5340  p;
5341  p = xmlNextElementSibling(p))
5342  {
5343  if (function_decl_sptr f =
5344  build_function_decl_if_not_suppressed(rdr, p, decl,
5345  /*add_to_cur_sc=*/true))
5346  {
5347  method_decl_sptr m = is_method_decl(f);
5348  ABG_ASSERT(m);
5349  set_member_access_specifier(m, access);
5350  set_member_is_static(m, is_static);
5351  set_member_function_is_ctor(m, is_ctor);
5352  set_member_function_is_dtor(m, is_dtor);
5353  set_member_function_is_const(m, is_const);
5354  break;
5355  }
5356  }
5357  }
5358  else if (xmlStrEqual(n->name, BAD_CAST("member-template")))
5359  {
5360  rdr.map_xml_node_to_decl(n, decl);
5361 
5362  access_specifier access = private_access;
5363  read_access(n, access);
5364 
5365  bool is_static = false;
5366  read_static(n, is_static);
5367 
5368  bool is_ctor = false, is_dtor = false, is_const = false;
5369  read_cdtor_const(n, is_ctor, is_dtor, is_const);
5370 
5371  for (xmlNodePtr p = xmlFirstElementChild(n);
5372  p;
5373  p = xmlNextElementSibling(p))
5374  {
5375  if (function_tdecl_sptr f =
5376  build_function_tdecl(rdr, p,
5377  /*add_to_current_scope=*/true))
5378  {
5379  member_function_template_sptr m
5380  (new member_function_template(f, access, is_static,
5381  is_ctor, is_const));
5382  ABG_ASSERT(f->get_scope());
5383  decl->add_member_function_template(m);
5384  }
5385  else if (class_tdecl_sptr c =
5386  build_class_tdecl(rdr, p,
5387  /*add_to_current_scope=*/true))
5388  {
5389  member_class_template_sptr m(new member_class_template(c,
5390  access,
5391  is_static));
5392  ABG_ASSERT(c->get_scope());
5393  decl->add_member_class_template(m);
5394  }
5395  }
5396  }
5397  }
5398 
5399  rdr.pop_scope_or_abort(decl);
5400 
5401  return decl;
5402 }
5403 
5404 /// Build an intance of function_tdecl, from an
5405 /// 'function-template-decl' xml element node.
5406 ///
5407 /// @param rdr the context of the parsing.
5408 ///
5409 /// @param node the xml node to parse from.
5410 ///
5411 /// @param add_to_current_scope if set to yes, the resulting of
5412 /// this function is added to its current scope.
5413 ///
5414 /// @return the newly built function_tdecl upon successful
5415 /// completion, a null pointer otherwise.
5416 static shared_ptr<function_tdecl>
5417 build_function_tdecl(reader& rdr,
5418  const xmlNodePtr node,
5419  bool add_to_current_scope)
5420 {
5421  shared_ptr<function_tdecl> nil, result;
5422 
5423  if (!xmlStrEqual(node->name, BAD_CAST("function-template-decl")))
5424  return nil;
5425 
5426  string id;
5427  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
5428  id = CHAR_STR(s);
5429  if (id.empty() || rdr.get_fn_tmpl_decl(id))
5430  return nil;
5431 
5432  location loc;
5433  read_location(rdr, node, loc);
5434 
5435  decl_base::visibility vis = decl_base::VISIBILITY_NONE;
5436  read_visibility(node, vis);
5437 
5438  decl_base::binding bind = decl_base::BINDING_NONE;
5439  read_binding(node, bind);
5440 
5441  const environment& env = rdr.get_environment();
5442 
5443  function_tdecl_sptr fn_tmpl_decl(new function_tdecl(env, loc, vis, bind));
5444  maybe_set_artificial_location(rdr, node, fn_tmpl_decl);
5445 
5446  rdr.push_decl_to_current_scope(fn_tmpl_decl, add_to_current_scope);
5447 
5448  unsigned parm_index = 0;
5449  for (xmlNodePtr n = xmlFirstElementChild(node);
5450  n;
5451  n = xmlNextElementSibling(n))
5452  {
5453  if (template_parameter_sptr parm =
5454  build_template_parameter(rdr, n, parm_index, fn_tmpl_decl))
5455  {
5456  fn_tmpl_decl->add_template_parameter(parm);
5457  ++parm_index;
5458  }
5459  else if (function_decl_sptr f =
5460  build_function_decl_if_not_suppressed(rdr, n, class_decl_sptr(),
5461  /*add_to_current_scope=*/true))
5462  fn_tmpl_decl->set_pattern(f);
5463  }
5464 
5465  rdr.key_fn_tmpl_decl(fn_tmpl_decl, id);
5466 
5467  return fn_tmpl_decl;
5468 }
5469 
5470 /// Build an intance of class_tdecl, from a
5471 /// 'class-template-decl' xml element node.
5472 ///
5473 /// @param rdr the context of the parsing.
5474 ///
5475 /// @param node the xml node to parse from.
5476 ///
5477 /// @param add_to_current_scope if set to yes, the resulting of this
5478 /// function is added to its current scope.
5479 ///
5480 /// @return the newly built function_tdecl upon successful
5481 /// completion, a null pointer otherwise.
5482 static shared_ptr<class_tdecl>
5483 build_class_tdecl(reader& rdr,
5484  const xmlNodePtr node,
5485  bool add_to_current_scope)
5486 {
5487  shared_ptr<class_tdecl> nil, result;
5488 
5489  if (!xmlStrEqual(node->name, BAD_CAST("class-template-decl")))
5490  return nil;
5491 
5492  string id;
5493  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
5494  id = CHAR_STR(s);
5495  if (id.empty() || rdr.get_class_tmpl_decl(id))
5496  return nil;
5497 
5498  location loc;
5499  read_location(rdr, node, loc);
5500 
5501  decl_base::visibility vis = decl_base::VISIBILITY_NONE;
5502  read_visibility(node, vis);
5503 
5504  const environment& env = rdr.get_environment();
5505 
5506  class_tdecl_sptr class_tmpl (new class_tdecl(env, loc, vis));
5507  maybe_set_artificial_location(rdr, node, class_tmpl);
5508 
5509  rdr.push_decl_to_current_scope(class_tmpl, add_to_current_scope);
5510 
5511  unsigned parm_index = 0;
5512  for (xmlNodePtr n = xmlFirstElementChild(node);
5513  n;
5514  n = xmlNextElementSibling(n))
5515  {
5516  if (template_parameter_sptr parm=
5517  build_template_parameter(rdr, n, parm_index, class_tmpl))
5518  {
5519  class_tmpl->add_template_parameter(parm);
5520  ++parm_index;
5521  }
5522  else if (class_decl_sptr c =
5523  build_class_decl_if_not_suppressed(rdr, n,
5524  add_to_current_scope))
5525  {
5526  if (c->get_scope())
5527  rdr.maybe_canonicalize_type(c, /*force_delay=*/false);
5528  class_tmpl->set_pattern(c);
5529  }
5530  }
5531 
5532  rdr.key_class_tmpl_decl(class_tmpl, id);
5533 
5534  return class_tmpl;
5535 }
5536 
5537 /// Build a type_tparameter from a 'template-type-parameter'
5538 /// xml element node.
5539 ///
5540 /// @param rdr the context of the parsing.
5541 ///
5542 /// @param node the xml node to parse from.
5543 ///
5544 /// @param index the index (occurrence index, starting from 0) of the
5545 /// template parameter.
5546 ///
5547 /// @param tdecl the enclosing template declaration that holds the
5548 /// template type parameter.
5549 ///
5550 /// @return a pointer to a newly created instance of
5551 /// type_tparameter, a null pointer otherwise.
5552 static type_tparameter_sptr
5553 build_type_tparameter(reader& rdr,
5554  const xmlNodePtr node,
5555  unsigned index,
5556  template_decl_sptr tdecl)
5557 {
5558  type_tparameter_sptr nil, result;
5559 
5560  if (!xmlStrEqual(node->name, BAD_CAST("template-type-parameter")))
5561  return nil;
5562 
5563  string id;
5564  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
5565  id = CHAR_STR(s);
5566  if (!id.empty())
5567  ABG_ASSERT(!rdr.get_type_decl(id));
5568 
5569  string type_id;
5570  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
5571  type_id = CHAR_STR(s);
5572  if (!type_id.empty()
5573  && !(result = dynamic_pointer_cast<type_tparameter>
5574  (rdr.build_or_get_type_decl(type_id, true))))
5575  abort();
5576 
5577  string name;
5578  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
5579  name = xml::unescape_xml_string(CHAR_STR(s));
5580 
5581  location loc;
5582  read_location(rdr, node,loc);
5583 
5584  result.reset(new type_tparameter(index, tdecl, name, loc));
5585  maybe_set_artificial_location(rdr, node, result);
5586 
5587  if (id.empty())
5588  rdr.push_decl_to_current_scope(dynamic_pointer_cast<decl_base>(result),
5589  /*add_to_current_scope=*/true);
5590  else
5591  rdr.push_and_key_type_decl(result, id, /*add_to_current_scope=*/true);
5592 
5593  rdr.maybe_canonicalize_type(result, /*force_delay=*/false);
5594 
5595  return result;
5596 }
5597 
5598 /// Build a tmpl_parm_type_composition from a
5599 /// "template-parameter-type-composition" xml element node.
5600 ///
5601 /// @param rdr the context of the parsing.
5602 ///
5603 /// @param node the xml node to parse from.
5604 ///
5605 /// @param index the index of the previous normal template parameter.
5606 ///
5607 /// @param tdecl the enclosing template declaration that holds this
5608 /// template parameter type composition.
5609 ///
5610 /// @return a pointer to a new instance of tmpl_parm_type_composition
5611 /// upon successful completion, a null pointer otherwise.
5612 static type_composition_sptr
5613 build_type_composition(reader& rdr,
5614  const xmlNodePtr node,
5615  unsigned index,
5616  template_decl_sptr tdecl)
5617 {
5618  type_composition_sptr nil, result;
5619 
5620  if (!xmlStrEqual(node->name, BAD_CAST("template-parameter-type-composition")))
5621  return nil;
5622 
5623  type_base_sptr composed_type;
5624  result.reset(new type_composition(index, tdecl, composed_type));
5625  rdr.push_decl_to_current_scope(dynamic_pointer_cast<decl_base>(result),
5626  /*add_to_current_scope=*/true);
5627 
5628  for (xmlNodePtr n = xmlFirstElementChild(node);
5629  n;
5630  n = xmlNextElementSibling(n))
5631  {
5632  if ((composed_type =
5633  build_pointer_type_def(rdr, n,
5634  /*add_to_current_scope=*/true))
5635  ||(composed_type =
5636  build_reference_type_def(rdr, n,
5637  /*add_to_current_scope=*/true))
5638  ||(composed_type =
5639  build_array_type_def(rdr, n,
5640  /*add_to_current_scope=*/true))
5641  || (composed_type =
5642  build_qualified_type_decl(rdr, n,
5643  /*add_to_current_scope=*/true)))
5644  {
5645  rdr.maybe_canonicalize_type(composed_type,
5646  /*force_delay=*/true);
5647  result->set_composed_type(composed_type);
5648  break;
5649  }
5650  }
5651 
5652  return result;
5653 }
5654 
5655 /// Build an instance of non_type_tparameter from a
5656 /// 'template-non-type-parameter' xml element node.
5657 ///
5658 /// @param rdr the context of the parsing.
5659 ///
5660 /// @param node the xml node to parse from.
5661 ///
5662 /// @param index the index of the parameter.
5663 ///
5664 /// @param tdecl the enclosing template declaration that holds this
5665 /// non type template parameter.
5666 ///
5667 /// @return a pointer to a newly created instance of
5668 /// non_type_tparameter upon successful completion, a null
5669 /// pointer code otherwise.
5671 build_non_type_tparameter(reader& rdr,
5672  const xmlNodePtr node,
5673  unsigned index,
5674  template_decl_sptr tdecl)
5675 {
5677 
5678  if (!xmlStrEqual(node->name, BAD_CAST("template-non-type-parameter")))
5679  return r;
5680 
5681  string type_id;
5682  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
5683  type_id = CHAR_STR(s);
5684  type_base_sptr type;
5685  if (type_id.empty()
5686  || !(type = rdr.build_or_get_type_decl(type_id, true)))
5687  abort();
5688 
5689  string name;
5690  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
5691  name = xml::unescape_xml_string(CHAR_STR(s));
5692 
5693  location loc;
5694  read_location(rdr, node,loc);
5695 
5696  r.reset(new non_type_tparameter(index, tdecl, name, type, loc));
5697  maybe_set_artificial_location(rdr, node, r);
5698  rdr.push_decl_to_current_scope(dynamic_pointer_cast<decl_base>(r),
5699  /*add_to_current_scope=*/true);
5700 
5701  return r;
5702 }
5703 
5704 /// Build an intance of template_tparameter from a
5705 /// 'template-template-parameter' xml element node.
5706 ///
5707 /// @param rdr the context of the parsing.
5708 ///
5709 /// @param node the xml node to parse from.
5710 ///
5711 /// @param index the index of the template parameter.
5712 ///
5713 /// @param tdecl the enclosing template declaration that holds this
5714 /// template template parameter.
5715 ///
5716 /// @return a pointer to a new instance of template_tparameter
5717 /// upon successful completion, a null pointer otherwise.
5719 build_template_tparameter(reader& rdr,
5720  const xmlNodePtr node,
5721  unsigned index,
5722  template_decl_sptr tdecl)
5723 {
5725 
5726  if (!xmlStrEqual(node->name, BAD_CAST("template-template-parameter")))
5727  return nil;
5728 
5729  string id;
5730  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "id"))
5731  id = CHAR_STR(s);
5732  // Bail out if a type with the same ID already exists.
5733  ABG_ASSERT(!id.empty());
5734 
5735  string type_id;
5736  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "type-id"))
5737  type_id = CHAR_STR(s);
5738  // Bail out if no type with this ID exists.
5739  if (!type_id.empty()
5740  && !(dynamic_pointer_cast<template_tparameter>
5741  (rdr.build_or_get_type_decl(type_id, true))))
5742  abort();
5743 
5744  string name;
5745  if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "name"))
5746  name = xml::unescape_xml_string(CHAR_STR(s));
5747 
5748  location loc;
5749  read_location(rdr, node, loc);
5750 
5751  template_tparameter_sptr result(new template_tparameter(index, tdecl,
5752  name, loc));
5753  maybe_set_artificial_location(rdr, node, result);
5754  rdr.push_decl_to_current_scope(result, /*add_to_current_scope=*/true);
5755 
5756  // Go parse template parameters that are children nodes
5757  int parm_index = 0;
5758  for (xmlNodePtr n = xmlFirstElementChild(node);
5759  n;
5760  n = xmlNextElementSibling(n))
5761  if (shared_ptr<template_parameter> p =
5762  build_template_parameter(rdr, n, parm_index, result))
5763  {
5764  result->add_template_parameter(p);
5765  ++parm_index;
5766  }
5767 
5768  if (result)
5769  {
5770  rdr.key_type_decl(result, id);
5771  rdr.maybe_canonicalize_type(result, /*force_delay=*/false);
5772  }
5773 
5774  return result;
5775 }
5776 
5777 /// Build a template parameter type from several possible xml elment
5778 /// nodes representing a serialized form a template parameter.
5779 ///
5780 /// @param rdr the context of the parsing.
5781 ///
5782 /// @param node the xml element node to parse from.
5783 ///
5784 /// @param index the index of the template parameter we are parsing.
5785 ///
5786 /// @param tdecl the enclosing template declaration that holds this
5787 /// template parameter.
5788 ///
5789 /// @return a pointer to a newly created instance of
5790 /// template_parameter upon successful completion, a null pointer
5791 /// otherwise.
5793 build_template_parameter(reader& rdr,
5794  const xmlNodePtr node,
5795  unsigned index,
5796  template_decl_sptr tdecl)
5797 {
5798  shared_ptr<template_parameter> r;
5799  ((r = build_type_tparameter(rdr, node, index, tdecl))
5800  || (r = build_non_type_tparameter(rdr, node, index, tdecl))
5801  || (r = build_template_tparameter(rdr, node, index, tdecl))
5802  || (r = build_type_composition(rdr, node, index, tdecl)));
5803 
5804  return r;
5805 }
5806 
5807 /// Build a type from an xml node.
5808 ///
5809 /// @param rdr the context of the parsing.
5810 ///
5811 /// @param node the xml node to build the type_base from.
5812 ///
5813 /// @return a pointer to the newly built type_base upon successful
5814 /// completion, a null pointer otherwise.
5815 static type_base_sptr
5816 build_type(reader& rdr,
5817  const xmlNodePtr node,
5818  bool add_to_current_scope)
5819 {
5820  type_base_sptr t;
5821 
5822  ((t = build_type_decl(rdr, node, add_to_current_scope))
5823  || (t = build_qualified_type_decl(rdr, node, add_to_current_scope))
5824  || (t = build_pointer_type_def(rdr, node, add_to_current_scope))
5825  || (t = build_reference_type_def(rdr, node , add_to_current_scope))
5826  || (t = build_function_type(rdr, node, add_to_current_scope))
5827  || (t = build_array_type_def(rdr, node, add_to_current_scope))
5828  || (t = build_subrange_type(rdr, node, add_to_current_scope))
5829  || (t = build_enum_type_decl_if_not_suppressed(rdr, node,
5830  add_to_current_scope))
5831  || (t = build_typedef_decl(rdr, node, add_to_current_scope))
5832  || (t = build_class_decl_if_not_suppressed(rdr, node,
5833  add_to_current_scope))
5834  || (t = build_union_decl_if_not_suppressed(rdr, node,
5835  add_to_current_scope)));
5836 
5837  if (rdr.tracking_non_reachable_types() && t)
5838  {
5839  corpus_sptr abi = rdr.corpus();
5840  ABG_ASSERT(abi);
5841  bool is_non_reachable_type = false;
5842  read_is_non_reachable_type(node, is_non_reachable_type);
5843  if (!is_non_reachable_type)
5844  abi->record_type_as_reachable_from_public_interfaces(*t);
5845  }
5846 
5847  MAYBE_MAP_TYPE_WITH_TYPE_ID(t, node);
5848 
5849  if (t)
5850  rdr.maybe_canonicalize_type(t,/*force_delay=*/false );
5851  return t;
5852 }
5853 
5854 /// Parses 'type-decl' xml element.
5855 ///
5856 /// @param rdr the parsing context.
5857 ///
5858 /// @return true upon successful parsing, false otherwise.
5859 static decl_base_sptr
5860 handle_type_decl(reader& rdr,
5861  xmlNodePtr node,
5862  bool add_to_current_scope)
5863 {
5864  type_decl_sptr decl = build_type_decl(rdr, node, add_to_current_scope);
5865  MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node);
5866  if (decl && decl->get_scope())
5867  rdr.maybe_canonicalize_type(decl, /*force_delay=*/false);
5868  return decl;
5869 }
5870 
5871 /// Parses 'namespace-decl' xml element.
5872 ///
5873 /// @param rdr the parsing context.
5874 ///
5875 /// @return true upon successful parsing, false otherwise.
5876 static decl_base_sptr
5877 handle_namespace_decl(reader& rdr,
5878  xmlNodePtr node,
5879  bool add_to_current_scope)
5880 {
5881  namespace_decl_sptr d = build_namespace_decl(rdr, node,
5882  add_to_current_scope);
5883  return d;
5884 }
5885 
5886 /// Parse a qualified-type-def xml element.
5887 ///
5888 /// @param rdr the parsing context.
5889 ///
5890 /// @return true upon successful parsing, false otherwise.
5891 static decl_base_sptr
5892 handle_qualified_type_decl(reader& rdr,
5893  xmlNodePtr node,
5894  bool add_to_current_scope)
5895 {
5896  qualified_type_def_sptr decl =
5897  build_qualified_type_decl(rdr, node,
5898  add_to_current_scope);
5899  MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node);
5900  if (decl && decl->get_scope())
5901  rdr.maybe_canonicalize_type(decl, /*force_delay=*/false);
5902  return decl;
5903 }
5904 
5905 /// Parse a pointer-type-decl element.
5906 ///
5907 /// @param rdr the context of the parsing.
5908 ///
5909 /// @return true upon successful completion, false otherwise.
5910 static decl_base_sptr
5911 handle_pointer_type_def(reader& rdr,
5912  xmlNodePtr node,
5913  bool add_to_current_scope)
5914 {
5915  pointer_type_def_sptr decl = build_pointer_type_def(rdr, node,
5916  add_to_current_scope);
5917  MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node);
5918  if (decl && decl->get_scope())
5919  rdr.maybe_canonicalize_type(decl, /*force_delay=*/false);
5920  return decl;
5921 }
5922 
5923 /// Parse a reference-type-def element.
5924 ///
5925 /// @param rdr the context of the parsing.
5926 ///
5927 /// reference_type_def is added to.
5928 static decl_base_sptr
5929 handle_reference_type_def(reader& rdr,
5930  xmlNodePtr node,
5931  bool add_to_current_scope)
5932 {
5933  reference_type_def_sptr decl = build_reference_type_def(rdr, node,
5934  add_to_current_scope);
5935  MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node);
5936  if (decl && decl->get_scope())
5937  rdr.maybe_canonicalize_type(decl, /*force_delay=*/false);
5938  return decl;
5939 }
5940 
5941 /// Parse a function-type element.
5942 ///
5943 /// @param rdr the context of the parsing.
5944 ///
5945 /// function_type is added to.
5946 static type_base_sptr
5947 handle_function_type(reader& rdr,
5948  xmlNodePtr node,
5949  bool add_to_current_scope)
5950 {
5951  function_type_sptr type = build_function_type(rdr, node,
5952  add_to_current_scope);
5953  MAYBE_MAP_TYPE_WITH_TYPE_ID(type, node);
5954  rdr.maybe_canonicalize_type(type, /*force_delay=*/true);
5955  return type;
5956 }
5957 
5958 /// Parse a array-type-def element.
5959 ///
5960 /// @param rdr the context of the parsing.
5961 ///
5962 /// array_type_def is added to.
5963 static decl_base_sptr
5964 handle_array_type_def(reader& rdr,
5965  xmlNodePtr node,
5966  bool add_to_current_scope)
5967 {
5968  array_type_def_sptr decl = build_array_type_def(rdr, node,
5969  add_to_current_scope);
5970  MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node);
5971  rdr.maybe_canonicalize_type(decl, /*force_delay=*/false);
5972  return decl;
5973 }
5974 
5975 /// Parse an enum-decl element.
5976 ///
5977 /// @param rdr the context of the parsing.
5978 static decl_base_sptr
5979 handle_enum_type_decl(reader& rdr,
5980  xmlNodePtr node,
5981  bool add_to_current_scope)
5982 {
5983  enum_type_decl_sptr decl =
5984  build_enum_type_decl_if_not_suppressed(rdr, node,
5985  add_to_current_scope);
5986  MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node);
5987  if (decl && decl->get_scope())
5988  rdr.maybe_canonicalize_type(decl, /*force_delay=*/false);
5989  return decl;
5990 }
5991 
5992 /// Parse a typedef-decl element.
5993 ///
5994 /// @param rdr the context of the parsing.
5995 static decl_base_sptr
5996 handle_typedef_decl(reader& rdr,
5997  xmlNodePtr node,
5998  bool add_to_current_scope)
5999 {
6000  typedef_decl_sptr decl = build_typedef_decl(rdr, node,
6001  add_to_current_scope);
6002  MAYBE_MAP_TYPE_WITH_TYPE_ID(decl, node);
6003  if (decl && decl->get_scope())
6004  rdr.maybe_canonicalize_type(decl, /*force_delay=*/false);
6005  return decl;
6006 }
6007 
6008 /// Parse a var-decl element.
6009 ///
6010 /// @param rdr the context of the parsing.
6011 ///
6012 /// @param node the node to read & parse from.
6013 ///
6014 /// @param add_to_current_scope if set to yes, the resulting of this
6015 /// function is added to its current scope.
6016 static decl_base_sptr
6017 handle_var_decl(reader& rdr,
6018  xmlNodePtr node,
6019  bool add_to_current_scope)
6020 {
6021  decl_base_sptr decl = build_var_decl_if_not_suppressed(rdr, node,
6022  add_to_current_scope);
6023  rdr.maybe_add_var_to_exported_decls(is_var_decl(decl).get());
6024  return decl;
6025 }
6026 
6027 /// Parse a function-decl element.
6028 ///
6029 /// @param rdr the context of the parsing
6030 ///
6031 /// @return true upon successful completion of the parsing, false
6032 /// otherwise.
6033 static decl_base_sptr
6034 handle_function_decl(reader& rdr,
6035  xmlNodePtr node,
6036  bool add_to_current_scope)
6037 {
6038  return build_function_decl_if_not_suppressed(rdr, node, class_decl_sptr(),
6039  add_to_current_scope);
6040 }
6041 
6042 /// Parse a 'class-decl' xml element.
6043 ///
6044 /// @param rdr the context of the parsing.
6045 ///
6046 /// @return the resulting @ref class_decl built from the XML element
6047 /// upon successful completion of the parsing, nil otherwise.
6048 static decl_base_sptr
6049 handle_class_decl(reader& rdr,
6050  xmlNodePtr node,
6051  bool add_to_current_scope)
6052 {
6053  class_decl_sptr decl =
6054  build_class_decl_if_not_suppressed(rdr, node, add_to_current_scope);
6055  MAYBE_MAP_TYPE_WITH_TYPE_ID(is_type(decl), node);
6056  if (decl && decl->get_scope())
6057  rdr.maybe_canonicalize_type(decl, /*force_delay=*/false);
6058  return decl;
6059 }
6060 
6061 /// Parse a 'union-decl' xml element.
6062 ///
6063 /// @param rdr the context of the parsing.
6064 ///
6065 /// @return the resulting @ref union_decl built from the XML element
6066 /// upon successful completion of the parsing, nil otherwise.
6067 static decl_base_sptr
6068 handle_union_decl(reader& rdr,
6069  xmlNodePtr node,
6070  bool add_to_current_scope)
6071 {
6072  union_decl_sptr decl =
6073  build_union_decl_if_not_suppressed(rdr, node, add_to_current_scope);
6074  MAYBE_MAP_TYPE_WITH_TYPE_ID(is_type(decl), node);
6075  if (decl && decl->get_scope())
6076  rdr.maybe_canonicalize_type(decl, /*force_delay=*/false);
6077  return decl;
6078 }
6079 
6080 /// Parse a 'function-template-decl' xml element.
6081 ///
6082 /// @param rdr the parsing context.
6083 ///
6084 /// @return true upon successful completion of the parsing, false
6085 /// otherwise.
6086 static decl_base_sptr
6087 handle_function_tdecl(reader& rdr,
6088  xmlNodePtr node,
6089  bool add_to_current_scope)
6090 {
6091  function_tdecl_sptr d = build_function_tdecl(rdr, node,
6092  add_to_current_scope);
6093  return d;
6094 }
6095 
6096 /// Parse a 'class-template-decl' xml element.
6097 ///
6098 /// @param rdr the context of the parsing.
6099 ///
6100 /// @return true upon successful completion, false otherwise.
6101 static decl_base_sptr
6102 handle_class_tdecl(reader& rdr,
6103  xmlNodePtr node,
6104  bool add_to_current_scope)
6105 {
6106  class_tdecl_sptr decl = build_class_tdecl(rdr, node,
6107  add_to_current_scope);
6108  return decl;
6109 }
6110 
6111 /// De-serialize a translation unit from an ABI Instrumentation xml
6112 /// file coming from an input stream.
6113 ///
6114 /// @param in a pointer to the input stream.
6115 ///
6116 /// @param env the environment to use.
6117 ///
6118 /// @return the translation unit resulting from the parsing upon
6119 /// successful completion, or nil.
6122 {
6123  reader read_rdr(xml::new_reader_from_istream(in), env);
6124  return read_translation_unit_from_input(read_rdr);
6125 }
6126 template<typename T>
6127 struct array_deleter
6128 {
6129  void
6130  operator()(T* a)
6131  {
6132  delete [] a;
6133  }
6134 };//end array_deleter
6135 
6136 
6137 /// Create an xml_reader::reader to read a native XML ABI file.
6138 ///
6139 /// @param path the path to the native XML file to read.
6140 ///
6141 /// @param env the environment to use.
6142 ///
6143 /// @return the created context.
6144 fe_iface_sptr
6145 create_reader(const string& path, environment& env)
6146 {
6147  reader_sptr result(new reader(xml::new_reader_from_file(path),
6148  env));
6149  corpus_sptr corp = result->corpus();
6150  corp->set_origin(corpus::NATIVE_XML_ORIGIN);
6151 #ifdef WITH_DEBUG_SELF_COMPARISON
6152  if (env.self_comparison_debug_is_on())
6153  env.set_self_comparison_debug_input(result->corpus());
6154 #endif
6155  result->set_path(path);
6156  return result;
6157 }
6158 
6159 /// Create an xml_reader::reader to read a native XML ABI from
6160 /// an input stream..
6161 ///
6162 /// @param in the input stream that contains the native XML file to read.
6163 ///
6164 /// @param env the environment to use.
6165 ///
6166 /// @return the created context.
6167 fe_iface_sptr
6168 create_reader(std::istream* in, environment& env)
6169 {
6170  reader_sptr result(new reader(xml::new_reader_from_istream(in),
6171  env));
6172  corpus_sptr corp = result->corpus();
6173  corp->set_origin(corpus::NATIVE_XML_ORIGIN);
6174 #ifdef WITH_DEBUG_SELF_COMPARISON
6175  if (env.self_comparison_debug_is_on())
6176  env.set_self_comparison_debug_input(result->corpus());
6177 #endif
6178  return result;
6179 }
6180 
6181 /// De-serialize an ABI corpus from an input XML document which root
6182 /// node is 'abi-corpus'.
6183 ///
6184 /// @param in the input stream to read the XML document from.
6185 ///
6186 /// @param env the environment to use. Note that the life time of
6187 /// this environment must be greater than the lifetime of the
6188 /// resulting corpus as the corpus uses resources that are allocated
6189 /// in the environment.
6190 ///
6191 /// @return the resulting corpus de-serialized from the parsing. This
6192 /// is non-null iff the parsing resulted in a valid corpus.
6193 corpus_sptr
6194 read_corpus_from_abixml(std::istream* in,
6195  environment& env)
6196 {
6197  fe_iface_sptr rdr = create_reader(in, env);
6198  fe_iface::status sts;
6199  return rdr->read_corpus(sts);
6200 }
6201 
6202 /// De-serialize an ABI corpus from an XML document file which root
6203 /// node is 'abi-corpus'.
6204 ///
6205 /// @param path the path to the input file to read the XML document
6206 /// from.
6207 ///
6208 /// @param env the environment to use. Note that the life time of
6209 /// this environment must be greater than the lifetime of the
6210 /// resulting corpus as the corpus uses resources that are allocated
6211 /// in the environment.
6212 ///
6213 /// @return the resulting corpus de-serialized from the parsing. This
6214 /// is non-null if the parsing successfully resulted in a corpus.
6215 corpus_sptr
6216 read_corpus_from_abixml_file(const string& path,
6217  environment& env)
6218 {
6219  fe_iface_sptr rdr = create_reader(path, env);
6220  fe_iface::status sts;
6221  corpus_sptr corp = rdr->read_corpus(sts);
6222  return corp;
6223 }
6224 
6225 }//end namespace xml_reader
6226 
6227 #ifdef WITH_DEBUG_SELF_COMPARISON
6228 /// Load the map that is stored at
6229 /// environment::get_type_id_canonical_type_map().
6230 ///
6231 /// That map associates type-ids to the pointer value of the canonical
6232 /// types they correspond to. The map is loaded from a file that was
6233 /// stored on disk by some debugging primitive that is activated when
6234 /// the command "abidw --debug-abidiff <binary>' is used."
6235 ///
6236 /// The function that stored the map in that file is
6237 /// write_canonical_type_ids.
6238 ///
6239 /// @param rdr the ABIXML reader to use.
6240 ///
6241 /// @param file_path the path to the file containing the type-ids <->
6242 /// canonical type mapping.
6243 ///
6244 /// @return true iff the loading was successful.
6245 bool
6246 load_canonical_type_ids(fe_iface& iface, const string &file_path)
6247 {
6248  abixml::reader& rdr = dynamic_cast<abixml::reader&>(iface);
6249 
6250  xmlDocPtr doc = xmlReadFile(file_path.c_str(), NULL, XML_PARSE_NOERROR);
6251  if (!doc)
6252  return false;
6253 
6254  xmlNodePtr node = xmlDocGetRootElement(doc);
6255  if (!node)
6256  return false;
6257 
6258  // We expect a file which content looks like:
6259  //
6260  // <abixml-types-check>
6261  // <type>
6262  // <id>type-id-573</id>
6263  // <c>0x262ee28</c>
6264  // </type>
6265  // <type>
6266  // <id>type-id-569</id>
6267  // <c>0x2628298</c>
6268  // </type>
6269  // <type>
6270  // <id>type-id-575</id>
6271  // <c>0x25f9ba8</c>
6272  // </type>
6273  // <abixml-types-check>
6274  //
6275  // So let's parse it!
6276 
6277  if (xmlStrcmp(node->name, (xmlChar*) "abixml-types-check"))
6278  return false;
6279 
6280  for (node = xmlFirstElementChild(node);
6281  node;
6282  node = xmlNextElementSibling(node))
6283  {
6284  if (xmlStrcmp(node->name, (xmlChar*) "type"))
6285  continue;
6286 
6287  string id, canonical_address;
6288  xmlNodePtr data = xmlFirstElementChild(node);
6289  if (data && !xmlStrcmp(data->name, (xmlChar*) "id")
6290  && data->children && xmlNodeIsText(data->children))
6291  id = (char*) XML_GET_CONTENT(data->children);
6292 
6293  data = xmlNextElementSibling(data);
6294  if (data && !xmlStrcmp(data->name, (xmlChar*) "c")
6295  && data->children && xmlNodeIsText(data->children))
6296  {
6297  canonical_address = (char*) XML_GET_CONTENT(data->children);
6298  std::stringstream s;
6299  s << canonical_address;
6300  uintptr_t v = 0;
6301  s >> std::hex >> v;
6302  if (!id.empty()
6303  // 0xdeadbabe is the special value the hash of types
6304  // that are not canonicalized. Look into function
6305  // hash_as_canonical_type_or_constant for the details.
6306  && v != 0xdeadbabe)
6307  rdr.get_environment().get_type_id_canonical_type_map()[id] = v;
6308  }
6309  }
6310  return true;
6311 }
6312 #endif
6313 
6314 }//end namespace abigail
This file contains the declarations for the fe_iface a.k.a "Front End Interface".
#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:1589
#define XML_READER_GET_NODE_NAME(reader)
Get the name of the current element node the reader is pointing to. Note that this macro returns an i...
#define XML_READER_GET_ATTRIBUTE(reader, name)
Get the value of attribute 'name' on the current node of 'reader' which is an instance of shared_ptr<...
#define XML_NODE_GET_ATTRIBUTE(node, name)
Get the value of attribute 'name' ont the instance of xmlNodePtr denoted by 'node'.
#define XML_READER_GET_NODE_TYPE(reader)
Get the type of the current node of the shared_ptr<xmlTextReader> passed in argument.
This file contains the declarations of the entry points to de-serialize an instance of abigail::trans...
This contains the private implementation of the suppression engine of libabigail.
This contains the declarations for the symtab reader.
#define ABG_ASSERT_NOT_REACHED
A macro that expands to aborting the program when executed.
The base class of all libabigail front-ends: The Front End Interface.
Definition: abg-fe-iface.h:29
status
The status of the fe_iface::read_corpus call.
Definition: abg-fe-iface.h:38
shared_ptr< subrange_type > subrange_sptr
Convenience typedef for a shared pointer on a function_decl::subrange.
Definition: abg-ir.h:2460
std::vector< subrange_sptr > subranges_type
Convenience typedef for a vector of subrange_sptr.
Definition: abg-ir.h:2467
vector< base_spec_sptr > base_specs
Convenience typedef.
Definition: abg-ir.h:4160
vector< method_decl_sptr > member_functions
Convenience typedef.
Definition: abg-ir.h:3970
vector< var_decl_sptr > data_members
Convenience typedef.
Definition: abg-ir.h:3969
vector< type_base_sptr > member_types
Convenience typedef.
Definition: abg-ir.h:3964
Abstracts the building of the set of exported variables and functions.
Definition: abg-corpus.h:304
Abstraction of a group of corpora.
Definition: abg-corpus.h:353
This is the abstraction of a set of translation units (themselves seen as bundles of unitary abi arte...
Definition: abg-corpus.h:25
void set_soname(const string &)
Setter for the soname property of the corpus.
Definition: abg-corpus.cc:995
exported_decls_builder_sptr get_exported_decls_builder() const
Getter for the object that is responsible for determining what decls ought to be in the set of export...
Definition: abg-corpus.cc:1577
string & get_path() const
Get the file path associated to the corpus file.
Definition: abg-corpus.cc:938
void set_origin(origin)
Setter for the origin of the corpus.
Definition: abg-corpus.cc:892
void set_path(const string &)
Set the file path associated to the corpus file.
Definition: abg-corpus.cc:950
virtual bool recording_types_reachable_from_public_interface_supported()
Test if the recording of reachable types (and thus, indirectly, the recording of non-reachable types)...
Definition: abg-corpus.cc:763
void set_needed(const vector< string > &)
Setter of the needed property of the corpus.
Definition: abg-corpus.cc:973
void set_architecture_name(const string &)
Setter for the architecture name of the corpus.
Definition: abg-corpus.cc:1017
void set_symtab(symtab_reader::symtab_sptr)
Setter for the symtab object.
Definition: abg-corpus.cc:1076
The base type of all declarations.
Definition: abg-ir.h:1516
binding
ELF binding.
Definition: abg-ir.h:1567
visibility
ELF visibility.
Definition: abg-ir.h:1557
binding
The binding of a symbol.
Definition: abg-ir.h:917
static bool get_name_and_version_from_id(const string &id, string &name, string &ver)
Given the ID of a symbol, get the name and the version of said symbol.
Definition: abg-ir.cc:2566
type
The type of a symbol.
Definition: abg-ir.h:904
static elf_symbol_sptr create(const environment &e, size_t i, size_t s, const string &n, type t, binding b, bool d, bool c, const version &ve, visibility vi, bool is_in_ksymtab=false, const abg_compat::optional< uint32_t > &crc={}, const abg_compat::optional< std::string > &ns={}, bool is_suppressed=false)
Factory of instances of elf_symbol.
Definition: abg-ir.cc:1902
visibility
The visibility of the symbol.
Definition: abg-ir.h:926
std::vector< enumerator > enumerators
Convenience typedef for a list of enumerator.
Definition: abg-ir.h:2690
This is an abstraction of the set of resources necessary to manage several aspects of the internal re...
Definition: abg-ir.h:140
bool canonicalization_is_done() const
Test if the canonicalization of types created out of the current environment is done.
Definition: abg-ir.cc:3563
Abstraction for a function declaration.
Definition: abg-ir.h:3024
shared_ptr< parameter > parameter_sptr
Convenience typedef for a shared pointer on a function_decl::parameter.
Definition: abg-ir.h:3044
const type_base_sptr get_return_type() const
Definition: abg-ir.cc:20869
const std::vector< parameter_sptr > & get_parameters() const
Definition: abg-ir.cc:20874
Abstraction of a function type.
Definition: abg-ir.h:3300
type_base_sptr get_return_type() const
Getter for the return type of the current instance of function_type.
Definition: abg-ir.cc:19906
const parameters & get_parameters() const
Getter for the set of parameters of the current intance of function_type.
Definition: abg-ir.cc:19923
This abstracts the global scope of a given translation unit.
Definition: abg-ir.h:1930
The source location of a token.
Definition: abg-ir.h:290
CV
Bit field values representing the cv qualifiers of the underlying type.
Definition: abg-ir.h:2223
A declaration that introduces a scope.
Definition: abg-ir.h:1787
This is the abstraction of the set of relevant artefacts (types, variable declarations,...
Definition: abg-ir.h:663
void set_address_size(char)
Setter of the address size in this translation unit.
Definition: abg-ir.cc:1393
void set_corpus(corpus *)
Set the corpus this translation unit is a member of.
Definition: abg-ir.cc:1335
void set_language(language l)
Setter of the language of the source code of the translation unit.
Definition: abg-ir.cc:1252
const scope_decl_sptr & get_global_scope() const
Getter of the the global scope of the translation unit.
Definition: abg-ir.cc:1188
void set_compilation_dir_path(const std::string &)
Set the path of the directory that was 'current' when the translation unit was compiled.
Definition: abg-ir.cc:1300
void set_path(const string &)
Set the path associated to the current instance of translation_unit.
Definition: abg-ir.cc:1276
The base class of both types and declarations.
Definition: abg-ir.h:1345
Abstraction of a function suppression specification.
Base type of a direct suppression specifications types.
bool has_soname_related_property() const
Test if the current suppression has a property related to SONAMEs.
bool has_file_name_related_property() const
Test if the current suppression has a property related to file name.
Abstraction of a type suppression specification.
static symtab_ptr load(Elf *elf_handle, const ir::environment &env, symbol_predicate is_suppressed=NULL)
Construct a symtab object and instantiate it from an ELF handle. Also pass in the ir::environment we ...
A type used to time various part of the libabigail system.
bool stop()
Stop the timer.
bool start()
Start the timer.
void add_reader_suppressions(reader &rdr, const suppr::suppressions_type &supprs)
Add suppressions specifications to the set of suppressions to be used during the construction of the ...
Definition: abg-reader.cc:1993
corpus_sptr read_corpus_from_abixml(std::istream *in, environment &env)
De-serialize an ABI corpus from an input XML document which root node is 'abi-corpus'.
Definition: abg-reader.cc:6194
translation_unit_sptr read_translation_unit_from_file(const string &input_file, environment &env)
Parse an ABI instrumentation file (in XML format) at a given path.
Definition: abg-reader.cc:2197
corpus_group_sptr read_corpus_group_from_input(fe_iface &iface)
Parse the input XML document containing an ABI corpus group, represented by an 'abi-corpus-group' ele...
Definition: abg-reader.cc:2092
corpus_sptr read_corpus_from_abixml_file(const string &path, environment &env)
De-serialize an ABI corpus from an XML document file which root node is 'abi-corpus'.
Definition: abg-reader.cc:6216
translation_unit_sptr read_translation_unit_from_buffer(const string &buffer, environment &env)
Parse an ABI instrumentation file (in XML format) from an in-memory buffer.
Definition: abg-reader.cc:2219
corpus_group_sptr read_corpus_group_from_abixml(std::istream *in, environment &env)
De-serialize an ABI corpus group from an input XML document which root node is 'abi-corpus-group'.
Definition: abg-reader.cc:2157
fe_iface_sptr create_reader(const string &path, environment &env)
Create an xml_reader::reader to read a native XML ABI file.
Definition: abg-reader.cc:6145
translation_unit_sptr read_translation_unit_from_istream(istream *in, environment &env)
De-serialize a translation unit from an ABI Instrumentation xml file coming from an input stream.
Definition: abg-reader.cc:6121
void consider_types_not_reachable_from_public_interfaces(fe_iface &iface, bool flag)
Configure the reader so that types not reachable from public interface are taken into account when th...
Definition: abg-reader.cc:2012
corpus_group_sptr read_corpus_group_from_abixml_file(const string &path, environment &env)
De-serialize an ABI corpus group from an XML document file which root node is 'abi-corpus-group'.
Definition: abg-reader.cc:2179
shared_ptr< type_tparameter > type_tparameter_sptr
Convenience typedef for a shared pointer to type_tparameter.
Definition: abg-fwd.h:331
shared_ptr< reference_type_def > reference_type_def_sptr
Convenience typedef for a shared pointer on a reference_type_def.
Definition: abg-fwd.h:229
bool is_non_canonicalized_type(const type_base *t)
Test if a given type is allowed to be non canonicalized.
Definition: abg-ir.cc:26449
shared_ptr< function_decl > function_decl_sptr
Convenience typedef for a shared pointer on a function_decl.
Definition: abg-fwd.h:263
access_specifier
Access specifier for class members.
Definition: abg-ir.h:856
shared_ptr< class_tdecl > class_tdecl_sptr
Convenience typedef for a shared pointer on a class_tdecl.
Definition: abg-fwd.h:287
void set_member_function_is_virtual(function_decl &f, bool is_virtual)
Set the virtual-ness of a member function.
Definition: abg-ir.cc:6659
scope_decl * get_type_scope(type_base *t)
Get the scope of a given type.
Definition: abg-ir.cc:8643
bool is_type(const type_or_decl_base &tod)
Test whether a declaration is a type.
Definition: abg-ir.cc:10194
bool is_anonymous_data_member(const decl_base &d)
Test if a decl is an anonymous data member.
Definition: abg-ir.cc:5877
array_type_def::subrange_type * is_subrange_type(const type_or_decl_base *type)
Test if a type is an array_type_def::subrange_type.
Definition: abg-ir.cc:11032
shared_ptr< elf_symbol > elf_symbol_sptr
A convenience typedef for a shared pointer to elf_symbol.
Definition: abg-ir.h:863
shared_ptr< non_type_tparameter > non_type_tparameter_sptr
Convenience typedef for shared pointer to non_type_template_parameter.
Definition: abg-fwd.h:317
bool odr_is_relevant(const type_or_decl_base &artifact)
By looking at the language of the TU a given ABI artifact belongs to, test if the ONE Definition Rule...
Definition: abg-ir.cc:9808
bool is_class_type(const type_or_decl_base &t)
Test whether a type is a class.
Definition: abg-ir.cc:10449
shared_ptr< array_type_def > array_type_def_sptr
Convenience typedef for a shared pointer on a array_type_def.
Definition: abg-fwd.h:234
std::vector< elf_symbol_sptr > elf_symbols
Convenience typedef for a vector of elf_symbol.
Definition: abg-ir.h:881
array_type_def * is_array_type(const type_or_decl_base *type)
Test if a type is an array_type_def.
Definition: abg-ir.cc:10954
reference_type_def * is_reference_type(type_or_decl_base *t)
Test whether a type is a reference_type_def.
Definition: abg-ir.cc:10599
void set_member_function_is_dtor(function_decl &f, bool d)
Set the destructor-ness property of a member function.
Definition: abg-ir.cc:6462
shared_ptr< template_parameter > template_parameter_sptr
Convenience typedef for shared pointer to template parameter.
Definition: abg-fwd.h:312
class_or_union * is_class_or_union_type(const type_or_decl_base *t)
Test if a type is a class_or_union.
Definition: abg-ir.cc:10509
shared_ptr< class_decl > class_decl_sptr
Convenience typedef for a shared pointer on a class_decl.
Definition: abg-fwd.h:187
void set_member_function_is_const(function_decl &f, bool is_const)
set the const-ness property of a member function.
Definition: abg-ir.cc:6518
bool string_to_elf_symbol_type(const string &s, elf_symbol::type &t)
Convert a string representing a symbol type into an elf_symbol::type.
Definition: abg-ir.cc:2878
void set_member_function_is_ctor(function_decl &f, bool c)
Setter for the is_ctor property of the member function.
Definition: abg-ir.cc:6405
const type_decl * is_type_decl(const type_or_decl_base *t)
Test whether a type is a type_decl (a builtin type).
Definition: abg-ir.cc:10278
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:10689
void set_member_access_specifier(decl_base &d, access_specifier a)
Sets the access specifier for a class member.
Definition: abg-ir.cc:5617
typedef_decl_sptr is_typedef(const type_or_decl_base_sptr t)
Test whether a type is a typedef.
Definition: abg-ir.cc:10336
shared_ptr< template_tparameter > template_tparameter_sptr
Convenience typedef for a shared_ptr to template_tparameter.
Definition: abg-fwd.h:325
shared_ptr< function_type > function_type_sptr
Convenience typedef for a shared pointer on a function_type.
Definition: abg-fwd.h:205
shared_ptr< typedef_decl > typedef_decl_sptr
Convenience typedef for a shared pointer on a typedef_decl.
Definition: abg-fwd.h:161
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:873
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:10399
const global_scope * get_global_scope(const decl_base &decl)
return the global scope as seen by a given declaration.
Definition: abg-ir.cc:8386
shared_ptr< var_decl > var_decl_sptr
Convenience typedef for a shared pointer on a var_decl.
Definition: abg-fwd.h:246
shared_ptr< scope_decl > scope_decl_sptr
Convenience typedef for a shared pointer on a scope_decl.
Definition: abg-fwd.h:258
bool string_to_elf_symbol_binding(const string &s, elf_symbol::binding &b)
Convert a string representing a an elf symbol binding into an elf_symbol::binding.
Definition: abg-ir.cc:2911
shared_ptr< type_or_decl_base > type_or_decl_base_sptr
A convenience typedef for a shared_ptr to type_or_decl_base.
Definition: abg-fwd.h:119
shared_ptr< translation_unit > translation_unit_sptr
Convenience typedef for a shared pointer on a translation_unit type.
Definition: abg-fwd.h:134
shared_ptr< string_elf_symbols_map_type > string_elf_symbols_map_sptr
Convenience typedef for a shared pointer to string_elf_symbols_map_type.
Definition: abg-ir.h:890
type_base * type_has_non_canonicalized_subtype(type_base_sptr t)
Test if a type has sub-types that are non-canonicalized.
Definition: abg-ir.cc:26284
bool string_to_elf_symbol_visibility(const string &s, elf_symbol::visibility &v)
Convert a string representing a an elf symbol visibility into an elf_symbol::visibility.
Definition: abg-ir.cc:2936
type_base_sptr canonicalize(type_base_sptr t)
Compute the canonical type of a given type.
Definition: abg-ir.cc:14839
shared_ptr< pointer_type_def > pointer_type_def_sptr
Convenience typedef for a shared pointer on a pointer_type_def.
Definition: abg-fwd.h:220
pointer_type_def * is_pointer_type(type_or_decl_base *t)
Test whether a type is a pointer_type_def.
Definition: abg-ir.cc:10558
translation_unit::language string_to_translation_unit_language(const string &l)
Parse a string representing a language into a translation_unit::language enumerator into a string.
Definition: abg-ir.cc:1575
var_decl * is_var_decl(const type_or_decl_base *tod)
Tests if a declaration is a variable declaration.
Definition: abg-ir.cc:10890
decl_base * is_decl(const type_or_decl_base *d)
Test if an ABI artifact is a declaration.
Definition: abg-ir.cc:10134
method_decl * is_method_decl(const type_or_decl_base *d)
Test if a function_decl is actually a method_decl.
Definition: abg-ir.cc:23624
bool is_member_type(const type_base_sptr &t)
Tests if a type is a class member.
Definition: abg-ir.cc:5537
decl_base_sptr add_decl_to_scope(decl_base_sptr decl, scope_decl *scope)
Appends a declaration to a given scope, if the declaration doesn't already belong to one.
Definition: abg-ir.cc:8293
shared_ptr< enum_type_decl > enum_type_decl_sptr
Convenience typedef for shared pointer to a enum_type_decl.
Definition: abg-fwd.h:169
bool is_union_type(const type_or_decl_base &t)
Test if a type is a union_decl.
Definition: abg-ir.cc:10528
shared_ptr< template_decl > template_decl_sptr
Convenience typedef for a shared pointer to template_decl.
Definition: abg-fwd.h:304
function_type_sptr lookup_function_type(const interned_string &type_name, const translation_unit &tu)
Lookup a function type from a translation unit.
Definition: abg-ir.cc:11657
const decl_base * get_type_declaration(const type_base *t)
Get the declaration for a given type.
Definition: abg-ir.cc:9827
shared_ptr< type_composition > type_composition_sptr
Convenience typedef for shared pointer to type_composition.
Definition: abg-fwd.h:344
void set_member_is_static(decl_base &d, bool s)
Sets the static-ness property of a class member.
Definition: abg-ir.cc:24747
shared_ptr< type_decl > type_decl_sptr
Convenience typedef for a shared pointer on a type_decl.
Definition: abg-fwd.h:156
translation_unit * get_translation_unit(const decl_base &decl)
Return the translation unit a declaration belongs to.
Definition: abg-ir.cc:9910
shared_ptr< namespace_decl > namespace_decl_sptr
Convenience typedef for a shared pointer on namespace_decl.
Definition: abg-fwd.h:282
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:8678
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:10719
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:10669
std::unordered_map< string, elf_symbols > string_elf_symbols_map_type
Convenience typedef for a map which key is a string and which value is a vector of elf_symbol.
Definition: abg-ir.h:886
string build_qualified_name(const scope_decl *scope, const string &name)
Build and return a qualified name from a name and its scope.
Definition: abg-ir.cc:8575
void set_member_function_vtable_offset(function_decl &f, ssize_t s)
Set the vtable offset of a member function.
Definition: abg-ir.cc:6591
shared_ptr< function_tdecl > function_tdecl_sptr
Convenience typedef for a shared pointer on a function_tdecl.
Definition: abg-fwd.h:292
shared_ptr< T > build_sptr(T *p)
This is to be specialized for the diverse C types that needs wrapping in shared_ptr.
shared_ptr< file_suppression > file_suppression_sptr
A convenience typedef for a shared_ptr to file_suppression.
vector< suppression_sptr > suppressions_type
Convenience typedef for a vector of suppression_sptr.
Definition: abg-fwd.h:1533
shared_ptr< function_suppression > function_suppression_sptr
Convenience typedef for a shared pointer to function_suppression.
bool suppression_can_match(const fe_iface &fe, const suppression_base &s)
Test if a given suppression specification can match an ABI artifact coming from the corpus being anal...
file_suppression_sptr is_file_suppression(const suppression_sptr s)
Test if a given suppression specification is a file suppression specification.
bool is_elf_symbol_suppressed(const fe_iface &fe, const elf_symbol_sptr &symbol)
Test if an ELF symbol is suppressed by at least one of the suppression specifications associated with...
bool suppression_matches_soname_or_filename(const string &soname, const string &filename, const suppression_base &suppr)
Test if a given SONAME or file name is matched by a given suppression specification.
bool is_type_suppressed(const fe_iface &fe, const string &type_name, const location &type_location, bool &type_is_private, bool require_drop_property)
Test if a type is matched by at least one suppression specification associated with a given front-end...
bool suppression_matches_type_name_or_location(const type_suppression &s, const string &type_name, const location &type_location)
Test if a type suppression matches a type name and location.
bool is_function_suppressed(const fe_iface &fe, const string &fn_name, const string &fn_linkage_name, bool require_drop_property)
Test if a function is matched by at least one suppression specification associated with a given front...
bool is_variable_suppressed(const fe_iface &fe, const string &var_name, const string &var_linkage_name, bool require_drop_property)
Test if a variable is matched by at least one suppression specification associated with a given front...
bool split_string(const string &input_string, const string &delims, vector< string > &result)
Split a given string into substrings, given some delimiters.
reader_sptr new_reader_from_file(const std::string &path)
Instantiate an xmlTextReader that parses the content of an on-disk file, wrap it into a smart pointer...
bool xml_char_sptr_to_string(xml_char_sptr ssptr, std::string &s)
Convert a shared pointer to xmlChar into an std::string.
reader_sptr new_reader_from_buffer(const std::string &buffer)
Instanciate an xmlTextReader that parses the content of an in-memory buffer, wrap it into a smart poi...
shared_ptr< xmlChar > xml_char_sptr
A convenience typedef for a shared pointer of xmlChar.
void unescape_xml_string(const std::string &str, std::string &escaped)
Read a string, detect the 5 predefined XML entities it may contain and un-escape them,...
reader_sptr new_reader_from_istream(std::istream *in)
Instanciate an xmlTextReader that parses a content coming from an input stream.
shared_ptr< xmlTextReader > reader_sptr
A convenience typedef for a shared pointer of xmlTextReader.
Toplevel namespace for libabigail.