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