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