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 to 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 <algorithm>
16 #include <fstream>
17 #include <iomanip>
18 #include <ios>
19 #include <iostream>
20 #include <memory>
21 #include <sstream>
22 #include <stack>
23 #include <unordered_map>
24 #include <vector>
25
26 #include "abg-tools-utils.h"
27
28 #include "abg-internal.h"
29 // <headers defining libabigail's API go under here>
30 ABG_BEGIN_EXPORT_DECLARATIONS
31
32 #include "abg-config.h"
33 #include "abg-corpus.h"
34 #include "abg-diff-utils.h"
35 #include "abg-hash.h"
36 #include "abg-sptr-utils.h"
37
38 #include "abg-writer.h"
39 #include "abg-libxml-utils.h"
40
41 ABG_END_EXPORT_DECLARATIONS
42 // </headers defining libabigail's API>
43
44 namespace abigail
45 {
46 using std::cerr;
47 using std::shared_ptr;
48 using std::dynamic_pointer_cast;
49 using std::static_pointer_cast;
50 using std::ofstream;
51 using std::ostream;
52 using std::ostringstream;
53 using std::list;
54 using std::vector;
55 using std::stack;
56 using std::unordered_map;
57 using abigail::sptr_utils::noop_deleter;
58
59 /// The namespace for the native XML file format writer.
60 ///
61 /// It contains utilities to serialize ABI artifacts from the @ref ir
62 /// namespace into the native XML format.
63 namespace xml_writer
64 {
65
66 class id_manager
67 {
68 const environment* m_env;
69 mutable unsigned long long m_cur_id;
70
71 unsigned long long
get_new_id() const72 get_new_id() const
73 { return ++m_cur_id; }
74
75 public:
id_manager(const environment * env)76 id_manager(const environment* env)
77 : m_env(env),
78 m_cur_id(0) {}
79
80 const environment*
get_environment() const81 get_environment() const
82 {return m_env;}
83
84 /// Return a unique string representing a numerical id.
85 interned_string
get_id() const86 get_id() const
87 {
88 ostringstream o;
89 o << get_new_id();
90 const environment* env = get_environment();
91 ABG_ASSERT(env);
92 return env->intern(o.str());
93 }
94
95 /// Return a unique string representing a numerical ID, prefixed by
96 /// prefix.
97 ///
98 /// @param prefix the prefix of the returned unique id.
99 interned_string
get_id_with_prefix(const string & prefix) const100 get_id_with_prefix(const string& prefix) const
101 {
102 ostringstream o;
103 o << prefix << get_new_id();
104 const environment* env = get_environment();
105 ABG_ASSERT(env);
106 return env->intern(o.str());
107 }
108 };
109
110 /// A hashing functor that should be as fast as possible.
111 struct type_hasher
112 {
113 size_t
operator ()abigail::xml_writer::type_hasher114 operator()(const type_base* t) const
115 {return hash_type(t);}
116 }; // end struct type_hasher
117
118 /// A convenience typedef for a map that associates a pointer to type
119 /// to a string. The pointer to type is hashed as fast as possible.
120 typedef unordered_map<type_base*,
121 interned_string,
122 type_hasher,
123 abigail::diff_utils::deep_ptr_eq_functor> type_ptr_map;
124
125 // A convenience typedef for a set of type_base*.
126 typedef unordered_set<const type_base*, type_hasher,
127 abigail::diff_utils::deep_ptr_eq_functor>
128 type_ptr_set_type;
129
130 /// A convenience typedef for a set of function type*.
131 typedef unordered_set<function_type*, type_hasher,
132 abigail::diff_utils::deep_ptr_eq_functor>
133 fn_type_ptr_set_type;
134
135 typedef unordered_map<shared_ptr<function_tdecl>,
136 string,
137 function_tdecl::shared_ptr_hash> fn_tmpl_shared_ptr_map;
138
139 typedef unordered_map<shared_ptr<class_tdecl>,
140 string,
141 class_tdecl::shared_ptr_hash> class_tmpl_shared_ptr_map;
142
143 class write_context
144 {
145 const environment* m_env;
146 id_manager m_id_manager;
147 ostream* m_ostream;
148 bool m_annotate;
149 bool m_show_locs;
150 bool m_write_architecture;
151 bool m_write_corpus_path;
152 bool m_write_comp_dir;
153 bool m_write_elf_needed;
154 bool m_write_parameter_names;
155 bool m_short_locs;
156 bool m_write_default_sizes;
157 type_id_style_kind m_type_id_style;
158 mutable type_ptr_map m_type_id_map;
159 mutable unordered_set<uint32_t> m_used_type_id_hashes;
160 mutable type_ptr_set_type m_emitted_type_set;
161 type_ptr_set_type m_emitted_decl_only_set;
162 // A map of types that are referenced by emitted pointers,
163 // references or typedefs
164 type_ptr_set_type m_referenced_types_set;
165 fn_type_ptr_set_type m_referenced_fn_types_set;
166 type_ptr_set_type m_referenced_non_canonical_types_set;
167 fn_tmpl_shared_ptr_map m_fn_tmpl_id_map;
168 class_tmpl_shared_ptr_map m_class_tmpl_id_map;
169 string_elf_symbol_sptr_map_type m_fun_symbol_map;
170 string_elf_symbol_sptr_map_type m_var_symbol_map;
171 mutable unordered_map<interned_string,
172 bool,
173 hash_interned_string> m_emitted_decls_map;
174
175 write_context();
176
177 public:
178
179 /// Constructor.
180 ///
181 /// @param env the enviroment we are operating from.
182 ///
183 /// @param os the output stream to write to.
write_context(const environment * env,ostream & os)184 write_context(const environment* env, ostream& os)
185 : m_env(env),
186 m_id_manager(env),
187 m_ostream(&os),
188 m_annotate(false),
189 m_show_locs(true),
190 m_write_architecture(true),
191 m_write_corpus_path(true),
192 m_write_comp_dir(true),
193 m_write_elf_needed(true),
194 m_write_parameter_names(true),
195 m_short_locs(false),
196 m_write_default_sizes(true),
197 m_type_id_style(SEQUENCE_TYPE_ID_STYLE)
198 {}
199
200 /// Getter of the environment we are operating from.
201 ///
202 /// @return the environment we are operating from.
203 const environment*
get_environment() const204 get_environment() const
205 {return m_env;}
206
207 const config&
get_config() const208 get_config() const
209 {
210 ABG_ASSERT(get_environment());
211 return get_environment()->get_config();
212 }
213
214 /// Getter for the current ostream
215 ///
216 /// @return a reference to the current ostream
217 ostream&
get_ostream()218 get_ostream()
219 {return *m_ostream;}
220
221 /// Setter for the current ostream
222 ///
223 /// @param os the new ostream
224 void
set_ostream(ostream & os)225 set_ostream(ostream& os)
226 {m_ostream = &os;}
227
228 /// Getter of the annotation option.
229 ///
230 /// @return true iff ABIXML annotations are turned on
231 bool
get_annotate()232 get_annotate()
233 {return m_annotate;}
234
235 /// Setter of the annotation option.
236 ///
237 /// @param f the new value of the flag.
238 void
set_annotate(bool f)239 set_annotate(bool f)
240 {m_annotate = f;}
241
242 /// Getter of the write-architecture option.
243 ///
244 /// @return true iff architecture information shall be emitted
245 bool
get_write_architecture()246 get_write_architecture()
247 {return m_write_architecture;}
248
249 /// Setter of the write-architecture option
250 ///
251 /// @param f the new value of the flag.
252 void
set_write_architecture(bool f)253 set_write_architecture(bool f)
254 {m_write_architecture = f;}
255
256 /// Getter of the elf-needed option.
257 ///
258 /// @return true iff elf needed information shall be emitted
259 bool
get_write_elf_needed()260 get_write_elf_needed()
261 {return m_write_elf_needed;}
262
263 /// Setter of the elf-needed option.
264 ///
265 /// @param f the new value of the flag.
266 void
set_write_elf_needed(bool f)267 set_write_elf_needed(bool f)
268 {m_write_elf_needed = f;}
269
270 /// Getter of the default-sizes option.
271 ///
272 /// @return true iff default size-in-bits needs to be emitted
273 bool
get_write_default_sizes()274 get_write_default_sizes()
275 {return m_write_default_sizes;}
276
277 /// Setter of the default-sizes option.
278 ///
279 /// @param f the new value of the flag.
280 void
set_write_default_sizes(bool f)281 set_write_default_sizes(bool f)
282 {m_write_default_sizes = f;}
283
284 /// Getter of the write-corpus-path option.
285 ///
286 /// @return true iff corpus-path information shall be emitted
287 bool
get_write_corpus_path()288 get_write_corpus_path()
289 {return m_write_corpus_path;}
290
291 /// Setter of the write-corpus-path option
292 ///
293 /// @param f the new value of the flag.
294 void
set_write_corpus_path(bool f)295 set_write_corpus_path(bool f)
296 {m_write_corpus_path = f;}
297
298 /// Getter of the comp-dir-path option.
299 ///
300 /// @return true iff compilation dir information shall be emitted
301 bool
get_write_comp_dir()302 get_write_comp_dir()
303 {return m_write_comp_dir;}
304
305 /// Setter of the comp-dir-path option
306 ///
307 /// @param f the new value of the flag.
308 void
set_write_comp_dir(bool f)309 set_write_comp_dir(bool f)
310 {m_write_comp_dir = f;}
311
312 /// Getter of the short-locs option.
313 ///
314 /// @return true iff short locations shall be emitted
315 bool
get_short_locs()316 get_short_locs()
317 {return m_short_locs;}
318
319 /// Setter of the short-locs option
320 ///
321 /// @param f the new value of the flag.
322 void
set_short_locs(bool f)323 set_short_locs(bool f)
324 {m_short_locs = f;}
325
326 /// Getter of the parameter-names option.
327 ///
328 /// @return true iff parameter names shall be emitted
329 bool
get_write_parameter_names() const330 get_write_parameter_names() const
331 {return m_write_parameter_names;}
332
333 /// Setter of the parameter-names option
334 ///
335 /// @param f the new value of the flag.
336 void
set_write_parameter_names(bool f)337 set_write_parameter_names(bool f)
338 {m_write_parameter_names = f;}
339
340 /// Getter of the "show-locs" option.
341 ///
342 /// When this option is true then the XML writer emits location
343 /// information for emitted ABI artifacts.
344 ///
345 /// @return the value of the "show-locs" option.
346 bool
get_show_locs() const347 get_show_locs() const
348 {return m_show_locs;}
349
350 /// Setter of the "show-locs" option.
351 ///
352 /// When this option is true then the XML writer emits location
353 /// information for emitted ABI artifacts.
354 ///
355 /// @param f the new value of the "show-locs" option.
356 void
set_show_locs(bool f)357 set_show_locs(bool f)
358 {m_show_locs = f;}
359
360 /// Getter of the "type-id-style" option.
361 ///
362 /// This option controls the kind of type ids used in XML output.
363 ///
364 /// @return the value of the "type-id-style" option.
365 type_id_style_kind
get_type_id_style() const366 get_type_id_style() const
367 {return m_type_id_style;}
368
369 /// Setter of the "type-id-style" option.
370 ///
371 /// This option controls the kind of type ids used in XML output.
372 ///
373 /// @param style the new value of the "type-id-style" option.
374 void
set_type_id_style(type_id_style_kind style)375 set_type_id_style(type_id_style_kind style)
376 {m_type_id_style = style;}
377
378 /// Getter of the @ref id_manager.
379 ///
380 /// @return the @ref id_manager used by the current instance of @ref
381 /// write_context.
382 const id_manager&
get_id_manager() const383 get_id_manager() const
384 {return m_id_manager;}
385
386 id_manager&
get_id_manager()387 get_id_manager()
388 {return m_id_manager;}
389
390 /// @return true iff type has already been assigned an ID.
391 bool
type_has_existing_id(type_base_sptr type) const392 type_has_existing_id(type_base_sptr type) const
393 {return type_has_existing_id(type.get());}
394
395 /// @return true iff type has already been assigned an ID.
396 bool
type_has_existing_id(type_base * type) const397 type_has_existing_id(type_base* type) const
398 {
399 type_base *c = type->get_naked_canonical_type();
400 if (c == 0)
401 c = const_cast<type_base*>(type);
402 return (m_type_id_map.find(c) != m_type_id_map.end());
403 }
404
405 /// Associate a unique id to a given type. For that, put the type
406 /// in a hash table, hashing the type. So if the type has no id
407 /// associated to it, create a new one and return it. Otherwise,
408 /// return the existing id for that type.
409 interned_string
get_id_for_type(const type_base_sptr & t)410 get_id_for_type(const type_base_sptr& t)
411 {return get_id_for_type(t.get());}
412
413 /// Associate a unique id to a given type. For that, put the type
414 /// in a hash table, hashing the type. So if the type has no id
415 /// associated to it, create a new one and return it. Otherwise,
416 /// return the existing id for that type.
417 interned_string
get_id_for_type(const type_base * t) const418 get_id_for_type(const type_base* t) const
419 {
420 type_base *c = t->get_naked_canonical_type();
421 if (c == 0)
422 c = const_cast<type_base*>(t);
423
424 type_ptr_map::const_iterator it = m_type_id_map.find(c);
425 if (it != m_type_id_map.end())
426 return it->second;
427
428 switch (m_type_id_style)
429 {
430 case SEQUENCE_TYPE_ID_STYLE:
431 {
432 interned_string id = get_id_manager().get_id_with_prefix("type-id-");
433 return m_type_id_map[c] = id;
434 }
435 case HASH_TYPE_ID_STYLE:
436 {
437 interned_string pretty = c->get_cached_pretty_representation(true);
438 size_t hash = hashing::fnv_hash(pretty);
439 while (!m_used_type_id_hashes.insert(hash).second)
440 ++hash;
441 std::ostringstream os;
442 os << std::hex << std::setfill('0') << std::setw(8) << hash;
443 return m_type_id_map[c] = c->get_environment()->intern(os.str());
444 }
445 }
446 ABG_ASSERT_NOT_REACHED;
447 return interned_string();
448 }
449
450 string
get_id_for_fn_tmpl(const function_tdecl_sptr & f)451 get_id_for_fn_tmpl(const function_tdecl_sptr& f)
452 {
453 fn_tmpl_shared_ptr_map::const_iterator it = m_fn_tmpl_id_map.find(f);
454 if (it == m_fn_tmpl_id_map.end())
455 {
456 string id = get_id_manager().get_id_with_prefix("fn-tmpl-id-");
457 m_fn_tmpl_id_map[f] = id;
458 return id;
459 }
460 return m_fn_tmpl_id_map[f];
461 }
462
463 string
get_id_for_class_tmpl(const class_tdecl_sptr & c)464 get_id_for_class_tmpl(const class_tdecl_sptr& c)
465 {
466 class_tmpl_shared_ptr_map::const_iterator it = m_class_tmpl_id_map.find(c);
467 if (it == m_class_tmpl_id_map.end())
468 {
469 string id = get_id_manager().get_id_with_prefix("class-tmpl-id-");
470 m_class_tmpl_id_map[c] = id;
471 return id;
472 }
473 return m_class_tmpl_id_map[c];
474 }
475
476 void
clear_type_id_map()477 clear_type_id_map()
478 {m_type_id_map.clear();}
479
480
481 /// Getter of the set of types that were referenced by a pointer,
482 /// reference or typedef.
483 ///
484 /// This set contains only types that do have canonical types and
485 /// which are not function types.
486 ///
487 /// @return the set of types that were referenced.
488 const type_ptr_set_type&
get_referenced_types() const489 get_referenced_types() const
490 {return m_referenced_types_set;}
491
492 /// Getter of the set of function types that were referenced by a
493 /// pointer, reference or typedef.
494 ///
495 /// @return the set of function types that were referenced.
496 const fn_type_ptr_set_type&
get_referenced_function_types() const497 get_referenced_function_types() const
498 {return m_referenced_fn_types_set;}
499
500 /// Getter of the set of types which have no canonical types and
501 /// which were referenced by a pointer, reference or typedef.
502 ///
503 /// @return the of referenced type that have no canonical types.
504 const type_ptr_set_type&
get_referenced_non_canonical_types() const505 get_referenced_non_canonical_types() const
506 {return m_referenced_non_canonical_types_set;}
507
508 /// Record a given type as being referenced by a pointer, a
509 /// reference or a typedef type that is being emitted to the XML
510 /// output.
511 ///
512 /// @param t a shared pointer to a type
513 void
record_type_as_referenced(const type_base_sptr & t)514 record_type_as_referenced(const type_base_sptr& t)
515 {
516 // If the type is a function type, record it in a dedicated data
517 // structure.
518 if (function_type* f = is_function_type(t.get()))
519 m_referenced_fn_types_set.insert(f);
520 else if (!t->get_naked_canonical_type())
521 // If the type doesn't have a canonical type, record it in a
522 // dedicated data structure.
523 m_referenced_non_canonical_types_set.insert(t.get());
524 else
525 m_referenced_types_set.insert(t.get());
526 }
527
528 /// Test if a given type has been referenced by a pointer, a
529 /// reference or a typedef type that was emitted to the XML output.
530 ///
531 /// @param f a shared pointer to a type
532 ///
533 /// @return true if the type has been referenced, false
534 /// otherwise.
535 bool
type_is_referenced(const type_base_sptr & t)536 type_is_referenced(const type_base_sptr& t)
537 {
538 if (function_type *f = is_function_type(t.get()))
539 return (m_referenced_fn_types_set.find(f)
540 != m_referenced_fn_types_set.end());
541 else if (!t->get_naked_canonical_type())
542 return (m_referenced_non_canonical_types_set.find(t.get())
543 != m_referenced_non_canonical_types_set.end());
544 else
545 return m_referenced_types_set.find
546 (t.get()) != m_referenced_types_set.end();
547 }
548
549 /// A comparison functor to compare pointers to @ref type_base.
550 ///
551 /// What is compared is the string representation of the pointed-to
552 /// type.
553 struct type_ptr_cmp
554 {
555 type_ptr_map *map;
type_ptr_cmpabigail::xml_writer::write_context::type_ptr_cmp556 type_ptr_cmp(type_ptr_map *m)
557 : map(m)
558 {}
559
560 /// The comparison operator of the functor.
561 ///
562 /// @param l the first type to consider.
563 ///
564 /// @param r the second type to consider.
565 ///
566 /// @return true if the string representation of type @p l is
567 /// considered to be "less than" the string representation of the
568 /// type @p r.
569 ///
570 /// But when the two string representations are equal (for
571 /// instance, for typedefs that have the same string
572 /// representation), this function compares the type-ids of the
573 /// types. This allows for a stable result.
574 bool
operator ()abigail::xml_writer::write_context::type_ptr_cmp575 operator()(const type_base* l, const type_base* r) const
576 {
577 if (!l && r)
578 return true;
579 if (l && !r)
580 return false;
581 if (!l && !r)
582 return false;
583
584 string r1 = ir::get_pretty_representation(l, true),
585 r2 = ir::get_pretty_representation(r, true);
586
587 if (r1 == r2)
588 {
589 type_ptr_map::const_iterator i =
590 map->find(const_cast<type_base*>(l));
591 if (i != map->end())
592 r1 = i->second;
593 i = map->find(const_cast<type_base*>(r));
594 if (i != map->end())
595 r2 = i->second;
596 }
597
598 return r1 < r2;
599 }
600
601 /// The comparison operator of the functor.
602 ///
603 /// @param l the first type to consider.
604 ///
605 /// @param r the second type to consider.
606 ///
607 /// @return true if the string representation of type @p l is
608 /// considered to be "less than" the string representation of the
609 /// type @p r.
610 ///
611 /// But when the two string representations are equal (for
612 /// instance, for typedefs that have the same string
613 /// representation), this function compares the type-ids of the
614 /// types. This allows for a stable result.
615 bool
operator ()abigail::xml_writer::write_context::type_ptr_cmp616 operator()(const type_base_sptr& l, const type_base_sptr& r) const
617 {return operator()(l.get(), r.get());}
618 }; // end struct type_ptr_cmp
619
620 /// Sort the content of a map of type pointers into a vector.
621 ///
622 /// The pointers are sorted by using their string representation as
623 /// the key to sort, lexicographically.
624 ///
625 /// @param types the map to sort.
626 ///
627 /// @param sorted the resulted sorted vector. It's set by this
628 /// function with the result of the sorting.
629 void
sort_types(type_ptr_set_type & types,vector<type_base * > & sorted)630 sort_types(type_ptr_set_type& types,
631 vector<type_base*>& sorted)
632 {
633 string id;
634 for (type_ptr_set_type::const_iterator i = types.begin();
635 i != types.end();
636 ++i)
637 sorted.push_back(const_cast<type_base*>(*i));
638 type_ptr_cmp comp(&m_type_id_map);
639 sort(sorted.begin(), sorted.end(), comp);
640 }
641
642 /// Sort the content of a map of type pointers into a vector.
643 ///
644 /// The pointers are sorted by using their string representation as
645 /// the key to sort, lexicographically.
646 ///
647 /// @param types the map to sort.
648 ///
649 /// @param sorted the resulted sorted vector. It's set by this
650 /// function with the result of the sorting.
651 void
sort_types(const istring_type_base_wptr_map_type & types,vector<type_base_sptr> & sorted)652 sort_types(const istring_type_base_wptr_map_type& types,
653 vector<type_base_sptr> &sorted)
654 {
655 for (istring_type_base_wptr_map_type::const_iterator i = types.begin();
656 i != types.end();
657 ++i)
658 sorted.push_back(type_base_sptr(i->second));
659 type_ptr_cmp comp(&m_type_id_map);
660 sort(sorted.begin(), sorted.end(), comp);
661 }
662
663 /// Sort the content of a vector of function types into a vector of
664 /// types.
665 ///
666 /// The pointers are sorted by using their string representation as
667 /// the key to sort, lexicographically.
668 ///
669 /// @param types the vector of function types to store.
670 ///
671 /// @param sorted the resulted sorted vector. It's set by this
672 /// function with the result of the sorting.
673 void
sort_types(const vector<function_type_sptr> & types,vector<type_base_sptr> & sorted)674 sort_types(const vector<function_type_sptr>& types,
675 vector<type_base_sptr> &sorted)
676 {
677 for (vector<function_type_sptr>::const_iterator i = types.begin();
678 i != types.end();
679 ++i)
680 sorted.push_back(*i);
681 type_ptr_cmp comp(&m_type_id_map);
682 sort(sorted.begin(), sorted.end(), comp);
683 }
684
685 /// Flag a type as having been written out to the XML output.
686 ///
687 /// @param t the type to flag.
688 void
record_type_as_emitted(const type_base_sptr & t)689 record_type_as_emitted(const type_base_sptr &t)
690 {record_type_as_emitted(t.get());}
691
692 /// Flag a type as having been written out to the XML output.
693 ///
694 /// @param t the type to flag.
695 void
record_type_as_emitted(const type_base * t)696 record_type_as_emitted(const type_base *t)
697 {
698 type_base *c = t->get_naked_canonical_type();
699 if (c == 0)
700 c = const_cast<type_base*>(t);
701 m_emitted_type_set.insert(c);
702 }
703
704 /// Test if a given type has been written out to the XML output.
705 ///
706 /// @param the type to test for.
707 ///
708 /// @return true if the type has already been emitted, false
709 /// otherwise.
710 bool
type_is_emitted(const type_base * t)711 type_is_emitted(const type_base *t)
712 {
713 return m_emitted_type_set.find(t) != m_emitted_type_set.end();
714 }
715
716 /// Test if a given type has been written out to the XML output.
717 ///
718 /// @param the type to test for.
719 ///
720 /// @return true if the type has already been emitted, false
721 /// otherwise.
722 bool
type_is_emitted(const type_base_sptr & t)723 type_is_emitted(const type_base_sptr& t)
724 {return type_is_emitted(t.get());}
725
726 /// Test if the name of a given decl has been written out to the XML
727 /// output.
728 ///
729 /// @param the decl to consider.
730 ///
731 /// @return true if the decl has already been emitted, false
732 /// otherwise.
733 bool
decl_name_is_emitted(const interned_string & name) const734 decl_name_is_emitted(const interned_string& name) const
735 {return m_emitted_decls_map.find(name) != m_emitted_decls_map.end();}
736
737 /// Test if a given decl has been written out to the XML output.
738 ///
739 /// @param the decl to consider.
740 ///
741 /// @return true if the decl has already been emitted, false
742 /// otherwise.
743 bool
decl_is_emitted(decl_base_sptr & decl) const744 decl_is_emitted(decl_base_sptr& decl) const
745 {
746 if (is_type(decl))
747 return false;
748
749 string repr = get_pretty_representation(decl, true);
750 interned_string irepr = decl->get_environment()->intern(repr);
751 bool is_emitted = decl_name_is_emitted(irepr);
752 return is_emitted;
753 }
754
755 /// Record a declaration-only class as being emitted.
756 ///
757 /// For now, this function expects a declaration-only class,
758 /// otherwise, it aborts.
759 ///
760 /// @param t the declaration-only class to report as emitted.
761 void
record_decl_only_type_as_emitted(type_base * t)762 record_decl_only_type_as_emitted(type_base* t)
763 {
764 class_or_union* cl = is_class_or_union_type(t);
765 ABG_ASSERT(cl && cl->get_is_declaration_only());
766 m_emitted_decl_only_set.insert(t);
767 }
768
769 /// Record a declaration-only class as being emitted.
770 ///
771 /// For now, this function expects a declaration-only class,
772 /// otherwise, it aborts.
773 ///
774 /// @param t the declaration-only class to report as emitted.
775 void
record_decl_only_type_as_emitted(const type_base_sptr & t)776 record_decl_only_type_as_emitted(const type_base_sptr& t)
777 {record_decl_only_type_as_emitted(t.get());}
778
779 /// Test if a declaration-only class has been emitted.
780 ///
781 /// @param t the declaration-only class to test for.
782 ///
783 /// @return true iff the declaration-only class @p t has been
784 /// emitted.
785 bool
decl_only_type_is_emitted(const type_base * t)786 decl_only_type_is_emitted(const type_base* t)
787 {
788 type_ptr_set_type::const_iterator i = m_emitted_decl_only_set.find(t);
789 if (i == m_emitted_decl_only_set.end())
790 return false;
791 return true;
792 }
793
794 /// Test if a declaration-only class has been emitted.
795 ///
796 /// @param t the declaration-only class to test for.
797 ///
798 /// @return true iff the declaration-only class @p t has been
799 /// emitted.
800 bool
decl_only_type_is_emitted(const type_base_sptr & t)801 decl_only_type_is_emitted(const type_base_sptr& t)
802 {return decl_only_type_is_emitted(t.get());}
803
804 /// Record a declaration as emitted in the abixml output.
805 ///
806 /// @param decl the decl to consider.
807 void
record_decl_as_emitted(const decl_base_sptr & decl) const808 record_decl_as_emitted(const decl_base_sptr &decl)const
809 {
810 string repr = get_pretty_representation(decl, true);
811 interned_string irepr = decl->get_environment()->intern(repr);
812 m_emitted_decls_map[irepr] = true;
813 }
814
815 /// Clear the map that contains the IDs of the types that has been
816 /// recorded as having been written out to the XML output.
817 void
clear_referenced_types()818 clear_referenced_types()
819 {
820 m_referenced_types_set.clear();
821 m_referenced_non_canonical_types_set.clear();
822 m_referenced_fn_types_set.clear();
823 }
824
825 const string_elf_symbol_sptr_map_type&
get_fun_symbol_map() const826 get_fun_symbol_map() const
827 {return m_fun_symbol_map;}
828
829 string_elf_symbol_sptr_map_type&
get_fun_symbol_map()830 get_fun_symbol_map()
831 {return m_fun_symbol_map;}
832
833 };//end write_context
834
835 static void write_location(const location&, write_context&);
836 static void write_location(const decl_base_sptr&, write_context&);
837 static bool write_visibility(const decl_base_sptr&, ostream&);
838 static bool write_binding(const decl_base_sptr&, ostream&);
839 static bool write_is_artificial(const decl_base_sptr&, ostream&);
840 static bool write_is_non_reachable(const type_base_sptr&, ostream&);
841 static bool write_tracking_non_reachable_types(const corpus_sptr&, ostream&);
842 static void write_array_size_and_alignment(const array_type_def_sptr,
843 ostream&);
844 static void write_size_and_alignment(const type_base_sptr, ostream&,
845 size_t default_size = 0,
846 size_t default_alignment = 0);
847 static void write_access(access_specifier, ostream&);
848 static void write_layout_offset(var_decl_sptr, ostream&);
849 static void write_layout_offset(class_decl::base_spec_sptr, ostream&);
850 static void write_cdtor_const_static(bool, bool, bool, bool, ostream&);
851 static void write_voffset(function_decl_sptr, ostream&);
852 static void write_elf_symbol_type(elf_symbol::type, ostream&);
853 static void write_elf_symbol_binding(elf_symbol::binding, ostream&);
854 static bool write_elf_symbol_aliases(const elf_symbol&, ostream&);
855 static bool write_elf_symbol_reference(const elf_symbol&, ostream&);
856 static bool write_elf_symbol_reference(const elf_symbol_sptr, ostream&);
857 static void write_is_declaration_only(const decl_base_sptr&, ostream&);
858 static void write_is_struct(const class_decl_sptr&, ostream&);
859 static void write_is_anonymous(const decl_base_sptr&, ostream&);
860 static void write_naming_typedef(const class_decl_sptr&, write_context&);
861 static bool write_decl(const decl_base_sptr&, write_context&, unsigned);
862 static void write_decl_in_scope(const decl_base_sptr&,
863 write_context&, unsigned);
864 static bool write_type_decl(const type_decl_sptr&, write_context&, unsigned);
865 static bool write_namespace_decl(const namespace_decl_sptr&,
866 write_context&, unsigned);
867 static bool write_qualified_type_def(const qualified_type_def_sptr&,
868 write_context&, unsigned);
869 static bool write_pointer_type_def(const pointer_type_def_sptr&,
870 write_context&, unsigned);
871 static bool write_reference_type_def(const reference_type_def_sptr&,
872 write_context&, unsigned);
873 static bool write_array_type_def(const array_type_def_sptr&,
874 write_context&, unsigned);
875 static bool write_enum_type_decl(const enum_type_decl_sptr&,
876 write_context&, unsigned);
877 static bool write_typedef_decl(const typedef_decl_sptr&,
878 write_context&, unsigned);
879 static bool write_elf_symbol(const elf_symbol_sptr&,
880 write_context&, unsigned);
881 static bool write_elf_symbols_table(const elf_symbols&,
882 write_context&, unsigned);
883 static bool write_var_decl(const var_decl_sptr&,
884 write_context&, bool, unsigned);
885 static bool write_function_decl(const function_decl_sptr&,
886 write_context&, bool, unsigned);
887 static bool write_function_type(const function_type_sptr&,
888 write_context&, unsigned);
889 static bool write_member_type_opening_tag(const type_base_sptr&,
890 write_context&, unsigned);
891 static bool write_member_type(const type_base_sptr&,
892 write_context&, unsigned);
893 static bool write_class_decl_opening_tag(const class_decl_sptr&, const string&,
894 write_context&, unsigned, bool);
895 static bool write_class_decl(const class_decl_sptr&,
896 write_context&, unsigned);
897 static bool write_union_decl_opening_tag(const union_decl_sptr&, const string&,
898 write_context&, unsigned, bool);
899 static bool write_union_decl(const union_decl_sptr&, const string&,
900 write_context&, unsigned);
901 static bool write_union_decl(const union_decl_sptr&, write_context&, unsigned);
902 static bool write_type_tparameter
903 (const shared_ptr<type_tparameter>, write_context&, unsigned);
904 static bool write_non_type_tparameter
905 (const shared_ptr<non_type_tparameter>, write_context&, unsigned);
906 static bool write_template_tparameter
907 (const shared_ptr<template_tparameter>, write_context&, unsigned);
908 static bool write_type_composition
909 (const shared_ptr<type_composition>, write_context&, unsigned);
910 static bool write_template_parameter(const shared_ptr<template_parameter>,
911 write_context&, unsigned);
912 static void write_template_parameters(const shared_ptr<template_decl>,
913 write_context&, unsigned);
914 static bool write_function_tdecl
915 (const shared_ptr<function_tdecl>,
916 write_context&, unsigned);
917 static bool write_class_tdecl
918 (const shared_ptr<class_tdecl>,
919 write_context&, unsigned);
920 static void do_indent(ostream&, unsigned);
921 static void do_indent_to_level(write_context&, unsigned, unsigned);
922 static unsigned get_indent_to_level(write_context&, unsigned, unsigned);
923
924 /// Emit nb_whitespaces white spaces into the output stream.
925 void
do_indent(ostream & o,unsigned nb_whitespaces)926 do_indent(ostream& o, unsigned nb_whitespaces)
927 {
928 for (unsigned i = 0; i < nb_whitespaces; ++i)
929 o << ' ';
930 }
931
932 /// Indent initial_indent + level number of xml element indentation.
933 ///
934 /// @param ctxt the context of the parsing.
935 ///
936 /// @param initial_indent the initial number of white space to indent to.
937 ///
938 /// @param level the number of indentation level to indent to.
939 static void
do_indent_to_level(write_context & ctxt,unsigned initial_indent,unsigned level)940 do_indent_to_level(write_context& ctxt,
941 unsigned initial_indent,
942 unsigned level)
943 {
944 do_indent(ctxt.get_ostream(),
945 get_indent_to_level(ctxt, initial_indent, level));
946 }
947
948 /// Return the number of white space of indentation that
949 /// #do_indent_to_level would have used.
950 ///
951 /// @param ctxt the context of the parsing.
952 ///
953 /// @param initial_indent the initial number of white space to indent to.
954 ///
955 /// @param level the number of indentation level to indent to.
956 static unsigned
get_indent_to_level(write_context & ctxt,unsigned initial_indent,unsigned level)957 get_indent_to_level(write_context& ctxt, unsigned initial_indent,
958 unsigned level)
959 {
960 int nb_ws = initial_indent +
961 level * ctxt.get_config().get_xml_element_indent();
962 return nb_ws;
963 }
964
965 /// Annotate a declaration in form of an ABIXML comment.
966 ///
967 /// This function is further specialized for declarations and types
968 /// with special requirements.
969 ///
970 /// @tparam T shall be of type decl_base_sptr or a shared pointer to a
971 /// type derived from it, for the instantiation to be syntactically
972 /// correct.
973 ///
974 /// @param decl_sptr the shared pointer to the declaration of type T.
975 ///
976 /// @param ctxt the context of the parsing.
977 ///
978 /// @param indent the amount of white space to indent to.
979 ///
980 /// @return true iff decl is valid.
981 template <typename T>
982 static bool
annotate(const T & decl,write_context & ctxt,unsigned indent)983 annotate(const T& decl,
984 write_context& ctxt,
985 unsigned indent)
986 {
987 if (!decl)
988 return false;
989
990 if (!ctxt.get_annotate())
991 return true;
992
993 ostream& o = ctxt.get_ostream();
994
995 do_indent(o, indent);
996
997 o << "<!-- "
998 << xml::escape_xml_comment(decl->get_pretty_representation())
999 << " -->\n";
1000
1001 return true;
1002 }
1003
1004 /// Annotate an elf symbol in form of an ABIXML comment, effectively
1005 /// writing out its demangled form.
1006 ///
1007 /// @param sym the symbol, whose name should be demangled.
1008 ///
1009 /// @param ctxt the context of the parsing.
1010 ///
1011 /// @param indent the amount of white space to indent to.
1012 ///
1013 /// @return true iff decl is valid
1014 template<>
1015 bool
annotate(const elf_symbol_sptr & sym,write_context & ctxt,unsigned indent)1016 annotate(const elf_symbol_sptr& sym,
1017 write_context& ctxt,
1018 unsigned indent)
1019 {
1020 if (!sym)
1021 return false;
1022
1023 if (!ctxt.get_annotate())
1024 return true;
1025
1026 ostream& o = ctxt.get_ostream();
1027
1028 do_indent(o, indent);
1029 o << "<!-- "
1030 << xml::escape_xml_comment(abigail::ir::demangle_cplus_mangled_name(sym->get_name()))
1031 << " -->\n";
1032
1033 return true;
1034 }
1035
1036 /// Annotate a typedef declaration in form of an ABIXML comment.
1037 ///
1038 /// @param typedef_decl the typedef to annotate.
1039 ///
1040 /// @param ctxt the context of the parsing.
1041 ///
1042 /// @param indent the amount of white space to indent to.
1043 ///
1044 /// @return true iff decl is valid
1045 template<>
1046 bool
annotate(const typedef_decl_sptr & typedef_decl,write_context & ctxt,unsigned indent)1047 annotate(const typedef_decl_sptr& typedef_decl,
1048 write_context& ctxt,
1049 unsigned indent)
1050 {
1051 if (!typedef_decl)
1052 return false;
1053
1054 if (!ctxt.get_annotate())
1055 return true;
1056
1057 ostream& o = ctxt.get_ostream();
1058
1059 do_indent(o, indent);
1060
1061 o << "<!-- typedef "
1062 << get_type_name(typedef_decl->get_underlying_type())
1063 << " "
1064 << get_type_name(typedef_decl)
1065 << " -->\n";
1066
1067 return true;
1068 }
1069
1070 /// Annotate a function type in form of an ABIXML comment.
1071 ///
1072 /// @param function_type the function type to annotate.
1073 ///
1074 /// @param ctxt the context of the parsing.
1075 ///
1076 /// @param indent the amount of white space to indent to.
1077 ///
1078 /// @param skip_first_parm if true, do not serialize the first
1079 /// parameter of the function decl.
1080 //
1081 /// @return true iff decl is valid
1082 bool
annotate(const function_type_sptr & function_type,write_context & ctxt,unsigned indent)1083 annotate(const function_type_sptr& function_type,
1084 write_context& ctxt,
1085 unsigned indent)
1086 {
1087 if (!function_type)
1088 return false;
1089
1090 if (!ctxt.get_annotate())
1091 return true;
1092
1093 ostream& o = ctxt.get_ostream();
1094
1095 do_indent(o, indent);
1096 o << "<!-- "
1097 << xml::escape_xml_comment(get_type_name(function_type->get_return_type()))
1098 << " (";
1099
1100 vector<shared_ptr<function_decl::parameter> >::const_iterator pi =
1101 function_type->get_first_non_implicit_parm();
1102
1103 for (; pi != function_type->get_parameters().end(); ++pi)
1104 {
1105 o << xml::escape_xml_comment((*pi)->get_type_name());
1106 // emit a comma after a param type, unless it's the last one
1107 if (distance(pi, function_type->get_parameters().end()) > 1)
1108 o << ", ";
1109 }
1110 o << ") -->\n";
1111
1112 return true;
1113 }
1114
1115 /// Annotate a function declaration in form of an ABIXML comment.
1116 ///
1117 /// @param fn the function decl to annotate.
1118 ///
1119 /// @param ctxt the context of the parsing.
1120 ///
1121 /// @param indent the amount of white space to indent to.
1122 ///
1123 /// @param skip_first_parm if true, do not serialize the first
1124 /// parameter of the function decl.
1125 //
1126 /// @return true iff decl is valid
1127 static bool
annotate(const function_decl_sptr & fn,write_context & ctxt,unsigned indent)1128 annotate(const function_decl_sptr& fn,
1129 write_context& ctxt,
1130 unsigned indent)
1131 {
1132 if (!fn)
1133 return false;
1134
1135 if (!ctxt.get_annotate())
1136 return true;
1137
1138 ostream& o = ctxt.get_ostream();
1139
1140 do_indent(o, indent);
1141 o << "<!-- ";
1142
1143 if (is_member_function(fn)
1144 && (get_member_function_is_ctor(fn) || get_member_function_is_dtor(fn)))
1145 ; // we don't emit return types for ctor or dtors
1146 else
1147 o << xml::escape_xml_comment(get_type_name(fn->get_return_type()))
1148 << " ";
1149
1150 o << xml::escape_xml_comment(fn->get_qualified_name()) << "(";
1151
1152 vector<function_decl::parameter_sptr>::const_iterator pi =
1153 fn->get_first_non_implicit_parm();
1154
1155 for (; pi != fn->get_parameters().end(); ++pi)
1156 {
1157 o << xml::escape_xml_comment((*pi)->get_type_name());
1158 // emit a comma after a param type, unless it's the last one
1159 if (distance(pi, fn->get_parameters().end()) > 1)
1160 o << ", ";
1161 }
1162 o << ") -->\n";
1163
1164 return true;
1165 }
1166
1167 /// Annotate a function parameter in form of an ABIXML comment.
1168 ///
1169 /// @param parm the function parameter to annotate.
1170 ///
1171 /// @param ctxt the context of the parsing.
1172 ///
1173 /// @param indent the amount of white space to indent to.
1174 ///
1175 /// @return true iff decl is valid
1176 template<>
1177 bool
annotate(const function_decl::parameter_sptr & parm,write_context & ctxt,unsigned indent)1178 annotate(const function_decl::parameter_sptr& parm,
1179 write_context& ctxt,
1180 unsigned indent)
1181 {
1182 if (!parm)
1183 return false;
1184
1185 if (!ctxt.get_annotate())
1186 return true;
1187
1188 ostream &o = ctxt.get_ostream();
1189
1190 do_indent(o, indent);
1191
1192 o << "<!-- ";
1193
1194 if (parm->get_variadic_marker())
1195 o << "variadic parameter";
1196 else
1197 {
1198 if (parm->get_is_artificial())
1199 {
1200 if (parm->get_index() == 0)
1201 o << "implicit ";
1202 else
1203 o << "artificial ";
1204 }
1205 o << "parameter of type '"
1206 << xml::escape_xml_comment(get_pretty_representation(parm->get_type()));
1207 }
1208
1209 o << "' -->\n";
1210
1211 return true;
1212 }
1213
1214 /// Write a location to the output stream.
1215 ///
1216 /// If the location is empty, nothing is written.
1217 ///
1218 /// @param loc the location to consider.
1219 ///
1220 /// @param tu the translation unit the location belongs to.
1221 ///
1222 /// @param ctxt the writer context to use.
1223 static void
write_location(const location & loc,write_context & ctxt)1224 write_location(const location& loc, write_context& ctxt)
1225 {
1226 if (!loc)
1227 return;
1228
1229 if (!ctxt.get_show_locs())
1230 return;
1231
1232 string filepath;
1233 unsigned line = 0, column = 0;
1234
1235 loc.expand(filepath, line, column);
1236
1237 ostream &o = ctxt.get_ostream();
1238
1239 if (ctxt.get_short_locs())
1240 tools_utils::base_name(filepath, filepath);
1241
1242 o << " filepath='" << xml::escape_xml_string(filepath) << "'"
1243 << " line='" << line << "'"
1244 << " column='" << column << "'";
1245 }
1246
1247 /// Write the location of a decl to the output stream.
1248 ///
1249 /// If the location is empty, nothing is written.
1250 ///
1251 /// @param decl the decl to consider.
1252 ///
1253 /// @param ctxt the @ref writer_context to use.
1254 static void
write_location(const decl_base_sptr & decl,write_context & ctxt)1255 write_location(const decl_base_sptr& decl,
1256 write_context& ctxt)
1257 {
1258 if (!decl)
1259 return;
1260
1261 location loc = decl->get_location();
1262 if (!loc)
1263 return;
1264
1265 write_location(loc, ctxt);
1266 }
1267
1268 /// Serialize the visibility property of the current decl as the
1269 /// 'visibility' attribute for the current xml element.
1270 ///
1271 /// @param decl the instance of decl_base to consider.
1272 ///
1273 /// @param o the output stream to serialize the property to.
1274 ///
1275 /// @return true upon successful completion, false otherwise.
1276 static bool
write_visibility(const shared_ptr<decl_base> & decl,ostream & o)1277 write_visibility(const shared_ptr<decl_base>& decl, ostream& o)
1278 {
1279 if (!decl)
1280 return false;
1281
1282 decl_base::visibility v = decl->get_visibility();
1283 string str;
1284
1285 switch (v)
1286 {
1287 case decl_base::VISIBILITY_NONE:
1288 return true;
1289 case decl_base::VISIBILITY_DEFAULT:
1290 str = "default";
1291 break;
1292 case decl_base::VISIBILITY_PROTECTED:
1293 str = "protected";
1294 break;
1295 case decl_base::VISIBILITY_HIDDEN:
1296 str = "hidden";
1297 break;
1298 case decl_base::VISIBILITY_INTERNAL:
1299 str = "internal";
1300 break;
1301 }
1302
1303 if (str.empty())
1304 return false;
1305
1306 o << " visibility='" << str << "'";
1307
1308 return true;
1309 }
1310
1311 /// Serialize the 'binding' property of the current decl.
1312 ///
1313 /// @param decl the decl to consider.
1314 ///
1315 /// @param o the output stream to serialize the property to.
1316 static bool
write_binding(const shared_ptr<decl_base> & decl,ostream & o)1317 write_binding(const shared_ptr<decl_base>& decl, ostream& o)
1318 {
1319 if (!decl)
1320 return false;
1321
1322 decl_base::binding bind = decl_base::BINDING_NONE;
1323
1324 shared_ptr<var_decl> var =
1325 dynamic_pointer_cast<var_decl>(decl);
1326 if (var)
1327 bind = var->get_binding();
1328 else
1329 {
1330 shared_ptr<function_decl> fun =
1331 dynamic_pointer_cast<function_decl>(decl);
1332 if (fun)
1333 bind = fun->get_binding();
1334 }
1335
1336 string str;
1337 switch (bind)
1338 {
1339 case decl_base::BINDING_NONE:
1340 break;
1341 case decl_base::BINDING_LOCAL:
1342 str = "local";
1343 break;
1344 case decl_base::BINDING_GLOBAL:
1345 str = "global";
1346 break;
1347 case decl_base::BINDING_WEAK:
1348 str = "weak";
1349 break;
1350 }
1351
1352 if (!str.empty())
1353 o << " binding='" << str << "'";
1354
1355 return true;
1356 }
1357
1358 /// Write the "is-artificial" attribute of the @ref decl.
1359 ///
1360 /// @param decl the declaration to consider.
1361 ///
1362 /// @param o the output stream to emit the "is-artificial" attribute
1363 /// to.
1364 ///
1365 /// @return true iff the "is-artificial" attribute was emitted.
1366 static bool
write_is_artificial(const decl_base_sptr & decl,ostream & o)1367 write_is_artificial(const decl_base_sptr& decl, ostream& o)
1368 {
1369 if (!decl)
1370 return false;
1371
1372 if (decl->get_is_artificial())
1373 o << " is-artificial='yes'";
1374
1375 return true;
1376 }
1377
1378 /// Write the 'is-non-reachable' attribute if a given type we are
1379 /// looking at is not reachable from global functions and variables
1380 /// and if the user asked us to track that information.
1381 ///
1382 /// @param t the type to consider.
1383 ///
1384 /// @param o the output stream to write the 'is-non-reachable'
1385 /// attribute to.
1386 static bool
write_is_non_reachable(const type_base_sptr & t,ostream & o)1387 write_is_non_reachable(const type_base_sptr& t, ostream& o)
1388 {
1389 if (!t)
1390 return false;
1391
1392 corpus* c = t->get_corpus();
1393 if (!c)
1394 return false;
1395
1396 if (!c->recording_types_reachable_from_public_interface_supported()
1397 || c->type_is_reachable_from_public_interfaces(*t))
1398 return false;
1399
1400 o << " is-non-reachable='yes'";
1401
1402 return true;
1403 }
1404
1405 /// Write the 'tracking-non-reachable-types' attribute if for a given
1406 /// corpus, the user wants us to track non-reachable types.
1407 ///
1408 /// @param corpus the ABI corpus to consider.
1409 ///
1410 /// @param o the output parameter to write the
1411 /// 'tracking-non-reachable-types' attribute to.
1412 static bool
write_tracking_non_reachable_types(const corpus_sptr & corpus,ostream & o)1413 write_tracking_non_reachable_types(const corpus_sptr& corpus,
1414 ostream& o)
1415 {
1416 corpus_group* group = corpus->get_group();
1417 if (!group)
1418 if (corpus->recording_types_reachable_from_public_interface_supported())
1419 {
1420 o << " tracking-non-reachable-types='yes'";
1421 return true;
1422 }
1423
1424 return false;
1425 }
1426
1427 /// Serialize the size and alignment attributes of a given type.
1428 ///
1429 /// @param decl the type to consider.
1430 ///
1431 /// @param o the output stream to serialize to.
1432 ///
1433 /// @param default_size size in bits that is the default for the type.
1434 /// No size-in-bits attribute is written if it
1435 /// would be the default value.
1436 ///
1437 /// @param default_alignment alignment in bits that is the default for
1438 /// the type. No alignment-in-bits attribute is
1439 /// written if it would be the default value.
1440 static void
write_size_and_alignment(const shared_ptr<type_base> decl,ostream & o,size_t default_size,size_t default_alignment)1441 write_size_and_alignment(const shared_ptr<type_base> decl, ostream& o,
1442 size_t default_size, size_t default_alignment)
1443 {
1444 size_t size_in_bits = decl->get_size_in_bits();
1445 if (size_in_bits != default_size)
1446 o << " size-in-bits='" << size_in_bits << "'";
1447
1448 size_t alignment_in_bits = decl->get_alignment_in_bits();
1449 if (alignment_in_bits != default_alignment)
1450 o << " alignment-in-bits='" << alignment_in_bits << "'";
1451 }
1452
1453 /// Serialize the size and alignment attributes of a given type.
1454 /// @param decl the type to consider.
1455 ///
1456 /// @param o the output stream to serialize to.
1457 static void
write_array_size_and_alignment(const shared_ptr<array_type_def> decl,ostream & o)1458 write_array_size_and_alignment(const shared_ptr<array_type_def> decl, ostream& o)
1459 {
1460 if (decl->is_infinite())
1461 o << " size-in-bits='" << "infinite" << "'";
1462 else {
1463 size_t size_in_bits = decl->get_size_in_bits();
1464 if (size_in_bits)
1465 o << " size-in-bits='" << size_in_bits << "'";
1466 }
1467
1468 size_t alignment_in_bits = decl->get_alignment_in_bits();
1469 if (alignment_in_bits)
1470 o << " alignment-in-bits='" << alignment_in_bits << "'";
1471 }
1472 /// Serialize the access specifier.
1473 ///
1474 /// @param a the access specifier to serialize.
1475 ///
1476 /// @param o the output stream to serialize it to.
1477 static void
write_access(access_specifier a,ostream & o)1478 write_access(access_specifier a, ostream& o)
1479 {
1480 string access_str = "private";
1481
1482 switch (a)
1483 {
1484 case private_access:
1485 access_str = "private";
1486 break;
1487
1488 case protected_access:
1489 access_str = "protected";
1490 break;
1491
1492 case public_access:
1493 access_str = "public";
1494 break;
1495
1496 default:
1497 break;
1498 }
1499
1500 o << " access='" << access_str << "'";
1501 }
1502
1503 /// Serialize the layout offset of a data member.
1504 static void
write_layout_offset(var_decl_sptr member,ostream & o)1505 write_layout_offset(var_decl_sptr member, ostream& o)
1506 {
1507 if (!is_data_member(member))
1508 return;
1509
1510 if (get_data_member_is_laid_out(member))
1511 o << " layout-offset-in-bits='"
1512 << get_data_member_offset(member)
1513 << "'";
1514 }
1515
1516 /// Serialize the layout offset of a base class
1517 static void
write_layout_offset(shared_ptr<class_decl::base_spec> base,ostream & o)1518 write_layout_offset(shared_ptr<class_decl::base_spec> base, ostream& o)
1519 {
1520 if (!base)
1521 return;
1522
1523 if (base->get_offset_in_bits() >= 0)
1524 o << " layout-offset-in-bits='" << base->get_offset_in_bits() << "'";
1525 }
1526
1527 /// Serialize the access specifier of a class member.
1528 ///
1529 /// @param member a pointer to the class member to consider.
1530 ///
1531 /// @param o the ostream to serialize the member to.
1532 static void
write_access(decl_base_sptr member,ostream & o)1533 write_access(decl_base_sptr member, ostream& o)
1534 {write_access(get_member_access_specifier(member), o);}
1535
1536 /// Write the voffset of a member function if it's non-zero
1537 ///
1538 /// @param fn the member function to consider
1539 ///
1540 /// @param o the output stream to write to
1541 static void
write_voffset(function_decl_sptr fn,ostream & o)1542 write_voffset(function_decl_sptr fn, ostream&o)
1543 {
1544 if (!fn)
1545 return;
1546
1547 if (get_member_function_is_virtual(fn))
1548 {
1549 ssize_t voffset = get_member_function_vtable_offset(fn);
1550 o << " vtable-offset='" << voffset << "'";
1551 }
1552 }
1553
1554 /// Serialize an elf_symbol::type into an XML node attribute named
1555 /// 'type'.
1556 ///
1557 /// @param t the elf_symbol::type to serialize.
1558 ///
1559 /// @param o the output stream to serialize it to.
1560 static void
write_elf_symbol_type(elf_symbol::type t,ostream & o)1561 write_elf_symbol_type(elf_symbol::type t, ostream& o)
1562 {
1563 string repr;
1564
1565 switch (t)
1566 {
1567 case elf_symbol::NOTYPE_TYPE:
1568 repr = "no-type";
1569 break;
1570 case elf_symbol::OBJECT_TYPE:
1571 repr = "object-type";
1572 break;
1573 case elf_symbol::FUNC_TYPE:
1574 repr = "func-type";
1575 break;
1576 case elf_symbol::SECTION_TYPE:
1577 repr = "section-type";
1578 break;
1579 case elf_symbol::FILE_TYPE:
1580 repr = "file-type";
1581 break;
1582 case elf_symbol::COMMON_TYPE:
1583 repr = "common-type";
1584 break;
1585 case elf_symbol::TLS_TYPE:
1586 repr = "tls-type";
1587 break;
1588 case elf_symbol::GNU_IFUNC_TYPE:
1589 repr = "gnu-ifunc-type";
1590 break;
1591 default:
1592 repr = "no-type";
1593 break;
1594 }
1595
1596 o << " type='" << repr << "'";
1597 }
1598
1599 /// Serialize an elf_symbol::binding into an XML element attribute of
1600 /// name 'binding'.
1601 ///
1602 /// @param b the elf_symbol::binding to serialize.
1603 ///
1604 /// @param o the output stream to serialize the binding to.
1605 static void
write_elf_symbol_binding(elf_symbol::binding b,ostream & o)1606 write_elf_symbol_binding(elf_symbol::binding b, ostream& o)
1607 {
1608 string repr;
1609
1610 switch (b)
1611 {
1612 case elf_symbol::LOCAL_BINDING:
1613 repr = "local-binding";
1614 break;
1615 case elf_symbol::GLOBAL_BINDING:
1616 repr = "global-binding";
1617 break;
1618 case elf_symbol::WEAK_BINDING:
1619 repr = "weak-binding";
1620 break;
1621 case elf_symbol::GNU_UNIQUE_BINDING:
1622 repr = "gnu-unique-binding";
1623 break;
1624 default:
1625 repr = "no-binding";
1626 break;
1627 }
1628
1629 o << " binding='" << repr << "'";
1630 }
1631
1632 /// Serialize an elf_symbol::binding into an XML element attribute of
1633 /// name 'binding'.
1634 ///
1635 /// @param b the elf_symbol::binding to serialize.
1636 ///
1637 /// @param o the output stream to serialize the binding to.
1638 static void
write_elf_symbol_visibility(elf_symbol::visibility v,ostream & o)1639 write_elf_symbol_visibility(elf_symbol::visibility v, ostream& o)
1640 {
1641 string repr;
1642
1643 switch (v)
1644 {
1645 case elf_symbol::DEFAULT_VISIBILITY:
1646 repr = "default-visibility";
1647 break;
1648 case elf_symbol::PROTECTED_VISIBILITY:
1649 repr = "protected-visibility";
1650 break;
1651 case elf_symbol::HIDDEN_VISIBILITY:
1652 repr = "hidden-visibility";
1653 break;
1654 case elf_symbol::INTERNAL_VISIBILITY:
1655 repr = "internal-visibility";
1656 break;
1657 default:
1658 repr = "default-visibility";
1659 break;
1660 }
1661
1662 o << " visibility='" << repr << "'";
1663 }
1664
1665 /// Write alias attributes for the aliases of a given symbol.
1666 ///
1667 /// @param sym the symbol to write the attributes for.
1668 ///
1669 /// @param o the output stream to write the attributes to.
1670 ///
1671 /// @return true upon successful completion.
1672 static bool
write_elf_symbol_aliases(const elf_symbol & sym,ostream & out)1673 write_elf_symbol_aliases(const elf_symbol& sym, ostream& out)
1674 {
1675 if (!sym.is_main_symbol() || !sym.has_aliases())
1676 return false;
1677
1678
1679 std::vector<std::string> aliases;
1680 for (elf_symbol_sptr s = sym.get_next_alias(); s && !s->is_main_symbol();
1681 s = s->get_next_alias())
1682 {
1683 if (!s->is_public())
1684 continue;
1685
1686 if (s->is_suppressed())
1687 continue;
1688
1689 if (sym.is_in_ksymtab() != s->is_in_ksymtab())
1690 continue;
1691
1692 aliases.push_back(s->get_id_string());
1693 }
1694
1695 if (!aliases.empty())
1696 {
1697 out << " alias='";
1698 std::string separator;
1699 for (const auto& alias : aliases)
1700 {
1701 out << separator << alias;
1702 separator = ",";
1703 }
1704
1705 out << "'";
1706 return true;
1707 }
1708
1709 return false;
1710 }
1711
1712 /// Write an XML attribute for the reference to a symbol for the
1713 /// current decl.
1714 ///
1715 /// @param sym the symbol to consider.
1716 ///
1717 /// @param o the output stream to write the attribute to.
1718 ///
1719 /// @return true upon successful completion.
1720 static bool
write_elf_symbol_reference(const elf_symbol & sym,ostream & o)1721 write_elf_symbol_reference(const elf_symbol& sym, ostream& o)
1722 {
1723 const elf_symbol* main = sym.get_main_symbol().get();
1724 const elf_symbol* alias = &sym;
1725 bool found = !alias->is_suppressed();
1726 // If the symbol itself is suppressed, check the alias chain.
1727 if (!found)
1728 {
1729 alias = main;
1730 found = !alias->is_suppressed();
1731 }
1732 // If the main symbol is suppressed, search the remainder of the chain.
1733 while (!found)
1734 {
1735 alias = alias->get_next_alias().get();
1736 // Two separate termination conditions at present.
1737 if (!alias || alias == main)
1738 break;
1739 found = !alias->is_suppressed();
1740 }
1741 // If all aliases are suppressed, just stick with the main symbol.
1742 if (!found)
1743 alias = main;
1744 o << " elf-symbol-id='" << alias->get_id_string() << "'";
1745 return true;
1746 }
1747
1748 /// Write an XML attribute for the reference to a symbol for the
1749 /// current decl.
1750 ///
1751 /// @param sym the symbol to consider.
1752 ///
1753 /// @param o the output stream to write the attribute to.
1754 ///
1755 /// @return true upon successful completion.
1756 static bool
write_elf_symbol_reference(const elf_symbol_sptr sym,ostream & o)1757 write_elf_symbol_reference(const elf_symbol_sptr sym, ostream& o)
1758 {
1759 if (!sym)
1760 return false;
1761
1762 return write_elf_symbol_reference(*sym, o);
1763 }
1764
1765 /// Serialize the attributes "constructor", "destructor" or "static"
1766 /// if they have true value.
1767 ///
1768 /// @param is_ctor if set to true, the "constructor='true'" string is
1769 /// emitted.
1770 ///
1771 /// @param is_dtor if set to true the "destructor='true' string is
1772 /// emitted.
1773 ///
1774 /// @param is_static if set to true the "static='true'" string is
1775 /// emitted.
1776 ///
1777 /// @param o the output stream to use for the serialization.
1778 static void
write_cdtor_const_static(bool is_ctor,bool is_dtor,bool is_const,bool is_static,ostream & o)1779 write_cdtor_const_static(bool is_ctor,
1780 bool is_dtor,
1781 bool is_const,
1782 bool is_static,
1783 ostream& o)
1784 {
1785 if (is_static)
1786 o << " static='yes'";
1787 if (is_ctor)
1788 o << " constructor='yes'";
1789 else if (is_dtor)
1790 o << " destructor='yes'";
1791 if (is_const)
1792 o << " const='yes'";
1793 }
1794
1795 /// Serialize the attribute "is-declaration-only", if the
1796 /// decl_base_sptr has its 'is_declaration_only property set.
1797 ///
1798 /// @param t the pointer to instance of @ref decl_base to consider.
1799 ///
1800 /// @param o the output stream to serialize to.
1801 static void
write_is_declaration_only(const decl_base_sptr & d,ostream & o)1802 write_is_declaration_only(const decl_base_sptr& d, ostream& o)
1803 {
1804 if (d->get_is_declaration_only())
1805 o << " is-declaration-only='yes'";
1806 }
1807
1808 /// Serialize the attribute "is-struct", if the current instance of
1809 /// class_decl is a struct.
1810 ///
1811 /// @param klass a pointer to the instance of class_decl to consider.
1812 ///
1813 /// @param o the output stream to serialize to.
1814 static void
write_is_struct(const class_decl_sptr & klass,ostream & o)1815 write_is_struct(const class_decl_sptr& klass, ostream& o)
1816 {
1817 if (klass->is_struct())
1818 o << " is-struct='yes'";
1819 }
1820
1821 /// Serialize the attribute "is-anonymous", if the current instance of
1822 /// decl is anonymous
1823 ///
1824 /// @param dcl a pointer to the instance of @ref decl_base to consider.
1825 ///
1826 /// @param o the output stream to serialize to.
1827 static void
write_is_anonymous(const decl_base_sptr & decl,ostream & o)1828 write_is_anonymous(const decl_base_sptr& decl, ostream& o)
1829 {
1830 if (decl->get_is_anonymous())
1831 o << " is-anonymous='yes'";
1832 }
1833
1834 /// Serialize the "naming-typedef-id" attribute, if the current
1835 /// instance of @ref class_decl has a naming typedef.
1836 ///
1837 /// @param klass the @ref class_decl to consider.
1838 ///
1839 /// @param ctxt the write context to use.
1840 static void
write_naming_typedef(const class_decl_sptr & klass,write_context & ctxt)1841 write_naming_typedef(const class_decl_sptr& klass, write_context& ctxt)
1842 {
1843 if (!klass)
1844 return;
1845
1846 ostream &o = ctxt.get_ostream();
1847
1848 if (typedef_decl_sptr typedef_type = klass->get_naming_typedef())
1849 {
1850 string id = ctxt.get_id_for_type(typedef_type);
1851 o << " naming-typedef-id='" << id << "'";
1852 }
1853 }
1854
1855 /// Helper to serialize a type artifact.
1856 ///
1857 /// @param type the type to serialize.
1858 ///
1859 /// @param ctxt the @ref write_context to use.
1860 ///
1861 /// @param indent the number of white space to use for indentation.
1862 ///
1863 /// @return true upon successful completion.
1864 static bool
write_type(const type_base_sptr & type,write_context & ctxt,unsigned indent)1865 write_type(const type_base_sptr& type, write_context& ctxt, unsigned indent)
1866 {
1867 if (write_type_decl(dynamic_pointer_cast<type_decl> (type),
1868 ctxt, indent)
1869 || write_qualified_type_def (dynamic_pointer_cast<qualified_type_def>
1870 (type),
1871 ctxt, indent)
1872 || write_pointer_type_def(dynamic_pointer_cast<pointer_type_def>(type),
1873 ctxt, indent)
1874 || write_reference_type_def(dynamic_pointer_cast
1875 <reference_type_def>(type), ctxt, indent)
1876 || write_array_type_def(dynamic_pointer_cast
1877 <array_type_def>(type), ctxt, indent)
1878 || write_enum_type_decl(dynamic_pointer_cast<enum_type_decl>(type),
1879 ctxt, indent)
1880 || write_typedef_decl(dynamic_pointer_cast<typedef_decl>(type),
1881 ctxt, indent)
1882 || write_class_decl(is_class_type(type), ctxt, indent)
1883 || write_union_decl(is_union_type(type), ctxt, indent)
1884 || (write_function_tdecl
1885 (dynamic_pointer_cast<function_tdecl>(type), ctxt, indent))
1886 || (write_class_tdecl
1887 (dynamic_pointer_cast<class_tdecl>(type), ctxt, indent)))
1888 return true;
1889
1890 return false;
1891 }
1892
1893 /// Serialize a pointer to an of decl_base into an output stream.
1894 ///
1895 /// @param decl the pointer to decl_base to serialize
1896 ///
1897 /// @param ctxt the context of the serialization. It contains e.g, the
1898 /// output stream to serialize to.
1899 ///
1900 /// @param indent how many indentation spaces to use during the
1901 /// serialization.
1902 ///
1903 /// @return true upon successful completion, false otherwise.
1904 static bool
write_decl(const decl_base_sptr & decl,write_context & ctxt,unsigned indent)1905 write_decl(const decl_base_sptr& decl, write_context& ctxt, unsigned indent)
1906 {
1907 if (write_type_decl(dynamic_pointer_cast<type_decl> (decl),
1908 ctxt, indent)
1909 || write_namespace_decl(dynamic_pointer_cast<namespace_decl>(decl),
1910 ctxt, indent)
1911 || write_qualified_type_def (dynamic_pointer_cast<qualified_type_def>
1912 (decl),
1913 ctxt, indent)
1914 || write_pointer_type_def(dynamic_pointer_cast<pointer_type_def>(decl),
1915 ctxt, indent)
1916 || write_reference_type_def(dynamic_pointer_cast
1917 <reference_type_def>(decl), ctxt, indent)
1918 || write_array_type_def(dynamic_pointer_cast
1919 <array_type_def>(decl), ctxt, indent)
1920 || write_enum_type_decl(dynamic_pointer_cast<enum_type_decl>(decl),
1921 ctxt, indent)
1922 || write_typedef_decl(dynamic_pointer_cast<typedef_decl>(decl),
1923 ctxt, indent)
1924 || write_var_decl(dynamic_pointer_cast<var_decl>(decl), ctxt,
1925 /*write_linkage_name=*/true, indent)
1926 || write_function_decl(dynamic_pointer_cast<method_decl>
1927 (decl), ctxt, /*skip_first_parameter=*/true,
1928 indent)
1929 || write_function_decl(dynamic_pointer_cast<function_decl>(decl),
1930 ctxt, /*skip_first_parameter=*/false, indent)
1931 || write_class_decl(is_class_type(decl), ctxt, indent)
1932 || write_union_decl(is_union_type(decl), ctxt, indent)
1933 || (write_function_tdecl
1934 (dynamic_pointer_cast<function_tdecl>(decl), ctxt, indent))
1935 || (write_class_tdecl
1936 (dynamic_pointer_cast<class_tdecl>(decl), ctxt, indent)))
1937 return true;
1938
1939 return false;
1940 }
1941
1942 /// Emit a declaration, along with its scope.
1943 ///
1944 /// This function is called at the end of emitting a translation unit,
1945 /// to emit type declarations that were referenced by types that were
1946 /// emitted in the TU already, but that were not emitted themselves.
1947 ///
1948 /// @param decl the decl to emit.
1949 ///
1950 /// @param ctxt the write context to use.
1951 ///
1952 /// @param initial_indent the number of indentation spaces to use.
1953 static void
write_decl_in_scope(const decl_base_sptr & decl,write_context & ctxt,unsigned initial_indent)1954 write_decl_in_scope(const decl_base_sptr& decl,
1955 write_context& ctxt,
1956 unsigned initial_indent)
1957 {
1958 type_base_sptr type = is_type(decl);
1959 ABG_ASSERT(type);
1960
1961 if (ctxt.type_is_emitted(type))
1962 return;
1963
1964 list<scope_decl*> scopes;
1965 for (scope_decl* s = decl->get_scope();
1966 s && !is_global_scope(s);
1967 s = s->get_scope())
1968 scopes.push_front(s);
1969
1970 ostream& o = ctxt.get_ostream();
1971 const config& c = ctxt.get_config();
1972 stack<string> closing_tags;
1973 stack<unsigned> closing_indents;
1974 unsigned indent = initial_indent;
1975 for (list<scope_decl*>::const_iterator i = scopes.begin();
1976 i != scopes.end();
1977 ++i)
1978 {
1979 ABG_ASSERT(!is_global_scope(*i));
1980
1981 // A type scope is either a namespace ...
1982 if (namespace_decl* n = is_namespace(*i))
1983 {
1984 do_indent(o, indent);
1985 o << "<namespace-decl name='"
1986 << xml::escape_xml_string(n->get_name())
1987 << "'>\n";
1988 closing_tags.push("</namespace-decl>");
1989 closing_indents.push(indent);
1990 }
1991 // ... or a class.
1992 else if (class_decl* c = is_class_type(*i))
1993 {
1994 class_decl_sptr class_type(c, noop_deleter());
1995 write_class_decl_opening_tag(class_type, "", ctxt, indent,
1996 /*prepare_to_handle_members=*/false);
1997 closing_tags.push("</class-decl>");
1998 closing_indents.push(indent);
1999
2000 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1);
2001 write_member_type_opening_tag(type, ctxt, nb_ws);
2002 indent = nb_ws;
2003 closing_tags.push("</member-type>");
2004 closing_indents.push(nb_ws);
2005 }
2006 else if (union_decl *u = is_union_type(*i))
2007 {
2008 union_decl_sptr union_type(u, noop_deleter());
2009 write_union_decl_opening_tag(union_type, "", ctxt, indent,
2010 /*prepare_to_handle_members=*/false);
2011 closing_tags.push("</union-decl>");
2012 closing_indents.push(indent);
2013
2014 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1);
2015 write_member_type_opening_tag(type, ctxt, nb_ws);
2016 indent = nb_ws;
2017 closing_tags.push("</member-type>");
2018 closing_indents.push(nb_ws);
2019 }
2020 else
2021 // We should never reach this point.
2022 abort();
2023 indent += c.get_xml_element_indent();
2024 }
2025
2026 write_decl(decl, ctxt, indent);
2027
2028 while (!closing_tags.empty())
2029 {
2030 do_indent(o, closing_indents.top());
2031 o << closing_tags.top() << "\n";
2032 closing_tags.pop();
2033 closing_indents.pop();
2034 }
2035 }
2036
2037 /// Create a @ref write_context object that can be used to emit abixml
2038 /// files.
2039 ///
2040 /// @param env the environment for the @ref write_context object to use.
2041 ///
2042 /// @param default_output_stream the default output stream to use.
2043 ///
2044 /// @return the new @ref write_context object.
2045 write_context_sptr
create_write_context(const environment * env,ostream & default_output_stream)2046 create_write_context(const environment *env,
2047 ostream& default_output_stream)
2048 {
2049 write_context_sptr ctxt(new write_context(env, default_output_stream));
2050 return ctxt;
2051 }
2052
2053 /// Set the "show-locs" flag.
2054 ///
2055 /// When this flag is set then the XML writer emits location (///
2056 /// information (file name, line and column) for the ABI artifacts
2057 /// that it emits.
2058 ///
2059 /// @param ctxt the @ref write_context to set the option for.
2060 ///
2061 /// @param flag the new value of the option.
2062 void
set_show_locs(write_context & ctxt,bool flag)2063 set_show_locs(write_context& ctxt, bool flag)
2064 {ctxt.set_show_locs(flag);}
2065
2066 /// Set the 'annotate' flag.
2067 ///
2068 /// When this flag is set then the XML writer annotates ABI artifacts
2069 /// with a human readable description.
2070 ///
2071 /// @param ctxt the context to set this flag on to.
2072 ///
2073 /// @param flag the new value of the 'annotate' flag.
2074 void
set_annotate(write_context & ctxt,bool flag)2075 set_annotate(write_context& ctxt, bool flag)
2076 {ctxt.set_annotate(flag);}
2077
2078 /// Set the new ostream.
2079 ///
2080 /// The ostream refers to the object, writers should stream new output to.
2081 ///
2082 /// @param ctxt the context to set this to.
2083 ///
2084 /// @param os the new ostream
2085 void
set_ostream(write_context & ctxt,ostream & os)2086 set_ostream(write_context& ctxt, ostream& os)
2087 {ctxt.set_ostream(os);}
2088
2089 /// Set the 'write-architecture' flag.
2090 ///
2091 /// When this flag is set then the XML writer will emit architecture
2092 /// information
2093 ///
2094 /// @param ctxt the context to set this flag on to.
2095 ///
2096 /// @param flag the new value of the 'write-architecture' flag.
2097 void
set_write_architecture(write_context & ctxt,bool flag)2098 set_write_architecture(write_context& ctxt, bool flag)
2099 {ctxt.set_write_architecture(flag);}
2100
2101 /// Set the 'write-corpus-path' flag.
2102 ///
2103 /// When this flag is set then the XML writer will emit corpus-path
2104 /// information
2105 ///
2106 /// @param ctxt the context to set this flag on to.
2107 ///
2108 /// @param flag the new value of the 'write-corpus-path' flag.
2109 void
set_write_corpus_path(write_context & ctxt,bool flag)2110 set_write_corpus_path(write_context& ctxt, bool flag)
2111 {ctxt.set_write_corpus_path(flag);}
2112
2113 /// Set the 'write-comp-dir' flag.
2114 ///
2115 /// When this flag is set then the XML writer will emit compilation dir
2116 /// information
2117 ///
2118 /// @param ctxt the context to set this flag on to.
2119 ///
2120 /// @param flag the new value of the 'write-comp-dir' flag.
2121 void
set_write_comp_dir(write_context & ctxt,bool flag)2122 set_write_comp_dir(write_context& ctxt, bool flag)
2123 {ctxt.set_write_comp_dir(flag);}
2124
2125 /// Set the 'short-locs' flag.
2126 ///
2127 /// When this flag is set then the XML writer will emit only file names
2128 /// rather than full paths.
2129 ///
2130 /// @param ctxt the context to set this flag on to.
2131 ///
2132 /// @param flag the new value of the 'short-locs' flag.
2133 void
set_short_locs(write_context & ctxt,bool flag)2134 set_short_locs(write_context& ctxt, bool flag)
2135 {ctxt.set_short_locs(flag);}
2136
2137 /// Set the 'parameter-names' flag.
2138 ///
2139 /// When this flag is set then the XML writer will emit the names of
2140 /// function parameters.
2141 ///
2142 /// @param ctxt the context to set this flag on to.
2143 ///
2144 /// @param flag the new value of the 'parameter-names' flag.
2145 void
set_write_parameter_names(write_context & ctxt,bool flag)2146 set_write_parameter_names(write_context& ctxt, bool flag)
2147 {ctxt.set_write_parameter_names(flag);}
2148
2149 /// Set the 'elf-needed' flag.
2150 ///
2151 /// When this flag is set then the XML writer will emit corpus
2152 /// get_needed() (DT_NEEDED) information.
2153 ///
2154 /// @param ctxt the context to set this flag on to.
2155 ///
2156 /// @param flag the new value of the 'elf-needed' flag.
2157 void
set_write_elf_needed(write_context & ctxt,bool flag)2158 set_write_elf_needed(write_context& ctxt, bool flag)
2159 {ctxt.set_write_elf_needed(flag);}
2160
2161 /// Set the 'default-sizes' flag.
2162 ///
2163 /// When this flag is set then the XML writer will emit default
2164 /// size-in-bits attributes for pointer type definitions, reference
2165 /// type definitions, function declarations and function types even
2166 /// when they are equal to the default address size of the translation
2167 /// unit.
2168 ///
2169 /// @param ctxt the context to set this flag on to.
2170 ///
2171 /// @param flag the new value of the 'default-sizes' flag.
2172 void
set_write_default_sizes(write_context & ctxt,bool flag)2173 set_write_default_sizes(write_context& ctxt, bool flag)
2174 {ctxt.set_write_default_sizes(flag);}
2175
2176 /// Set the 'type-id-style' property.
2177 ///
2178 /// This property controls the kind of type ids used in XML output.
2179 ///
2180 /// @param ctxt the context to set this property on.
2181 ///
2182 /// @param style the new value of the 'type-id-style' property.
2183 void
set_type_id_style(write_context & ctxt,type_id_style_kind style)2184 set_type_id_style(write_context& ctxt, type_id_style_kind style)
2185 {ctxt.set_type_id_style(style);}
2186
2187 /// Serialize the canonical types of a given scope.
2188 ///
2189 /// @param scope the scope to consider.
2190 ///
2191 /// @param ctxt the write context to use.
2192 ///
2193 /// @param indent the number of white space indentation to use.
2194 //
2195 // @param is_member_type if true, the canonical types are emitted as
2196 // member types (of a class).
2197 //
2198 // return true upon successful completion.
2199 static bool
write_canonical_types_of_scope(const scope_decl & scope,write_context & ctxt,const unsigned indent,bool is_member_type=false)2200 write_canonical_types_of_scope(const scope_decl &scope,
2201 write_context &ctxt,
2202 const unsigned indent,
2203 bool is_member_type = false)
2204 {
2205 const type_base_sptrs_type &canonical_types =
2206 scope.get_sorted_canonical_types();
2207
2208 for (type_base_sptrs_type::const_iterator i = canonical_types.begin();
2209 i != canonical_types.end();
2210 ++i)
2211 {
2212 if (is_member_type)
2213 write_member_type(*i, ctxt, indent);
2214 else
2215 write_type(*i, ctxt, indent);
2216 }
2217
2218 return true;
2219 }
2220
2221 /// Serialize a translation unit to an output stream.
2222 ///
2223 /// @param ctxt the context of the serialization. It contains e.g,
2224 /// the output stream to serialize to.
2225 ///
2226 /// @param tu the translation unit to serialize.
2227 ///
2228 /// @param indent how many indentation spaces to use during the
2229 /// serialization.
2230 ///
2231 /// @return true upon successful completion, false otherwise.
2232 bool
write_translation_unit(write_context & ctxt,const translation_unit & tu,const unsigned indent)2233 write_translation_unit(write_context& ctxt,
2234 const translation_unit& tu,
2235 const unsigned indent)
2236 {
2237 ostream& o = ctxt.get_ostream();
2238 const config& c = ctxt.get_config();
2239
2240 do_indent(o, indent);
2241
2242 o << "<abi-instr";
2243
2244 if (tu.get_address_size() != 0)
2245 o << " address-size='" << static_cast<int>(tu.get_address_size()) << "'";
2246
2247 std::string tu_path = tu.get_path();
2248 if (ctxt.get_short_locs())
2249 tools_utils::base_name(tu_path, tu_path);
2250 if (!tu_path.empty())
2251 o << " path='" << xml::escape_xml_string(tu_path) << "'";
2252
2253 if (!tu.get_compilation_dir_path().empty() && ctxt.get_write_comp_dir())
2254 o << " comp-dir-path='"
2255 << xml::escape_xml_string(tu.get_compilation_dir_path()) << "'";
2256
2257 if (tu.get_language() != translation_unit::LANG_UNKNOWN)
2258 o << " language='"
2259 << translation_unit_language_to_string(tu.get_language())
2260 <<"'";
2261
2262 if (tu.is_empty())
2263 {
2264 o << "/>\n";
2265 return true;
2266 }
2267
2268 o << ">\n";
2269
2270 write_canonical_types_of_scope(*tu.get_global_scope(),
2271 ctxt, indent + c.get_xml_element_indent());
2272
2273 typedef scope_decl::declarations declarations;
2274 typedef declarations::const_iterator const_iterator;
2275 const declarations& d = tu.get_global_scope()->get_sorted_member_decls();
2276
2277 for (const_iterator i = d.begin(); i != d.end(); ++i)
2278 {
2279 if (type_base_sptr t = is_type(*i))
2280 {
2281 // Emit non-empty classes that are declaration-only. Those
2282 // beasts are class that only contain member types.
2283 if (class_decl_sptr class_type = is_class_type(t))
2284 if (class_type->get_is_declaration_only()
2285 && !class_type->is_empty()
2286 && !ctxt.type_is_emitted(class_type))
2287 write_type(class_type, ctxt,
2288 indent + c.get_xml_element_indent());
2289 continue;
2290 }
2291
2292 if (decl_base_sptr d = is_decl(*i))
2293 if (ctxt.decl_is_emitted(d))
2294 continue;
2295 write_decl(*i, ctxt, indent + c.get_xml_element_indent());
2296 }
2297
2298 // Now let's handle types that were referenced, but not yet
2299 // emitted because they are either:
2300 // 1/ Types without canonical type
2301 // 2/ or function types (these might have no scope).
2302
2303 // So this map of type -> string is to contain the referenced types
2304 // we need to emit.
2305 type_ptr_set_type referenced_types_to_emit;
2306
2307 for (type_ptr_set_type::const_iterator i =
2308 ctxt.get_referenced_types().begin();
2309 i != ctxt.get_referenced_types().end();
2310 ++i)
2311 if (!ctxt.type_is_emitted(*i)
2312 && !ctxt.decl_only_type_is_emitted(*i))
2313 referenced_types_to_emit.insert(*i);
2314
2315 for (fn_type_ptr_set_type::const_iterator i =
2316 ctxt.get_referenced_function_types().begin();
2317 i != ctxt.get_referenced_function_types().end();
2318 ++i)
2319 if (!ctxt.type_is_emitted(*i)
2320 && !ctxt.decl_only_type_is_emitted(*i))
2321 // A referenced type that was not emitted at all must be
2322 // emitted now.
2323 referenced_types_to_emit.insert(*i);
2324
2325 for (type_ptr_set_type::const_iterator i =
2326 ctxt.get_referenced_non_canonical_types().begin();
2327 i != ctxt.get_referenced_non_canonical_types().end();
2328 ++i)
2329 if (!ctxt.type_is_emitted(*i)
2330 && !ctxt.decl_only_type_is_emitted(*i))
2331 // A referenced type that was not emitted at all must be
2332 // emitted now.
2333 referenced_types_to_emit.insert(*i);
2334
2335 // Ok, now let's emit the referenced type for good.
2336 while (!referenced_types_to_emit.empty())
2337 {
2338 // But first, we need to sort them, otherwise, emitting the ABI
2339 // (in xml) of the same binary twice will yield different
2340 // results, because we'd be walking an *unordered* hash table.
2341 vector<type_base*> sorted_referenced_types;
2342 ctxt.sort_types(referenced_types_to_emit,
2343 sorted_referenced_types);
2344
2345 // Clear the types recorded as referenced by the process of
2346 // emitting the types out. New types are going to be referenced
2347 // the process of emitting the types below.
2348 ctxt.clear_referenced_types();
2349
2350 // Now, emit the referenced decls in a sorted order.
2351 for (vector<type_base*>::const_iterator i =
2352 sorted_referenced_types.begin();
2353 i != sorted_referenced_types.end();
2354 ++i)
2355 {
2356 // We handle types which have declarations *and* function
2357 // types here.
2358 type_base_sptr t(*i, noop_deleter());
2359 if (!ctxt.type_is_emitted(t))
2360 {
2361 if (decl_base* d = get_type_declaration(*i))
2362 {
2363 decl_base_sptr decl(d, noop_deleter());
2364 write_decl_in_scope(decl, ctxt,
2365 indent + c.get_xml_element_indent());
2366 }
2367 else if (function_type_sptr fn_type = is_function_type(t))
2368 write_function_type(fn_type, ctxt,
2369 indent + c.get_xml_element_indent());
2370 else
2371 ABG_ASSERT_NOT_REACHED;
2372 }
2373 }
2374
2375 // So all the (referenced) types that we wanted to emit were
2376 // emitted.
2377 referenced_types_to_emit.clear();
2378
2379 // But then, while emitting those referenced type, other types
2380 // might have been referenced by those referenced types
2381 // themselves! So let's look at the sets of referenced type
2382 // that are maintained for the entire ABI corpus and see if
2383 // there are still some referenced types in there that are not
2384 // emitted yet. If yes, then we'll emit those again.
2385
2386 for (type_ptr_set_type::const_iterator i =
2387 ctxt.get_referenced_types().begin();
2388 i != ctxt.get_referenced_types().end();
2389 ++i)
2390 if (!ctxt.type_is_emitted(*i)
2391 && !ctxt.decl_only_type_is_emitted(*i))
2392 // A referenced type that was not emitted at all must be
2393 // emitted now.
2394 referenced_types_to_emit.insert(*i);
2395
2396 for (type_ptr_set_type::const_iterator i =
2397 ctxt.get_referenced_non_canonical_types().begin();
2398 i != ctxt.get_referenced_non_canonical_types().end();
2399 ++i)
2400 if (!ctxt.type_is_emitted(*i)
2401 && !ctxt.decl_only_type_is_emitted(*i))
2402 // A referenced type that was not emitted at all must be
2403 // emitted now.
2404 referenced_types_to_emit.insert(*i);
2405 }
2406
2407 // Now handle all function types that were not only referenced by
2408 // emitted types.
2409 const vector<function_type_sptr>& t = tu.get_live_fn_types();
2410 vector<type_base_sptr> sorted_types;
2411 ctxt.sort_types(t, sorted_types);
2412
2413 for (vector<type_base_sptr>::const_iterator i = sorted_types.begin();
2414 i != sorted_types.end();
2415 ++i)
2416 {
2417 function_type_sptr fn_type = is_function_type(*i);
2418
2419 if (!ctxt.type_is_referenced(fn_type) || ctxt.type_is_emitted(fn_type))
2420 // This function type is either not referenced by any emitted
2421 // pointer or reference type, or has already been emitted, so skip it.
2422 continue;
2423
2424 ABG_ASSERT(fn_type);
2425 write_function_type(fn_type, ctxt, indent + c.get_xml_element_indent());
2426 }
2427
2428 ctxt.clear_referenced_types();
2429
2430 do_indent(o, indent);
2431 o << "</abi-instr>\n";
2432
2433 return true;
2434 }
2435
2436 /// Serialize a pointer to an instance of basic type declaration, into
2437 /// an output stream.
2438 ///
2439 /// @param d the basic type declaration to serialize.
2440 ///
2441 /// @param ctxt the context of the serialization. It contains e.g, the
2442 /// output stream to serialize to.
2443 ///
2444 /// @param indent how many indentation spaces to use during the
2445 /// serialization.
2446 ///
2447 /// @return true upon successful completion, false otherwise.
2448 static bool
write_type_decl(const type_decl_sptr & d,write_context & ctxt,unsigned indent)2449 write_type_decl(const type_decl_sptr& d, write_context& ctxt, unsigned indent)
2450 {
2451 if (!d)
2452 return false;
2453
2454 ostream& o = ctxt.get_ostream();
2455
2456 annotate(d, ctxt, indent);
2457
2458 do_indent(o, indent);
2459
2460 o << "<type-decl name='" << xml::escape_xml_string(d->get_name()) << "'";
2461
2462 write_is_anonymous(d, o);
2463
2464 write_size_and_alignment(d, o);
2465
2466 write_is_declaration_only(d, o);
2467
2468 write_location(d, ctxt);
2469
2470 o << " id='" << ctxt.get_id_for_type(d) << "'" << "/>\n";
2471
2472 ctxt.record_type_as_emitted(d);
2473
2474 return true;
2475 }
2476
2477 /// Serialize a namespace declaration int an output stream.
2478 ///
2479 /// @param decl the namespace declaration to serialize.
2480 ///
2481 /// @param ctxt the context of the serialization. It contains e.g, the
2482 /// output stream to serialize to.
2483 ///
2484 /// @param indent how many indentation spaces to use during the
2485 /// serialization.
2486 ///
2487 /// @return true upon successful completion, false otherwise.
2488 static bool
write_namespace_decl(const namespace_decl_sptr & decl,write_context & ctxt,unsigned indent)2489 write_namespace_decl(const namespace_decl_sptr& decl,
2490 write_context& ctxt, unsigned indent)
2491 {
2492 if (!decl || decl->is_empty_or_has_empty_sub_namespaces())
2493 return false;
2494
2495 ostream& o = ctxt.get_ostream();
2496 const config &c = ctxt.get_config();
2497
2498 annotate(decl, ctxt, indent);
2499
2500 do_indent(o, indent);
2501
2502 o << "<namespace-decl name='"
2503 << xml::escape_xml_string(decl->get_name())
2504 << "'>\n";
2505
2506 typedef scope_decl::declarations declarations;
2507 typedef declarations::const_iterator const_iterator;
2508 const declarations& d = decl->get_member_decls();
2509
2510 write_canonical_types_of_scope(*decl, ctxt,
2511 indent + c.get_xml_element_indent());
2512
2513 for (const_iterator i = d.begin(); i != d.end(); ++i)
2514 {
2515 if (type_base_sptr t = is_type(*i))
2516 if (ctxt.type_is_emitted(t))
2517 // This type has already been emitted to the current
2518 // translation unit so do not emit it again.
2519 continue;
2520 write_decl(*i, ctxt, indent + c.get_xml_element_indent());
2521 }
2522
2523 do_indent(o, indent);
2524 o << "</namespace-decl>\n";
2525
2526 return true;
2527 }
2528
2529 /// Serialize a qualified type declaration to an output stream.
2530 ///
2531 /// @param decl the qualfied type declaration to write.
2532 ///
2533 /// @param id the type id identitifier to use in the serialized
2534 /// output. If this is empty, the function will compute an
2535 /// appropriate one. This is useful when this function is called to
2536 /// serialize the underlying type of a member type; in that case, the
2537 /// caller has already computed the id of the *member type*, and that
2538 /// id is the one to be written as the value of the 'id' attribute of
2539 /// the XML element of the underlying type.
2540 ///
2541 /// @param ctxt the write context.
2542 ///
2543 /// @param indent the number of space to indent to during the
2544 /// serialization.
2545 ///
2546 /// @return true upon successful completion, false otherwise.
2547 static bool
write_qualified_type_def(const qualified_type_def_sptr & decl,const string & id,write_context & ctxt,unsigned indent)2548 write_qualified_type_def(const qualified_type_def_sptr& decl,
2549 const string& id,
2550 write_context& ctxt,
2551 unsigned indent)
2552 {
2553 if (!decl)
2554 return false;
2555
2556 ostream& o = ctxt.get_ostream();
2557
2558
2559 type_base_sptr underlying_type = decl->get_underlying_type();
2560
2561 annotate(decl, ctxt, indent);
2562
2563 do_indent(o, indent);
2564 o << "<qualified-type-def type-id='"
2565 << ctxt.get_id_for_type(underlying_type)
2566 << "'";
2567
2568 ctxt.record_type_as_referenced(underlying_type);
2569
2570 if (decl->get_cv_quals() & qualified_type_def::CV_CONST)
2571 o << " const='yes'";
2572 if (decl->get_cv_quals() & qualified_type_def::CV_VOLATILE)
2573 o << " volatile='yes'";
2574 if (decl->get_cv_quals() & qualified_type_def::CV_RESTRICT)
2575 o << " restrict='yes'";
2576
2577 write_location(static_pointer_cast<decl_base>(decl), ctxt);
2578
2579 string i = id;
2580 if (i.empty())
2581 i = ctxt.get_id_for_type(decl);
2582
2583 o << " id='" << i << "'/>\n";
2584
2585 ctxt.record_type_as_emitted(decl);
2586
2587 return true;
2588 }
2589
2590 /// Serialize a qualified type declaration to an output stream.
2591 ///
2592 /// @param decl the qualfied type declaration to write.
2593 ///
2594 /// @param ctxt the write context.
2595 ///
2596 /// @param indent the number of space to indent to during the
2597 /// serialization.
2598 ///
2599 /// @return true upon successful completion, false otherwise.
2600 static bool
write_qualified_type_def(const qualified_type_def_sptr & decl,write_context & ctxt,unsigned indent)2601 write_qualified_type_def(const qualified_type_def_sptr& decl,
2602 write_context& ctxt,
2603 unsigned indent)
2604 {return write_qualified_type_def(decl, "", ctxt, indent);}
2605
2606 /// Serialize a pointer to an instance of pointer_type_def.
2607 ///
2608 /// @param decl the pointer_type_def to serialize.
2609 ///
2610 /// @param id the type id identitifier to use in the serialized
2611 /// output. If this is empty, the function will compute an
2612 /// appropriate one. This is useful when this function is called to
2613 /// serialize the underlying type of a member type; in that case, the
2614 /// caller has already computed the id of the *member type*, and that
2615 /// id is the one to be written as the value of the 'id' attribute of
2616 /// the XML element of the underlying type.
2617 ///
2618 /// @param ctxt the context of the serialization.
2619 ///
2620 /// @param indent the number of indentation white spaces to use.
2621 ///
2622 /// @return true upon succesful completion, false otherwise.
2623 static bool
write_pointer_type_def(const pointer_type_def_sptr & decl,const string & id,write_context & ctxt,unsigned indent)2624 write_pointer_type_def(const pointer_type_def_sptr& decl,
2625 const string& id,
2626 write_context& ctxt,
2627 unsigned indent)
2628 {
2629 if (!decl)
2630 return false;
2631
2632 ostream& o = ctxt.get_ostream();
2633
2634
2635 type_base_sptr pointed_to_type = decl->get_pointed_to_type();
2636
2637 annotate(decl->get_canonical_type(), ctxt, indent);
2638
2639 do_indent(o, indent);
2640 o << "<pointer-type-def type-id='"
2641 << ctxt.get_id_for_type(pointed_to_type)
2642 << "'";
2643
2644 ctxt.record_type_as_referenced(pointed_to_type);
2645
2646 write_size_and_alignment(decl, o,
2647 (ctxt.get_write_default_sizes()
2648 ? 0
2649 : decl->get_translation_unit()->get_address_size()),
2650 0);
2651
2652 string i = id;
2653 if (i.empty())
2654 i = ctxt.get_id_for_type(decl);
2655
2656 o << " id='" << i << "'";
2657
2658 write_location(static_pointer_cast<decl_base>(decl), ctxt);
2659 o << "/>\n";
2660
2661 ctxt.record_type_as_emitted(decl);
2662
2663 return true;
2664 }
2665
2666 /// Serialize a pointer to an instance of pointer_type_def.
2667 ///
2668 /// @param decl the pointer_type_def to serialize.
2669 ///
2670 /// @param ctxt the context of the serialization.
2671 ///
2672 /// @param indent the number of indentation white spaces to use.
2673 ///
2674 /// @return true upon succesful completion, false otherwise.
2675 static bool
write_pointer_type_def(const pointer_type_def_sptr & decl,write_context & ctxt,unsigned indent)2676 write_pointer_type_def(const pointer_type_def_sptr& decl,
2677 write_context& ctxt,
2678 unsigned indent)
2679 {return write_pointer_type_def(decl, "", ctxt, indent);}
2680
2681 /// Serialize a pointer to an instance of reference_type_def.
2682 ///
2683 /// @param decl the reference_type_def to serialize.
2684 ///
2685 /// @param id the type id identitifier to use in the serialized
2686 /// output. If this is empty, the function will compute an
2687 /// appropriate one. This is useful when this function is called to
2688 /// serialize the underlying type of a member type; in that case, the
2689 /// caller has already computed the id of the *member type*, and that
2690 /// id is the one to be written as the value of the 'id' attribute of
2691 /// the XML element of the underlying type.
2692 ///
2693 /// @param ctxt the context of the serialization.
2694 ///
2695 /// @param indent the number of indentation white spaces to use.
2696 ///
2697 /// @return true upon succesful completion, false otherwise.
2698 static bool
write_reference_type_def(const reference_type_def_sptr & decl,const string & id,write_context & ctxt,unsigned indent)2699 write_reference_type_def(const reference_type_def_sptr& decl,
2700 const string& id,
2701 write_context& ctxt,
2702 unsigned indent)
2703 {
2704 if (!decl)
2705 return false;
2706
2707 annotate(decl->get_canonical_type(), ctxt, indent);
2708
2709 ostream& o = ctxt.get_ostream();
2710
2711 do_indent(o, indent);
2712
2713 o << "<reference-type-def kind='";
2714 if (decl->is_lvalue())
2715 o << "lvalue";
2716 else
2717 o << "rvalue";
2718 o << "'";
2719
2720 type_base_sptr pointed_to_type = decl->get_pointed_to_type();
2721 o << " type-id='" << ctxt.get_id_for_type(pointed_to_type) << "'";
2722
2723 ctxt.record_type_as_referenced(pointed_to_type);
2724
2725 if (function_type_sptr f = is_function_type(decl->get_pointed_to_type()))
2726 ctxt.record_type_as_referenced(f);
2727
2728 write_size_and_alignment(decl, o,
2729 (ctxt.get_write_default_sizes()
2730 ? 0
2731 : decl->get_translation_unit()->get_address_size()),
2732 0);
2733
2734 string i = id;
2735 if (i.empty())
2736 i = ctxt.get_id_for_type(decl);
2737 o << " id='" << i << "'";
2738
2739 write_location(static_pointer_cast<decl_base>(decl), ctxt);
2740
2741 o << "/>\n";
2742
2743 ctxt.record_type_as_emitted(decl);
2744
2745 return true;
2746 }
2747
2748 /// Serialize a pointer to an instance of reference_type_def.
2749 ///
2750 /// @param decl the reference_type_def to serialize.
2751 ///
2752 /// @param ctxt the context of the serialization.
2753 ///
2754 /// @param indent the number of indentation white spaces to use.
2755 ///
2756 /// @return true upon succesful completion, false otherwise.
2757 static bool
write_reference_type_def(const reference_type_def_sptr & decl,write_context & ctxt,unsigned indent)2758 write_reference_type_def(const reference_type_def_sptr& decl,
2759 write_context& ctxt,
2760 unsigned indent)
2761 {return write_reference_type_def(decl, "", ctxt, indent);}
2762
2763 /// Serialize an instance of @ref array_type_def::subrange_type.
2764 ///
2765 /// @param decl the array_type_def::subrange_type to serialize.
2766 ///
2767 /// @param ctxt the context of the serialization.
2768 ///
2769 /// @param indent the number of indentation white spaces to use.
2770 ///
2771 /// return true upon successful completion, false otherwise.
2772 static bool
write_array_subrange_type(const array_type_def::subrange_sptr & decl,write_context & ctxt,unsigned indent)2773 write_array_subrange_type(const array_type_def::subrange_sptr& decl,
2774 write_context& ctxt,
2775 unsigned indent)
2776 {
2777 if (!decl)
2778 return false;
2779
2780 annotate(decl, ctxt, indent);
2781
2782 ostream& o = ctxt.get_ostream();
2783
2784 do_indent(o, indent);
2785
2786 o << "<subrange";
2787
2788 if (!decl->get_name().empty())
2789 o << " name='" << decl->get_name() << "'";
2790
2791 o << " length='";
2792 if (decl->is_infinite())
2793 o << "infinite";
2794 else
2795 o << decl->get_length();
2796
2797 o << "'";
2798
2799 if (decl->get_lower_bound())
2800 {
2801 ABG_ASSERT(decl->is_infinite()
2802 || (decl->get_length() ==
2803 (uint64_t) (decl->get_upper_bound()
2804 - decl->get_lower_bound() + 1)));
2805 o << " lower-bound='" << decl->get_lower_bound() << "' upper-bound='"
2806 << decl->get_upper_bound() << "'";
2807 }
2808
2809 type_base_sptr underlying_type = decl->get_underlying_type();
2810 if (underlying_type)
2811 {
2812 o << " type-id='"
2813 << ctxt.get_id_for_type(underlying_type)
2814 << "'";
2815 ctxt.record_type_as_referenced(underlying_type);
2816 }
2817
2818 o << " id='" << ctxt.get_id_for_type(decl) << "'";
2819
2820 write_location(decl->get_location(), ctxt);
2821
2822 o << "/>\n";
2823
2824 return true;
2825 }
2826
2827 /// Serialize a pointer to an instance of array_type_def.
2828 ///
2829 /// @param decl the array_type_def to serialize.
2830 ///
2831 /// @param id the type id identitifier to use in the serialized
2832 /// output. If this is empty, the function will compute an
2833 /// appropriate one. This is useful when this function is called to
2834 /// serialize the underlying type of a member type; in that case, the
2835 /// caller has already computed the id of the *member type*, and that
2836 /// id is the one to be written as the value of the 'id' attribute of
2837 /// the XML element of the underlying type.
2838 ///
2839 /// @param ctxt the context of the serialization.
2840 ///
2841 /// @param indent the number of indentation white spaces to use.
2842 ///
2843 /// @return true upon succesful completion, false otherwise.
2844 static bool
write_array_type_def(const array_type_def_sptr & decl,const string & id,write_context & ctxt,unsigned indent)2845 write_array_type_def(const array_type_def_sptr& decl,
2846 const string& id,
2847 write_context& ctxt,
2848 unsigned indent)
2849 {
2850 if (!decl)
2851 return false;
2852
2853 annotate(decl, ctxt, indent);
2854
2855 ostream& o = ctxt.get_ostream();
2856
2857 do_indent(o, indent);
2858 o << "<array-type-def";
2859
2860 o << " dimensions='" << decl->get_dimension_count() << "'";
2861
2862 type_base_sptr element_type = decl->get_element_type();
2863 o << " type-id='" << ctxt.get_id_for_type(element_type) << "'";
2864
2865 ctxt.record_type_as_referenced(element_type);
2866
2867 write_array_size_and_alignment(decl, o);
2868
2869 string i = id;
2870 if (i.empty())
2871 i = ctxt.get_id_for_type(decl);
2872 o << " id='" << i << "'";
2873
2874 write_location(static_pointer_cast<decl_base>(decl), ctxt);
2875
2876 if (!decl->get_dimension_count())
2877 o << "/>\n";
2878 else
2879 {
2880 o << ">\n";
2881
2882 vector<array_type_def::subrange_sptr>::const_iterator si;
2883
2884 for (si = decl->get_subranges().begin();
2885 si != decl->get_subranges().end(); ++si)
2886 {
2887 unsigned local_indent =
2888 indent + ctxt.get_config().get_xml_element_indent();
2889 write_array_subrange_type(*si, ctxt, local_indent);
2890 }
2891
2892 do_indent(o, indent);
2893 o << "</array-type-def>\n";
2894 }
2895
2896 ctxt.record_type_as_emitted(decl);
2897
2898 return true;
2899 }
2900
2901 /// Serialize a pointer to an instance of array_type_def.
2902 ///
2903 /// @param decl the array_type_def to serialize.
2904 ///
2905 /// @param ctxt the context of the serialization.
2906 ///
2907 /// @param indent the number of indentation white spaces to use.
2908 ///
2909 /// @return true upon succesful completion, false otherwise.
2910 static bool
write_array_type_def(const array_type_def_sptr & decl,write_context & ctxt,unsigned indent)2911 write_array_type_def(const array_type_def_sptr& decl,
2912 write_context& ctxt,
2913 unsigned indent)
2914 {return write_array_type_def(decl, "", ctxt, indent);}
2915
2916 /// Serialize a pointer to an instance of enum_type_decl.
2917 ///
2918 /// @param decl the enum_type_decl to serialize.
2919 ///
2920 /// @param id the type id identitifier to use in the serialized
2921 /// output. If this is empty, the function will compute an
2922 /// appropriate one. This is useful when this function is called to
2923 /// serialize the underlying type of a member type; in that case, the
2924 /// caller has already computed the id of the *member type*, and that
2925 /// id is the one to be written as the value of the 'id' attribute of
2926 /// the XML element of the underlying type.
2927 ///
2928 /// @param ctxt the context of the serialization.
2929 ///
2930 /// @param indent the number of indentation white spaces to use.
2931 ///
2932 /// @return true upon succesful completion, false otherwise.
2933 static bool
write_enum_type_decl(const enum_type_decl_sptr & decl,const string & id,write_context & ctxt,unsigned indent)2934 write_enum_type_decl(const enum_type_decl_sptr& decl,
2935 const string& id,
2936 write_context& ctxt,
2937 unsigned indent)
2938 {
2939 if (!decl)
2940 return false;
2941
2942 annotate(decl->get_canonical_type(), ctxt, indent);
2943
2944 ostream& o = ctxt.get_ostream();
2945
2946 do_indent(o, indent);
2947 o << "<enum-decl name='" << xml::escape_xml_string(decl->get_name()) << "'";
2948
2949 write_is_anonymous(decl, o);
2950 write_is_artificial(decl, o);
2951 write_is_non_reachable(is_type(decl), o);
2952
2953 if (!decl->get_linkage_name().empty())
2954 o << " linkage-name='" << decl->get_linkage_name() << "'";
2955
2956 write_location(decl, ctxt);
2957 write_is_declaration_only(decl, o);
2958
2959 string i = id;
2960 if (i.empty())
2961 i = ctxt.get_id_for_type(decl);
2962 o << " id='" << i << "'>\n";
2963
2964 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
2965 o << "<underlying-type type-id='"
2966 << ctxt.get_id_for_type(decl->get_underlying_type())
2967 << "'/>\n";
2968
2969 for (enum_type_decl::enumerators::const_iterator i =
2970 decl->get_enumerators().begin();
2971 i != decl->get_enumerators().end();
2972 ++i)
2973 {
2974 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
2975 o << "<enumerator name='"
2976 << i->get_name()
2977 << "' value='"
2978 << i->get_value()
2979 << "'/>\n";
2980 }
2981
2982 do_indent(o, indent);
2983 o << "</enum-decl>\n";
2984
2985 ctxt.record_type_as_emitted(decl);
2986
2987 return true;
2988 }
2989
2990 /// Serialize a pointer to an instance of enum_type_decl.
2991 ///
2992 /// @param decl the enum_type_decl to serialize.
2993 ///
2994 /// @param ctxt the context of the serialization.
2995 ///
2996 /// @param indent the number of indentation white spaces to use.
2997 ///
2998 /// @return true upon succesful completion, false otherwise.
2999 static bool
write_enum_type_decl(const enum_type_decl_sptr & decl,write_context & ctxt,unsigned indent)3000 write_enum_type_decl(const enum_type_decl_sptr& decl,
3001 write_context& ctxt,
3002 unsigned indent)
3003 {return write_enum_type_decl(decl, "", ctxt, indent);}
3004
3005 /// Serialize an @ref elf_symbol to an XML element of name
3006 /// 'elf-symbol'.
3007 ///
3008 /// @param sym the elf symbol to serialize.
3009 ///
3010 /// @param ctxt the read context to use.
3011 ///
3012 /// @param indent the number of white spaces to use as indentation.
3013 ///
3014 /// @return true iff the function completed successfully.
3015 static bool
write_elf_symbol(const elf_symbol_sptr & sym,write_context & ctxt,unsigned indent)3016 write_elf_symbol(const elf_symbol_sptr& sym,
3017 write_context& ctxt,
3018 unsigned indent)
3019 {
3020 if (!sym)
3021 return false;
3022
3023 ostream &o = ctxt.get_ostream();
3024
3025 annotate(sym, ctxt, indent);
3026 do_indent(o, indent);
3027 o << "<elf-symbol name='" << sym->get_name() << "'";
3028 if (sym->is_variable() && sym->get_size())
3029 o << " size='" << sym->get_size() << "'";
3030
3031 if (!sym->get_version().is_empty())
3032 {
3033 o << " version='" << sym->get_version().str() << "'";
3034 o << " is-default-version='";
3035 if (sym->get_version().is_default())
3036 o << "yes";
3037 else
3038 o << "no";
3039 o << "'";
3040 }
3041
3042 write_elf_symbol_type(sym->get_type(), o);
3043
3044 write_elf_symbol_binding(sym->get_binding(), o);
3045
3046 write_elf_symbol_visibility(sym->get_visibility(), o);
3047
3048 write_elf_symbol_aliases(*sym, o);
3049
3050 o << " is-defined='";
3051 if (sym->is_defined())
3052 o << "yes";
3053 else
3054 o << "no";
3055 o << "'";
3056
3057 if (sym->is_common_symbol())
3058 o << " is-common='yes'";
3059
3060 if (sym->get_crc() != 0)
3061 o << " crc='"
3062 << std::hex << std::showbase << sym->get_crc() << "'"
3063 << std::dec << std::noshowbase;
3064
3065 o << "/>\n";
3066
3067 return true;
3068 }
3069
3070 /// Write the elf symbol database to the output associated to the
3071 /// current context.
3072 ///
3073 /// @param syms the sorted elf symbol data to write out.
3074 ///
3075 /// @param ctxt the context to consider.
3076 ///
3077 /// @param indent the number of white spaces to use as indentation.
3078 ///
3079 /// @return true upon successful completion.
3080 static bool
write_elf_symbols_table(const elf_symbols & syms,write_context & ctxt,unsigned indent)3081 write_elf_symbols_table(const elf_symbols& syms,
3082 write_context& ctxt,
3083 unsigned indent)
3084 {
3085 if (syms.empty())
3086 return false;
3087
3088 unordered_map<string, bool> emitted_syms;
3089 for (elf_symbols::const_iterator it = syms.begin(); it != syms.end(); ++it)
3090 write_elf_symbol(*it, ctxt, indent);
3091
3092 return true;
3093 }
3094
3095 /// Write a vector of dependency names for the current corpus we are
3096 /// writting.
3097 ///
3098 /// @param needed the vector of dependency names to write.
3099 ///
3100 /// @param ctxt the write context to use for the writting.
3101 ///
3102 /// @param indent the number of indendation spaces to use.
3103 ///
3104 /// @return true upon successful completion, false otherwise.
3105 static bool
write_elf_needed(const vector<string> & needed,write_context & ctxt,unsigned indent)3106 write_elf_needed(const vector<string>& needed,
3107 write_context& ctxt,
3108 unsigned indent)
3109 {
3110 if (needed.empty())
3111 return false;
3112
3113 ostream& o = ctxt.get_ostream();
3114
3115 for (vector<string>::const_iterator i = needed.begin();
3116 i != needed.end();
3117 ++i)
3118 {
3119 do_indent(o, indent);
3120 o << "<dependency name='" << *i << "'/>\n";
3121 }
3122 return true;
3123 }
3124
3125 /// Serialize a pointer to an instance of typedef_decl.
3126 ///
3127 /// @param decl the typedef_decl to serialize.
3128 ///
3129 /// @param id the type id identitifier to use in the serialized
3130 /// output. If this is empty, the function will compute an
3131 /// appropriate one. This is useful when this function is called to
3132 /// serialize the underlying type of a member type; in that case, the
3133 /// caller has already computed the id of the *member type*, and that
3134 /// id is the one to be written as the value of the 'id' attribute of
3135 /// the XML element of the underlying type.
3136 ///
3137 /// @param ctxt the context of the serialization.
3138 ///
3139 /// @param indent the number of indentation white spaces to use.
3140 ///
3141 /// @return true upon succesful completion, false otherwise.
3142 static bool
write_typedef_decl(const typedef_decl_sptr & decl,const string & id,write_context & ctxt,unsigned indent)3143 write_typedef_decl(const typedef_decl_sptr& decl,
3144 const string& id,
3145 write_context& ctxt,
3146 unsigned indent)
3147 {
3148 if (!decl)
3149 return false;
3150
3151 ostream &o = ctxt.get_ostream();
3152
3153 annotate(decl, ctxt, indent);
3154
3155 do_indent(o, indent);
3156
3157 o << "<typedef-decl name='"
3158 << xml::escape_xml_string(decl->get_name())
3159 << "'";
3160
3161 type_base_sptr underlying_type = decl->get_underlying_type();
3162 string type_id = ctxt.get_id_for_type(underlying_type);
3163 o << " type-id='" << type_id << "'";
3164 ctxt.record_type_as_referenced(underlying_type);
3165
3166 write_location(decl, ctxt);
3167
3168 string i = id;
3169 if (i.empty())
3170 i = ctxt.get_id_for_type(decl);
3171
3172 o << " id='" << i << "'/>\n";
3173
3174 ctxt.record_type_as_emitted(decl);
3175
3176 return true;
3177 }
3178
3179 /// Serialize a pointer to an instance of typedef_decl.
3180 ///
3181 /// @param decl the typedef_decl to serialize.
3182 ///
3183 /// @param ctxt the context of the serialization.
3184 ///
3185 /// @param indent the number of indentation white spaces to use.
3186 ///
3187 /// @return true upon succesful completion, false otherwise.
3188 static bool
write_typedef_decl(const typedef_decl_sptr & decl,write_context & ctxt,unsigned indent)3189 write_typedef_decl(const typedef_decl_sptr& decl,
3190 write_context& ctxt,
3191 unsigned indent)
3192 {return write_typedef_decl(decl, "", ctxt, indent);}
3193
3194 /// Serialize a pointer to an instances of var_decl.
3195 ///
3196 /// @param decl the var_decl to serialize.
3197 ///
3198 /// @param ctxt the context of the serialization.
3199 ///
3200 /// @param write_linkage_name if true, serialize the mangled name of
3201 /// this variable.
3202 ///
3203 /// @param indent the number of indentation white spaces to use.
3204 ///
3205 /// @return true upon succesful completion, false otherwise.
3206 static bool
write_var_decl(const var_decl_sptr & decl,write_context & ctxt,bool write_linkage_name,unsigned indent)3207 write_var_decl(const var_decl_sptr& decl, write_context& ctxt,
3208 bool write_linkage_name, unsigned indent)
3209 {
3210 if (!decl)
3211 return false;
3212
3213 annotate(decl, ctxt, indent);
3214
3215 ostream &o = ctxt.get_ostream();
3216
3217 do_indent(o, indent);
3218
3219 o << "<var-decl name='" << xml::escape_xml_string(decl->get_name()) << "'";
3220 type_base_sptr var_type = decl->get_type();
3221 o << " type-id='" << ctxt.get_id_for_type(var_type) << "'";
3222 ctxt.record_type_as_referenced(var_type);
3223
3224 if (write_linkage_name)
3225 {
3226 const string& linkage_name = decl->get_linkage_name();
3227 if (!linkage_name.empty())
3228 o << " mangled-name='" << linkage_name << "'";
3229 }
3230
3231 write_visibility(decl, o);
3232
3233 write_binding(decl, o);
3234
3235 write_location(decl, ctxt);
3236
3237 write_elf_symbol_reference(decl->get_symbol(), o);
3238
3239 o << "/>\n";
3240
3241 ctxt.record_decl_as_emitted(decl);
3242
3243 return true;
3244 }
3245
3246 /// Serialize a pointer to a function_decl.
3247 ///
3248 /// @param decl the pointer to function_decl to serialize.
3249 ///
3250 /// @param ctxt the context of the serialization.
3251 ///
3252 /// @param skip_first_parm if true, do not serialize the first
3253 /// parameter of the function decl.
3254 ///
3255 /// @param indent the number of indentation white spaces to use.
3256 ///
3257 /// @return true upon succesful completion, false otherwise.
3258 static bool
write_function_decl(const function_decl_sptr & decl,write_context & ctxt,bool skip_first_parm,unsigned indent)3259 write_function_decl(const function_decl_sptr& decl, write_context& ctxt,
3260 bool skip_first_parm, unsigned indent)
3261 {
3262 if (!decl)
3263 return false;
3264
3265 annotate(decl, ctxt, indent);
3266
3267 ostream &o = ctxt.get_ostream();
3268
3269 do_indent(o, indent);
3270
3271 o << "<function-decl name='"
3272 << xml::escape_xml_string(decl->get_name())
3273 << "'";
3274
3275 if (!decl->get_linkage_name().empty())
3276 o << " mangled-name='"
3277 << xml::escape_xml_string(decl->get_linkage_name()) << "'";
3278
3279 write_location(decl, ctxt);
3280
3281 if (decl->is_declared_inline())
3282 o << " declared-inline='yes'";
3283
3284 write_visibility(decl, o);
3285
3286 write_binding(decl, o);
3287
3288 write_size_and_alignment(decl->get_type(), o,
3289 (ctxt.get_write_default_sizes()
3290 ? 0
3291 : decl->get_translation_unit()->get_address_size()),
3292 0);
3293 write_elf_symbol_reference(decl->get_symbol(), o);
3294
3295 o << ">\n";
3296
3297 type_base_sptr parm_type;
3298 vector<shared_ptr<function_decl::parameter> >::const_iterator pi =
3299 decl->get_parameters().begin();
3300 for ((skip_first_parm && pi != decl->get_parameters().end()) ? ++pi: pi;
3301 pi != decl->get_parameters().end();
3302 ++pi)
3303 {
3304 if ((*pi)->get_variadic_marker())
3305 {
3306 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
3307 o << "<parameter is-variadic='yes'";
3308 }
3309 else
3310 {
3311 parm_type = (*pi)->get_type();
3312
3313 annotate(*pi, ctxt,
3314 indent + ctxt.get_config().get_xml_element_indent());
3315
3316 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
3317
3318 o << "<parameter type-id='"
3319 << ctxt.get_id_for_type(parm_type)
3320 << "'";
3321 ctxt.record_type_as_referenced(parm_type);
3322
3323 if (ctxt.get_write_parameter_names() && !(*pi)->get_name().empty())
3324 o << " name='" << (*pi)->get_name() << "'";
3325 }
3326 write_is_artificial(*pi, o);
3327 write_location((*pi)->get_location(), ctxt);
3328 o << "/>\n";
3329 }
3330
3331 if (shared_ptr<type_base> return_type = decl->get_return_type())
3332 {
3333 annotate(return_type , ctxt,
3334 indent + ctxt.get_config().get_xml_element_indent());
3335 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
3336 o << "<return type-id='" << ctxt.get_id_for_type(return_type) << "'/>\n";
3337 ctxt.record_type_as_referenced(return_type);
3338 }
3339
3340 do_indent(o, indent);
3341 o << "</function-decl>\n";
3342
3343 ctxt.record_decl_as_emitted(decl);
3344
3345 return true;
3346 }
3347
3348 /// Serialize a function_type.
3349 ///
3350 /// @param decl the pointer to function_type to serialize.
3351 ///
3352 /// @param ctxt the context of the serialization.
3353 ///
3354 /// @param indent the number of indentation white spaces to use.
3355 ///
3356 /// @return true upon succesful completion, false otherwise.
3357 static bool
write_function_type(const function_type_sptr & fn_type,write_context & ctxt,unsigned indent)3358 write_function_type(const function_type_sptr& fn_type,
3359 write_context& ctxt, unsigned indent)
3360 {
3361 if (!fn_type)
3362 return false;
3363
3364 ostream &o = ctxt.get_ostream();
3365
3366 annotate(fn_type, ctxt, indent);
3367
3368 do_indent(o, indent);
3369
3370 o << "<function-type";
3371
3372 write_size_and_alignment(fn_type, o,
3373 (ctxt.get_write_default_sizes()
3374 ? 0
3375 : fn_type->get_translation_unit()->get_address_size()),
3376 0);
3377
3378 if (method_type_sptr method_type = is_method_type(fn_type))
3379 {
3380 o << " method-class-id='"
3381 << ctxt.get_id_for_type(method_type->get_class_type())
3382 << "'";
3383
3384 write_cdtor_const_static(/*is_ctor=*/false, /*is_dtor=*/false,
3385 /*is_const=*/method_type->get_is_const(),
3386 /*is_static=*/false, o);
3387 }
3388
3389 interned_string id = ctxt.get_id_for_type(fn_type);
3390
3391 o << " id='"
3392 << id << "'"
3393 << ">\n";
3394
3395 type_base_sptr parm_type;
3396 for (vector<function_decl::parameter_sptr>::const_iterator pi =
3397 fn_type->get_parameters().begin();
3398 pi != fn_type->get_parameters().end();
3399 ++pi)
3400 {
3401
3402 if ((*pi)->get_variadic_marker())
3403 {
3404 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
3405 o << "<parameter is-variadic='yes'";
3406 }
3407 else
3408 {
3409 parm_type = (*pi)->get_type();
3410
3411 annotate(*pi, ctxt, indent + ctxt.get_config().get_xml_element_indent());
3412
3413 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
3414 o << "<parameter type-id='"
3415 << ctxt.get_id_for_type(parm_type)
3416 << "'";
3417 ctxt.record_type_as_referenced(parm_type);
3418
3419 if (!(*pi)->get_name().empty())
3420 {
3421 string name = xml::escape_xml_string((*pi)->get_name());
3422 o << " name='" << name << "'";
3423 }
3424 }
3425 write_is_artificial(*pi, o);
3426 o << "/>\n";
3427 }
3428
3429 if (type_base_sptr return_type = fn_type->get_return_type())
3430 {
3431 annotate(return_type, ctxt, indent + ctxt.get_config().get_xml_element_indent());
3432 do_indent(o, indent + ctxt.get_config().get_xml_element_indent());
3433 o << "<return type-id='" << ctxt.get_id_for_type(return_type) << "'/>\n";
3434 ctxt.record_type_as_referenced(return_type);
3435 }
3436
3437 do_indent(o, indent);
3438 o << "</function-type>\n";
3439
3440 ctxt.record_type_as_emitted(fn_type);
3441 return true;
3442 }
3443
3444 /// Write the opening tag of a 'class-decl' element.
3445 ///
3446 /// @param decl the class declaration to serialize.
3447 ///
3448 /// @param the type ID to use for the 'class-decl' element,, or empty
3449 /// if we need to build a new one.
3450 ///
3451 /// @param ctxt the write context to use.
3452 ///
3453 /// @param indent the number of white space to use for indentation.
3454 ///
3455 /// @param prepare_to_handle_members if set to true, then this function
3456 /// figures out if the opening tag should be for an empty element or
3457 /// not. If set to false, then the opening tag is unconditionnaly for
3458 /// a non-empty element.
3459 ///
3460 /// @return true upon successful completion.
3461 static bool
write_class_decl_opening_tag(const class_decl_sptr & decl,const string & id,write_context & ctxt,unsigned indent,bool prepare_to_handle_members)3462 write_class_decl_opening_tag(const class_decl_sptr& decl,
3463 const string& id,
3464 write_context& ctxt,
3465 unsigned indent,
3466 bool prepare_to_handle_members)
3467 {
3468 if (!decl)
3469 return false;
3470
3471 ostream& o = ctxt.get_ostream();
3472
3473 do_indent_to_level(ctxt, indent, 0);
3474
3475 o << "<class-decl name='" << xml::escape_xml_string(decl->get_name()) << "'";
3476
3477 write_size_and_alignment(decl, o);
3478
3479 write_is_struct(decl, o);
3480
3481 write_is_anonymous(decl, o);
3482
3483 write_is_artificial(decl, o);
3484
3485 write_is_non_reachable(is_type(decl), o);
3486
3487 write_naming_typedef(decl, ctxt);
3488
3489 write_visibility(decl, o);
3490
3491 write_location(decl, ctxt);
3492
3493 write_is_declaration_only(decl, o);
3494
3495 if (decl->get_earlier_declaration())
3496 {
3497 // This instance is the definition of an earlier declaration.
3498 o << " def-of-decl-id='"
3499 << ctxt.get_id_for_type(is_type(decl->get_earlier_declaration()))
3500 << "'";
3501 }
3502
3503 string i = id;
3504 if (i.empty())
3505 i = ctxt.get_id_for_type(decl);
3506 o << " id='" << i << "'";
3507
3508 if (prepare_to_handle_members && decl->has_no_base_nor_member())
3509 o << "/>\n";
3510 else
3511 o << ">\n";
3512
3513 return true;
3514 }
3515
3516 /// Write the opening tag of a 'union-decl' element.
3517 ///
3518 /// @param decl the union declaration to serialize.
3519 ///
3520 /// @param the type ID to use for the 'union-decl' element, or empty
3521 /// if we need to build a new one.
3522 ///
3523 /// @param ctxt the write context to use.
3524 ///
3525 /// @param indent the number of white space to use for indentation.
3526 ///
3527 /// @param prepare_to_handle_members if set to true, then this function
3528 /// figures out if the opening tag should be for an empty element or
3529 /// not. If set to false, then the opening tag is unconditionnaly for
3530 /// a non-empty element.
3531 ///
3532 /// @return true upon successful completion.
3533 static bool
write_union_decl_opening_tag(const union_decl_sptr & decl,const string & id,write_context & ctxt,unsigned indent,bool prepare_to_handle_members)3534 write_union_decl_opening_tag(const union_decl_sptr& decl,
3535 const string& id,
3536 write_context& ctxt,
3537 unsigned indent,
3538 bool prepare_to_handle_members)
3539 {
3540 if (!decl)
3541 return false;
3542
3543 ostream& o = ctxt.get_ostream();
3544
3545 do_indent_to_level(ctxt, indent, 0);
3546
3547 o << "<union-decl name='" << xml::escape_xml_string(decl->get_name()) << "'";
3548
3549 if (!decl->get_is_declaration_only())
3550 write_size_and_alignment(decl, o);
3551
3552 write_is_anonymous(decl, o);
3553
3554 write_visibility(decl, o);
3555
3556 write_is_artificial(decl, o);
3557
3558 write_is_non_reachable(is_type(decl), o);
3559
3560 write_location(decl, ctxt);
3561
3562 write_is_declaration_only(decl, o);
3563
3564 string i = id;
3565 if (i.empty())
3566 i = ctxt.get_id_for_type(decl);
3567 o << " id='" << i << "'";
3568
3569 if (prepare_to_handle_members && decl->has_no_member())
3570 o << "/>\n";
3571 else
3572 o << ">\n";
3573
3574 return true;
3575 }
3576
3577 /// Serialize a class_decl type.
3578 ///
3579 /// @param d the pointer to class_decl to serialize.
3580 ///
3581 /// @param id the type id identitifier to use in the serialized
3582 /// output. If this is empty, the function will compute an
3583 /// appropriate one. This is useful when this function is called to
3584 /// serialize the underlying type of a member type; in that case, the
3585 /// caller has already computed the id of the *member type*, and that
3586 /// id is the one to be written as the value of the 'id' attribute of
3587 /// the XML element of the underlying type.
3588 ///
3589 /// @param ctxt the context of the serialization.
3590 ///
3591 /// @param indent the initial indentation to use.
3592 static bool
write_class_decl(const class_decl_sptr & d,const string & id,write_context & ctxt,unsigned indent)3593 write_class_decl(const class_decl_sptr& d,
3594 const string& id,
3595 write_context& ctxt,
3596 unsigned indent)
3597 {
3598 if (!d)
3599 return false;
3600
3601 class_decl_sptr decl = is_class_type(look_through_decl_only_class(d));
3602
3603 annotate(decl, ctxt, indent);
3604
3605 ostream& o = ctxt.get_ostream();
3606
3607 write_class_decl_opening_tag(decl, id, ctxt, indent,
3608 /*prepare_to_handle_members=*/true);
3609
3610 if (!decl->has_no_base_nor_member())
3611 {
3612 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1);
3613 type_base_sptr base_type;
3614 for (class_decl::base_specs::const_iterator base =
3615 decl->get_base_specifiers().begin();
3616 base != decl->get_base_specifiers().end();
3617 ++base)
3618 {
3619 annotate((*base)->get_base_class(), ctxt, nb_ws);
3620 do_indent(o, nb_ws);
3621 o << "<base-class";
3622
3623 write_access((*base)->get_access_specifier(), o);
3624
3625 write_layout_offset (*base, o);
3626
3627 if ((*base)->get_is_virtual ())
3628 o << " is-virtual='yes'";
3629
3630 base_type = (*base)->get_base_class();
3631 o << " type-id='"
3632 << ctxt.get_id_for_type(base_type)
3633 << "'/>\n";
3634
3635 ctxt.record_type_as_referenced(base_type);
3636 }
3637
3638 write_canonical_types_of_scope(*decl, ctxt, nb_ws,
3639 /*is_member_type=*/true);
3640
3641 for (class_decl::member_types::const_iterator ti =
3642 decl->get_member_types().begin();
3643 ti != decl->get_member_types().end();
3644 ++ti)
3645 if (!(*ti)->get_naked_canonical_type())
3646 write_member_type(*ti, ctxt, nb_ws);
3647
3648 for (class_decl::data_members::const_iterator data =
3649 decl->get_data_members().begin();
3650 data != decl->get_data_members().end();
3651 ++data)
3652 {
3653 do_indent(o, nb_ws);
3654 o << "<data-member";
3655 write_access(get_member_access_specifier(*data), o);
3656
3657 bool is_static = get_member_is_static(*data);
3658 write_cdtor_const_static(/*is_ctor=*/false,
3659 /*is_dtor=*/false,
3660 /*is_const=*/false,
3661 /*is_static=*/is_static,
3662 o);
3663 write_layout_offset(*data, o);
3664 o << ">\n";
3665
3666 write_var_decl(*data, ctxt, is_static,
3667 get_indent_to_level(ctxt, indent, 2));
3668
3669 do_indent_to_level(ctxt, indent, 1);
3670 o << "</data-member>\n";
3671 }
3672
3673 for (class_decl::member_functions::const_iterator f =
3674 decl->get_member_functions().begin();
3675 f != decl->get_member_functions().end();
3676 ++f)
3677 {
3678 function_decl_sptr fn = *f;
3679 if (get_member_function_is_virtual(fn))
3680 // All virtual member functions are emitted together,
3681 // later.
3682 continue;
3683
3684 ABG_ASSERT(!get_member_function_is_virtual(fn));
3685
3686 do_indent(o, nb_ws);
3687 o << "<member-function";
3688 write_access(get_member_access_specifier(fn), o);
3689 write_cdtor_const_static( get_member_function_is_ctor(fn),
3690 get_member_function_is_dtor(fn),
3691 get_member_function_is_const(fn),
3692 get_member_is_static(fn),
3693 o);
3694 o << ">\n";
3695
3696 write_function_decl(fn, ctxt,
3697 /*skip_first_parameter=*/false,
3698 get_indent_to_level(ctxt, indent, 2));
3699
3700 do_indent_to_level(ctxt, indent, 1);
3701 o << "</member-function>\n";
3702 }
3703
3704 for (class_decl::member_functions::const_iterator f =
3705 decl->get_virtual_mem_fns().begin();
3706 f != decl->get_virtual_mem_fns().end();
3707 ++f)
3708 {
3709 function_decl_sptr fn = *f;
3710
3711 ABG_ASSERT(get_member_function_is_virtual(fn));
3712
3713 do_indent(o, nb_ws);
3714 o << "<member-function";
3715 write_access(get_member_access_specifier(fn), o);
3716 write_cdtor_const_static( get_member_function_is_ctor(fn),
3717 get_member_function_is_dtor(fn),
3718 get_member_function_is_const(fn),
3719 get_member_is_static(fn),
3720 o);
3721 write_voffset(fn, o);
3722 o << ">\n";
3723
3724 write_function_decl(fn, ctxt,
3725 /*skip_first_parameter=*/false,
3726 get_indent_to_level(ctxt, indent, 2));
3727
3728 do_indent_to_level(ctxt, indent, 1);
3729 o << "</member-function>\n";
3730 }
3731
3732 for (member_function_templates::const_iterator fn =
3733 decl->get_member_function_templates().begin();
3734 fn != decl->get_member_function_templates().end();
3735 ++fn)
3736 {
3737 do_indent(o, nb_ws);
3738 o << "<member-template";
3739 write_access((*fn)->get_access_specifier(), o);
3740 write_cdtor_const_static((*fn)->is_constructor(),
3741 /*is_dtor=*/false,
3742 (*fn)->is_const(),
3743 (*fn)->get_is_static(), o);
3744 o << ">\n";
3745 write_function_tdecl((*fn)->as_function_tdecl(), ctxt,
3746 get_indent_to_level(ctxt, indent, 2));
3747 do_indent(o, nb_ws);
3748 o << "</member-template>\n";
3749 }
3750
3751 for (member_class_templates::const_iterator cl =
3752 decl->get_member_class_templates().begin();
3753 cl != decl->get_member_class_templates().end();
3754 ++cl)
3755 {
3756 do_indent(o, nb_ws);
3757 o << "<member-template";
3758 write_access((*cl)->get_access_specifier(), o);
3759 write_cdtor_const_static(false, false, false,
3760 (*cl)->get_is_static(), o);
3761 o << ">\n";
3762 write_class_tdecl((*cl)->as_class_tdecl(), ctxt,
3763 get_indent_to_level(ctxt, indent, 2));
3764 do_indent(o, nb_ws);
3765 o << "</member-template>\n";
3766 }
3767
3768 do_indent_to_level(ctxt, indent, 0);
3769
3770 o << "</class-decl>\n";
3771 }
3772
3773 // We allow several *declarations* of the same class in the corpus,
3774 // but only one definition.
3775 if (!decl->get_is_declaration_only())
3776 ctxt.record_type_as_emitted(decl);
3777 else
3778 ctxt.record_decl_only_type_as_emitted(decl);
3779
3780 return true;
3781 }
3782
3783 /// Serialize a class_decl type.
3784 ///
3785 /// @param decl the pointer to class_decl to serialize.
3786 ///
3787 /// @param ctxt the context of the serialization.
3788 ///
3789 /// @param indent the initial indentation to use.
3790 ///
3791 /// @return true upon successful completion.
3792 static bool
write_class_decl(const class_decl_sptr & decl,write_context & ctxt,unsigned indent)3793 write_class_decl(const class_decl_sptr& decl,
3794 write_context& ctxt,
3795 unsigned indent)
3796 {return write_class_decl(decl, "", ctxt, indent);}
3797
3798 /// Serialize a @ref union_decl type.
3799 ///
3800 /// @param d the pointer to @ref union_decl to serialize.
3801 ///
3802 /// @param ctxt the context of the serialization.
3803 ///
3804 /// @param indent the initial indentation to use.
3805 ///
3806 /// @return true upon successful completion.
3807 static bool
write_union_decl(const union_decl_sptr & d,const string & id,write_context & ctxt,unsigned indent)3808 write_union_decl(const union_decl_sptr& d,
3809 const string& id,
3810 write_context& ctxt,
3811 unsigned indent)
3812 {
3813 if (!d)
3814 return false;
3815
3816 union_decl_sptr decl = is_union_type(look_through_decl_only_class(d));
3817
3818 annotate(decl, ctxt, indent);
3819
3820 ostream& o = ctxt.get_ostream();
3821
3822 write_union_decl_opening_tag(decl, id, ctxt, indent,
3823 /*prepare_to_handle_members=*/true);
3824 if (!decl->has_no_member())
3825 {
3826 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1);
3827 for (class_decl::member_types::const_iterator ti =
3828 decl->get_member_types().begin();
3829 ti != decl->get_member_types().end();
3830 ++ti)
3831 write_member_type(*ti, ctxt, nb_ws);
3832
3833 for (union_decl::data_members::const_iterator data =
3834 decl->get_data_members().begin();
3835 data != decl->get_data_members().end();
3836 ++data)
3837 {
3838 do_indent(o, nb_ws);
3839 o << "<data-member";
3840 write_access(get_member_access_specifier(*data), o);
3841
3842 bool is_static = get_member_is_static(*data);
3843 write_cdtor_const_static(/*is_ctor=*/false,
3844 /*is_dtor=*/false,
3845 /*is_const=*/false,
3846 /*is_static=*/is_static,
3847 o);
3848 o << ">\n";
3849
3850 write_var_decl(*data, ctxt, is_static,
3851 get_indent_to_level(ctxt, indent, 2));
3852
3853 do_indent_to_level(ctxt, indent, 1);
3854 o << "</data-member>\n";
3855 }
3856
3857 for (union_decl::member_functions::const_iterator f =
3858 decl->get_member_functions().begin();
3859 f != decl->get_member_functions().end();
3860 ++f)
3861 {
3862 function_decl_sptr fn = *f;
3863 if (get_member_function_is_virtual(fn))
3864 // All virtual member functions are emitted together,
3865 // later.
3866 continue;
3867
3868 ABG_ASSERT(!get_member_function_is_virtual(fn));
3869
3870 do_indent(o, nb_ws);
3871 o << "<member-function";
3872 write_access(get_member_access_specifier(fn), o);
3873 write_cdtor_const_static( get_member_function_is_ctor(fn),
3874 get_member_function_is_dtor(fn),
3875 get_member_function_is_const(fn),
3876 get_member_is_static(fn),
3877 o);
3878 o << ">\n";
3879
3880 write_function_decl(fn, ctxt,
3881 /*skip_first_parameter=*/false,
3882 get_indent_to_level(ctxt, indent, 2));
3883
3884 do_indent_to_level(ctxt, indent, 1);
3885 o << "</member-function>\n";
3886 }
3887
3888 for (member_function_templates::const_iterator fn =
3889 decl->get_member_function_templates().begin();
3890 fn != decl->get_member_function_templates().end();
3891 ++fn)
3892 {
3893 do_indent(o, nb_ws);
3894 o << "<member-template";
3895 write_access((*fn)->get_access_specifier(), o);
3896 write_cdtor_const_static((*fn)->is_constructor(),
3897 /*is_dtor=*/false,
3898 (*fn)->is_const(),
3899 (*fn)->get_is_static(), o);
3900 o << ">\n";
3901 write_function_tdecl((*fn)->as_function_tdecl(), ctxt,
3902 get_indent_to_level(ctxt, indent, 2));
3903 do_indent(o, nb_ws);
3904 o << "</member-template>\n";
3905 }
3906
3907 for (member_class_templates::const_iterator cl =
3908 decl->get_member_class_templates().begin();
3909 cl != decl->get_member_class_templates().end();
3910 ++cl)
3911 {
3912 do_indent(o, nb_ws);
3913 o << "<member-template";
3914 write_access((*cl)->get_access_specifier(), o);
3915 write_cdtor_const_static(false, false, false,
3916 (*cl)->get_is_static(), o);
3917 o << ">\n";
3918 write_class_tdecl((*cl)->as_class_tdecl(), ctxt,
3919 get_indent_to_level(ctxt, indent, 2));
3920 do_indent(o, nb_ws);
3921 o << "</member-template>\n";
3922 }
3923
3924 do_indent_to_level(ctxt, indent, 0);
3925
3926 o << "</union-decl>\n";
3927 }
3928
3929 // We allow several *declarations* of the same union in the corpus,
3930 // but only one definition.
3931 if (!decl->get_is_declaration_only())
3932 ctxt.record_type_as_emitted(decl);
3933 else
3934 ctxt.record_decl_only_type_as_emitted(decl);
3935
3936 return true;
3937 }
3938
3939 static bool
write_union_decl(const union_decl_sptr & decl,write_context & ctxt,unsigned indent)3940 write_union_decl(const union_decl_sptr& decl,
3941 write_context& ctxt,
3942 unsigned indent)
3943 {return write_union_decl(decl, "", ctxt, indent);}
3944
3945 /// Write the opening tag for a 'member-type' element.
3946 ///
3947 /// @param t the member type to consider.
3948 ///
3949 /// @param ctxt the write context to use.
3950 ///
3951 /// @param indent the number of white spaces to use for indentation.
3952 ///
3953 /// @return true upon successful completion.
3954 static bool
write_member_type_opening_tag(const type_base_sptr & t,write_context & ctxt,unsigned indent)3955 write_member_type_opening_tag(const type_base_sptr& t,
3956 write_context& ctxt,
3957 unsigned indent)
3958 {
3959 ostream& o = ctxt.get_ostream();
3960
3961 do_indent_to_level(ctxt, indent, 0);
3962
3963 decl_base_sptr decl = get_type_declaration(t);
3964 ABG_ASSERT(decl);
3965
3966 o << "<member-type";
3967 write_access(decl, o);
3968 o << ">\n";
3969
3970 return true;
3971 }
3972
3973 /// Serialize a member type.
3974 ///
3975 /// Note that the id written as the value of the 'id' attribute of the
3976 /// underlying type is actually the id of the member type, not the one
3977 /// for the underying type. That id takes in account, the access
3978 /// specifier and the qualified name of the member type.
3979 ///
3980 /// @param decl the declaration of the member type to serialize.
3981 ///
3982 /// @param ctxt the write context to use.
3983 ///
3984 /// @param indent the number of levels to use for indentation
3985 static bool
write_member_type(const type_base_sptr & t,write_context & ctxt,unsigned indent)3986 write_member_type(const type_base_sptr& t, write_context& ctxt, unsigned indent)
3987 {
3988 if (!t)
3989 return false;
3990
3991 ostream& o = ctxt.get_ostream();
3992
3993 write_member_type_opening_tag(t, ctxt, indent);
3994
3995 string id = ctxt.get_id_for_type(t);
3996
3997 unsigned nb_ws = get_indent_to_level(ctxt, indent, 1);
3998 ABG_ASSERT(write_qualified_type_def(dynamic_pointer_cast<qualified_type_def>(t),
3999 id, ctxt, nb_ws)
4000 || write_pointer_type_def(dynamic_pointer_cast<pointer_type_def>(t),
4001 id, ctxt, nb_ws)
4002 || write_reference_type_def(dynamic_pointer_cast<reference_type_def>(t),
4003 id, ctxt, nb_ws)
4004 || write_array_type_def(dynamic_pointer_cast<array_type_def>(t),
4005 id, ctxt, nb_ws)
4006 || write_enum_type_decl(dynamic_pointer_cast<enum_type_decl>(t),
4007 id, ctxt, nb_ws)
4008 || write_typedef_decl(dynamic_pointer_cast<typedef_decl>(t),
4009 id, ctxt, nb_ws)
4010 || write_union_decl(dynamic_pointer_cast<union_decl>(t),
4011 id, ctxt, nb_ws)
4012 || write_class_decl(dynamic_pointer_cast<class_decl>(t),
4013 id, ctxt, nb_ws));
4014
4015 do_indent_to_level(ctxt, indent, 0);
4016 o << "</member-type>\n";
4017
4018 return true;
4019 }
4020
4021 /// Serialize an instance of type_tparameter.
4022 ///
4023 /// @param decl the instance to serialize.
4024 ///
4025 /// @param ctxt the context of the serialization.
4026 ///
4027 /// @param indent the initial indentation to use.
4028 ///
4029 /// @return true upon successful completion, false otherwise.
4030 static bool
write_type_tparameter(const type_tparameter_sptr decl,write_context & ctxt,unsigned indent)4031 write_type_tparameter(const type_tparameter_sptr decl,
4032 write_context& ctxt,
4033 unsigned indent)
4034 {
4035 if (!decl)
4036 return false;
4037
4038 ostream &o = ctxt.get_ostream();
4039 do_indent_to_level(ctxt, indent, 0);
4040
4041 string id_attr_name;
4042 if (ctxt.type_has_existing_id(decl))
4043 id_attr_name = "type-id";
4044 else
4045 id_attr_name = "id";
4046
4047 o << "<template-type-parameter "
4048 << id_attr_name << "='" << ctxt.get_id_for_type(decl) << "'";
4049
4050 std::string name = xml::escape_xml_string(decl->get_name ());
4051 if (!name.empty())
4052 o << " name='" << name << "'";
4053
4054 write_location(decl, ctxt);
4055
4056 o << "/>\n";
4057
4058 ctxt.record_type_as_emitted(decl);
4059
4060 return true;
4061 }
4062
4063 /// Serialize an instance of non_type_tparameter.
4064 ///
4065 /// @param decl the instance to serialize.
4066 ///
4067 /// @param ctxt the context of the serialization.
4068 ///
4069 /// @param indent the intial indentation to use.
4070 ///
4071 /// @return true open successful completion, false otherwise.
4072 static bool
write_non_type_tparameter(const shared_ptr<non_type_tparameter> decl,write_context & ctxt,unsigned indent)4073 write_non_type_tparameter(
4074 const shared_ptr<non_type_tparameter> decl,
4075 write_context& ctxt, unsigned indent)
4076 {
4077 if (!decl)
4078 return false;
4079
4080 ostream &o = ctxt.get_ostream();
4081 do_indent_to_level(ctxt, indent, 0);
4082
4083 o << "<template-non-type-parameter type-id='"
4084 << ctxt.get_id_for_type(decl->get_type())
4085 << "'";
4086
4087 string name = xml::escape_xml_string(decl->get_name());
4088 if (!name.empty())
4089 o << " name='" << name << "'";
4090
4091 write_location(decl, ctxt);
4092
4093 o << "/>\n";
4094
4095 return true;
4096 }
4097
4098 /// Serialize an instance of template template parameter.
4099 ///
4100 /// @param decl the instance to serialize.
4101 ///
4102 /// @param ctxt the context of the serialization.
4103 ///
4104 /// @param indent the initial indentation to use.
4105 ///
4106 /// @return true upon successful completion, false otherwise.
4107
4108 static bool
write_template_tparameter(const template_tparameter_sptr decl,write_context & ctxt,unsigned indent)4109 write_template_tparameter (const template_tparameter_sptr decl,
4110 write_context& ctxt,
4111 unsigned indent)
4112 {
4113 if (!decl)
4114 return false;
4115
4116 ostream& o = ctxt.get_ostream();
4117 do_indent_to_level(ctxt, indent, 0);
4118
4119 string id_attr_name = "id";
4120 if (ctxt.type_has_existing_id(decl))
4121 id_attr_name = "type-id";
4122
4123 o << "<template-template-parameter " << id_attr_name << "='"
4124 << ctxt.get_id_for_type(decl) << "'";
4125
4126 string name = xml::escape_xml_string(decl->get_name());
4127 if (!name.empty())
4128 o << " name='" << name << "'";
4129
4130 o << ">\n";
4131
4132 unsigned nb_spaces = get_indent_to_level(ctxt, indent, 1);
4133 for (list<shared_ptr<template_parameter> >::const_iterator p =
4134 decl->get_template_parameters().begin();
4135 p != decl->get_template_parameters().end();
4136 ++p)
4137 write_template_parameter(decl, ctxt, nb_spaces);
4138
4139 do_indent_to_level(ctxt, indent, 0);
4140 o << "</template-template-parameter>\n";
4141
4142 ctxt.record_type_as_emitted(decl);
4143
4144 return true;
4145 }
4146
4147 /// Serialize an instance of type_composition.
4148 ///
4149 /// @param decl the decl to serialize.
4150 ///
4151 /// @param ctxt the context of the serialization.
4152 ///
4153 /// @param indent the initial indentation to use.
4154 ///
4155 /// @return true upon successful completion, false otherwise.
4156 static bool
write_type_composition(const shared_ptr<type_composition> decl,write_context & ctxt,unsigned indent)4157 write_type_composition
4158 (const shared_ptr<type_composition> decl,
4159 write_context& ctxt, unsigned indent)
4160 {
4161 if (!decl)
4162 return false;
4163
4164 ostream& o = ctxt.get_ostream();
4165
4166 do_indent_to_level(ctxt, indent, 0);
4167
4168 o << "<template-parameter-type-composition>\n";
4169
4170 unsigned nb_spaces = get_indent_to_level(ctxt, indent, 1);
4171 (write_pointer_type_def
4172 (dynamic_pointer_cast<pointer_type_def>(decl->get_composed_type()),
4173 ctxt, nb_spaces)
4174 || write_reference_type_def
4175 (dynamic_pointer_cast<reference_type_def>(decl->get_composed_type()),
4176 ctxt, nb_spaces)
4177 || write_array_type_def
4178 (dynamic_pointer_cast<array_type_def>(decl->get_composed_type()),
4179 ctxt, nb_spaces)
4180 || write_qualified_type_def
4181 (dynamic_pointer_cast<qualified_type_def>(decl->get_composed_type()),
4182 ctxt, nb_spaces));
4183
4184 do_indent_to_level(ctxt, indent, 0);
4185 o << "</template-parameter-type-composition>\n";
4186
4187 return true;
4188 }
4189
4190 /// Serialize an instance of template_parameter.
4191 ///
4192 /// @param decl the instance to serialize.
4193 ///
4194 /// @param ctxt the context of the serialization.
4195 ///
4196 /// @param indent the initial indentation to use.
4197 ///
4198 /// @return true upon successful completion, false otherwise.
4199 static bool
write_template_parameter(const shared_ptr<template_parameter> decl,write_context & ctxt,unsigned indent)4200 write_template_parameter(const shared_ptr<template_parameter> decl,
4201 write_context& ctxt, unsigned indent)
4202 {
4203 if ((!write_type_tparameter
4204 (dynamic_pointer_cast<type_tparameter>(decl), ctxt, indent))
4205 && (!write_non_type_tparameter
4206 (dynamic_pointer_cast<non_type_tparameter>(decl),
4207 ctxt, indent))
4208 && (!write_template_tparameter
4209 (dynamic_pointer_cast<template_tparameter>(decl),
4210 ctxt, indent))
4211 && (!write_type_composition
4212 (dynamic_pointer_cast<type_composition>(decl),
4213 ctxt, indent)))
4214 return false;
4215
4216 return true;
4217 }
4218
4219 /// Serialize the template parameters of the a given template.
4220 ///
4221 /// @param tmpl the template for which to emit the template parameters.
4222 static void
write_template_parameters(const shared_ptr<template_decl> tmpl,write_context & ctxt,unsigned indent)4223 write_template_parameters(const shared_ptr<template_decl> tmpl,
4224 write_context& ctxt, unsigned indent)
4225 {
4226 if (!tmpl)
4227 return;
4228
4229 unsigned nb_spaces = get_indent_to_level(ctxt, indent, 1);
4230 for (list<shared_ptr<template_parameter> >::const_iterator p =
4231 tmpl->get_template_parameters().begin();
4232 p != tmpl->get_template_parameters().end();
4233 ++p)
4234 write_template_parameter(*p, ctxt, nb_spaces);
4235 }
4236
4237 /// Serialize an instance of function_tdecl.
4238 ///
4239 /// @param decl the instance to serialize.
4240 ///
4241 /// @param ctxt the context of the serialization
4242 ///
4243 /// @param indent the initial indentation.
4244 static bool
write_function_tdecl(const shared_ptr<function_tdecl> decl,write_context & ctxt,unsigned indent)4245 write_function_tdecl(const shared_ptr<function_tdecl> decl,
4246 write_context& ctxt, unsigned indent)
4247 {
4248 if (!decl)
4249 return false;
4250
4251 ostream& o = ctxt.get_ostream();
4252
4253 do_indent_to_level(ctxt, indent, 0);
4254
4255 o << "<function-template-decl id='" << ctxt.get_id_for_fn_tmpl(decl) << "'";
4256
4257 write_location(decl, ctxt);
4258
4259 write_visibility(decl, o);
4260
4261 write_binding(decl, o);
4262
4263 o << ">\n";
4264
4265 write_template_parameters(decl, ctxt, indent);
4266
4267 write_function_decl(decl->get_pattern(), ctxt,
4268 /*skip_first_parameter=*/false,
4269 get_indent_to_level(ctxt, indent, 1));
4270
4271 do_indent_to_level(ctxt, indent, 0);
4272
4273 o << "</function-template-decl>\n";
4274
4275 return true;
4276 }
4277
4278
4279 /// Serialize an instance of class_tdecl
4280 ///
4281 /// @param decl a pointer to the instance of class_tdecl to serialize.
4282 ///
4283 /// @param ctxt the context of the serializtion.
4284 ///
4285 /// @param indent the initial number of white space to use for
4286 /// indentation.
4287 ///
4288 /// @return true upon successful completion, false otherwise.
4289 static bool
write_class_tdecl(const shared_ptr<class_tdecl> decl,write_context & ctxt,unsigned indent)4290 write_class_tdecl(const shared_ptr<class_tdecl> decl,
4291 write_context& ctxt, unsigned indent)
4292 {
4293 if (!decl)
4294 return false;
4295
4296 ostream& o = ctxt.get_ostream();
4297
4298 do_indent_to_level(ctxt, indent, 0);
4299
4300 o << "<class-template-decl id='" << ctxt.get_id_for_class_tmpl(decl) << "'";
4301
4302 write_location(decl, ctxt);
4303
4304 write_visibility(decl, o);
4305
4306 o << ">\n";
4307
4308 write_template_parameters(decl, ctxt, indent);
4309
4310 write_class_decl(decl->get_pattern(), ctxt,
4311 get_indent_to_level(ctxt, indent, 1));
4312
4313 do_indent_to_level(ctxt, indent, 0);
4314
4315 o << "</class-template-decl>\n";
4316
4317 return true;
4318 }
4319
4320 /// Serialize the current version number of the ABIXML format.
4321 ///
4322 /// @param ctxt the writing context to use.
4323 static void
write_version_info(write_context & ctxt)4324 write_version_info(write_context& ctxt)
4325 {
4326 ostream& o = ctxt.get_ostream();
4327 const config& c = ctxt.get_config();
4328
4329 o << "version='"
4330 << c.get_format_major_version_number()
4331 << "." << c.get_format_minor_version_number()
4332 << "'";
4333 }
4334
4335 /// Serialize an ABI corpus to a single native xml document. The root
4336 /// note of the resulting XML document is 'abi-corpus'.
4337 ///
4338 /// Note: If either corpus is null or corpus does not contain serializable
4339 /// content (i.e. corpus.is_empty()), nothing is emitted to the ctxt's
4340 /// output stream.
4341 ///
4342 /// @param ctxt the write context to use.
4343 ///
4344 /// @param corpus the corpus to serialize.
4345 ///
4346 /// @param indent the number of white space indentation to use.
4347 ///
4348 /// @return true upon successful completion, false otherwise.
4349 bool
write_corpus(write_context & ctxt,const corpus_sptr & corpus,unsigned indent,bool member_of_group)4350 write_corpus(write_context& ctxt,
4351 const corpus_sptr& corpus,
4352 unsigned indent,
4353 bool member_of_group)
4354 {
4355 if (!corpus)
4356 return false;
4357
4358 if (corpus->is_empty())
4359 return true;
4360
4361 do_indent_to_level(ctxt, indent, 0);
4362
4363 std::ostream& out = ctxt.get_ostream();
4364
4365 out << "<abi-corpus ";
4366
4367 write_version_info(ctxt);
4368
4369 // For an abi-corpus as part of an abi-corpus group, only omit the path, but
4370 // keep the filename.
4371 std::string corpus_path = corpus->get_path();
4372 if (!ctxt.get_write_corpus_path())
4373 {
4374 if (member_of_group)
4375 tools_utils::base_name(corpus_path, corpus_path);
4376 else
4377 corpus_path.clear();
4378 }
4379 else
4380 {
4381 if (ctxt.get_short_locs())
4382 tools_utils::base_name(corpus_path, corpus_path);
4383 }
4384 if (!corpus_path.empty())
4385 out << " path='" << xml::escape_xml_string(corpus_path) << "'";
4386
4387 if (!corpus->get_architecture_name().empty()
4388 && ctxt.get_write_architecture())
4389 out << " architecture='" << corpus->get_architecture_name()<< "'";
4390
4391 if (!corpus->get_soname().empty())
4392 out << " soname='" << corpus->get_soname()<< "'";
4393
4394 write_tracking_non_reachable_types(corpus, out);
4395
4396 out << ">\n";
4397
4398 // Write the list of needed corpora.
4399
4400 if (ctxt.get_write_elf_needed () && !corpus->get_needed().empty())
4401 {
4402 do_indent_to_level(ctxt, indent, 1);
4403 out << "<elf-needed>\n";
4404 write_elf_needed(corpus->get_needed(), ctxt,
4405 get_indent_to_level(ctxt, indent, 2));
4406 do_indent_to_level(ctxt, indent, 1);
4407 out << "</elf-needed>\n";
4408 }
4409
4410 // Write the function symbols data base.
4411 if (!corpus->get_fun_symbol_map().empty())
4412 {
4413 do_indent_to_level(ctxt, indent, 1);
4414 out << "<elf-function-symbols>\n";
4415
4416 write_elf_symbols_table(corpus->get_sorted_fun_symbols(), ctxt,
4417 get_indent_to_level(ctxt, indent, 2));
4418
4419 do_indent_to_level(ctxt, indent, 1);
4420 out << "</elf-function-symbols>\n";
4421 }
4422
4423 // Write the variable symbols data base.
4424 if (!corpus->get_var_symbol_map().empty())
4425 {
4426 do_indent_to_level(ctxt, indent, 1);
4427 out << "<elf-variable-symbols>\n";
4428
4429 write_elf_symbols_table(corpus->get_sorted_var_symbols(), ctxt,
4430 get_indent_to_level(ctxt, indent, 2));
4431
4432 do_indent_to_level(ctxt, indent, 1);
4433 out << "</elf-variable-symbols>\n";
4434 }
4435
4436 // Now write the translation units.
4437 for (translation_units::const_iterator i =
4438 corpus->get_translation_units().begin();
4439 i != corpus->get_translation_units().end();
4440 ++i)
4441 {
4442 translation_unit& tu = **i;
4443 if (!tu.is_empty())
4444 write_translation_unit(ctxt, tu, get_indent_to_level(ctxt, indent, 1));
4445 }
4446
4447 do_indent_to_level(ctxt, indent, 0);
4448 out << "</abi-corpus>\n";
4449
4450 return true;
4451 }
4452
4453 /// Serialize an ABI corpus group to a single native xml document.
4454 /// The root note of the resulting XML document is 'abi-corpus-group'.
4455 ///
4456 /// @param ctxt the write context to use.
4457 ///
4458 /// @param group the corpus group to serialize.
4459 ///
4460 /// @param indent the number of white space indentation to use.
4461 ///
4462 /// @return true upon successful completion, false otherwise.
4463 bool
write_corpus_group(write_context & ctxt,const corpus_group_sptr & group,unsigned indent)4464 write_corpus_group(write_context& ctxt,
4465 const corpus_group_sptr& group,
4466 unsigned indent)
4467
4468 {
4469 if (!group)
4470 return false;
4471
4472 do_indent_to_level(ctxt, indent, 0);
4473
4474 std::ostream& out = ctxt.get_ostream();
4475
4476 out << "<abi-corpus-group ";
4477 write_version_info(ctxt);
4478
4479 if (!group->get_path().empty() && ctxt.get_write_corpus_path())
4480 out << " path='" << xml::escape_xml_string(group->get_path()) << "'";
4481
4482 if (!group->get_architecture_name().empty() && ctxt.get_write_architecture())
4483 out << " architecture='" << group->get_architecture_name()<< "'";
4484
4485 write_tracking_non_reachable_types(group, out);
4486
4487 if (group->is_empty())
4488 {
4489 out << "/>\n";
4490 return true;
4491 }
4492
4493 out << ">\n";
4494
4495 // Write the list of corpora
4496 for (corpus_group::corpora_type::const_iterator c =
4497 group->get_corpora().begin();
4498 c != group->get_corpora().end();
4499 ++c)
4500 write_corpus(ctxt, *c, get_indent_to_level(ctxt, indent, 1), true);
4501
4502 do_indent_to_level(ctxt, indent, 0);
4503 out << "</abi-corpus-group>\n";
4504
4505 return true;
4506 }
4507
4508 } //end namespace xml_writer
4509
4510 // <Debugging routines>
4511
4512 using namespace abigail::ir;
4513
4514 /// Serialize a pointer to decl_base to an output stream.
4515 ///
4516 /// @param d the pointer to decl_base to serialize.
4517 ///
4518 /// @param o the output stream to consider.
4519 ///
4520 /// @param annotate whether ABIXML output should be annotated.
4521 void
dump(const decl_base_sptr d,std::ostream & o,const bool annotate)4522 dump(const decl_base_sptr d, std::ostream& o, const bool annotate)
4523 {
4524 xml_writer::write_context ctxt(d->get_environment(), o);
4525 xml_writer::set_annotate(ctxt, annotate);
4526 write_decl(d, ctxt, /*indent=*/0);
4527 }
4528
4529 /// Serialize a pointer to decl_base to stderr.
4530 ///
4531 /// @param d the pointer to decl_base to serialize.
4532 ///
4533 /// @param annotate whether ABIXML output should be annotated.
4534 void
dump(const decl_base_sptr d,const bool annotate)4535 dump(const decl_base_sptr d, const bool annotate)
4536 {dump(d, cerr, annotate);}
4537
4538 /// Serialize a pointer to type_base to an output stream.
4539 ///
4540 /// @param t the pointer to type_base to serialize.
4541 ///
4542 /// @param o the output stream to serialize the @ref type_base to.
4543 ///
4544 /// @param annotate whether ABIXML output should be annotated.
4545 void
dump(const type_base_sptr t,std::ostream & o,const bool annotate)4546 dump(const type_base_sptr t, std::ostream& o, const bool annotate)
4547 {dump(get_type_declaration(t), o, annotate);}
4548
4549 /// Serialize a pointer to type_base to stderr.
4550 ///
4551 /// @param t the pointer to type_base to serialize.
4552 ///
4553 /// @param annotate whether ABIXML output should be annotated.
4554 void
dump(const type_base_sptr t,const bool annotate)4555 dump(const type_base_sptr t, const bool annotate)
4556 {dump(t, cerr, annotate);}
4557
4558 /// Serialize a pointer to var_decl to an output stream.
4559 ///
4560 /// @param v the pointer to var_decl to serialize.
4561 ///
4562 /// @param o the output stream to serialize the @ref var_decl to.
4563 ///
4564 /// @param annotate whether ABIXML output should be annotated.
4565 void
dump(const var_decl_sptr v,std::ostream & o,const bool annotate)4566 dump(const var_decl_sptr v, std::ostream& o, const bool annotate)
4567 {
4568 xml_writer::write_context ctxt(v->get_environment(), o);
4569 xml_writer::set_annotate(ctxt, annotate);
4570 write_var_decl(v, ctxt, /*linkage_name*/true, /*indent=*/0);
4571 }
4572
4573 /// Serialize a pointer to var_decl to stderr.
4574 ///
4575 /// @param v the pointer to var_decl to serialize.
4576 ///
4577 /// @param annotate whether ABIXML output should be annotated.
4578 void
dump(const var_decl_sptr v,const bool annotate)4579 dump(const var_decl_sptr v, const bool annotate)
4580 {dump(v, cerr, annotate);}
4581
4582 /// Serialize a @ref translation_unit to an output stream.
4583 ///
4584 /// @param t the translation_unit to serialize.
4585 ///
4586 /// @param o the outpout stream to serialize the translation_unit to.
4587 ///
4588 /// @param annotate whether ABIXML output should be annotated.
4589 void
dump(const translation_unit & t,std::ostream & o,const bool annotate)4590 dump(const translation_unit& t, std::ostream& o, const bool annotate)
4591 {
4592 xml_writer::write_context ctxt(t.get_environment(), o);
4593 xml_writer::set_annotate(ctxt, annotate);
4594 write_translation_unit(ctxt, t, /*indent=*/0);
4595 }
4596
4597 /// Serialize an instance of @ref translation_unit to stderr.
4598 ///
4599 /// @param t the translation_unit to serialize.
4600 void
dump(const translation_unit & t,const bool annotate)4601 dump(const translation_unit& t, const bool annotate)
4602 {dump(t, cerr, annotate);}
4603
4604 /// Serialize a pointer to @ref translation_unit to an output stream.
4605 ///
4606 /// @param t the @ref translation_unit_sptr to serialize.
4607 ///
4608 /// @param o the output stream to serialize the translation unit to.
4609 ///
4610 /// @param annotate whether ABIXML output should be annotated.
4611 void
dump(const translation_unit_sptr t,std::ostream & o,const bool annotate)4612 dump(const translation_unit_sptr t, std::ostream& o, const bool annotate)
4613 {
4614 if (t)
4615 dump(*t, o, annotate);
4616 }
4617
4618 /// Serialize a pointer to @ref translation_unit to stderr.
4619 ///
4620 /// @param t the translation_unit_sptr to serialize.
4621 ///
4622 /// @param annotate whether ABIXML output should be annotated.
4623 void
dump(const translation_unit_sptr t,const bool annotate)4624 dump(const translation_unit_sptr t, const bool annotate)
4625 {
4626 if (t)
4627 dump(*t, annotate);
4628 }
4629
4630 /// Serialize a source location to an output stream.
4631 ///
4632 /// @param l the declaration to consider.
4633 ///
4634 /// @param o the output stream to serialize to.
4635 void
dump_location(const location & l,ostream & o)4636 dump_location(const location& l, ostream& o)
4637 {
4638 string path;
4639 unsigned line = 0, col = 0;
4640
4641 l.expand(path, line, col);
4642 o << path << ":" << line << "," << col << "\n";
4643 }
4644
4645 /// Serialize a source location for debugging purposes.
4646 ///
4647 /// The location is serialized to the standard error output stream.
4648 ///
4649 /// @param l the declaration to consider.
4650 ///
4651 void
dump_location(const location & l)4652 dump_location(const location& l)
4653 {dump_location(l, cerr);}
4654
4655 /// Serialize the source location of a decl to an output stream for
4656 /// debugging purposes.
4657 ///
4658 /// @param d the declaration to consider.
4659 ///
4660 /// @param o the output stream to serizalize the location to.
4661 void
dump_decl_location(const decl_base & d,ostream & o)4662 dump_decl_location(const decl_base& d, ostream& o)
4663 {dump_location(d.get_location(), o);}
4664
4665 /// Serialize the source location of a decl to stderr for debugging
4666 /// purposes.
4667 ///
4668 /// @param d the declaration to consider.
4669 void
dump_decl_location(const decl_base & d)4670 dump_decl_location(const decl_base& d)
4671 {dump_decl_location(d, cerr);}
4672
4673 /// Serialize the source location of a dcl to stderr for debugging
4674 /// purposes.
4675 ///
4676 /// @param d the declaration to consider.
4677 void
dump_decl_location(const decl_base * d)4678 dump_decl_location(const decl_base* d)
4679 {
4680 if (d)
4681 dump_decl_location(*d);
4682 }
4683
4684 /// Serialize the source location of a decl to stderr for debugging
4685 /// purposes.
4686 ///
4687 /// @param d the declaration to consider.
4688 void
dump_decl_location(const decl_base_sptr d)4689 dump_decl_location(const decl_base_sptr d)
4690 {dump_decl_location(d.get());}
4691
4692 // </Debugging routines>
4693 } //end namespace abigail
4694