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