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