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