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