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