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