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