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