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