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