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