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