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