libabigail
abg-ir-priv.h
Go to the documentation of this file.
1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2016-2025 Red Hat, Inc.
5 //
6 // Author: Dodji Seketeli
7 
8 /// @file
9 ///
10 /// This contains the private implementation of the suppression engine
11 /// of libabigail.
12 
13 #ifndef __ABG_IR_PRIV_H__
14 #define __ABG_IR_PRIV_H__
15 
16 #include <algorithm>
17 #include <iostream>
18 #include <string>
19 
20 #include "abg-hash.h"
21 #include "abg-corpus.h"
22 #include "abg-tools-utils.h"
23 
24 namespace abigail
25 {
26 
27 namespace ir
28 {
29 
30 using std::string;
31 using std::unordered_set;
33 
34 /// The result of structural comparison of type ABI artifacts.
36 {
37  COMPARISON_RESULT_DIFFERENT = 0,
38  COMPARISON_RESULT_EQUAL = 1,
39  COMPARISON_RESULT_CYCLE_DETECTED = 2,
40  COMPARISON_RESULT_UNKNOWN = 3,
41 }; //end enum comparison_result
42 
43 /// The internal representation of an integral type.
44 ///
45 /// This is a "utility type" used internally to canonicalize the name
46 /// of fundamental integral types, so that "unsignd long" and "long
47 /// unsined int" end-up having the same name.
48 class real_type
49 {
50 public:
51  /// The possible base types of integral types. We might have
52  /// forgotten many of these, so do not hesitate to add new ones.
53  ///
54  /// If you do add new ones, please also consider updating functions
55  /// parse_base_real_type and real_type::to_string.
56  enum base_type
57  {
58  /// The "int" base type.
60  /// The "char" base type.
62  /// The "bool" base type in C++ or "_Bool" in C11.
64  /// The "double" base type.
66  /// The "float" base type.
68  /// The "char16_t base type.
70  /// The "char32_t" base type.
72  /// The "wchar_t" base type.
74  SIZE_BASE_TYPE,
75  SSIZE_BASE_TYPE,
76  BIT_SIZE_BASE_TYPE,
77  SBIT_SIZE_BASE_TYPE,
78  /// The aray size type used by Clang.
80  };
81 
82  /// The modifiers of the base types above. Several modifiers can be
83  /// combined for a given base type. The presence of modifiers is
84  /// usually modelled by a bitmap of modifiers.
85  ///
86  /// If you add a new modifier, please consider updating functions
87  /// parse_real_type_modifier and real_type::to_string.
89  {
90  NO_MODIFIER = 0,
91  /// The "signed" modifier.
93  /// The "unsigned" modier.
95  /// The "short" modifier.
96  SHORT_MODIFIER = 1 << 2,
97  /// The "long" modifier.
98  LONG_MODIFIER = 1 << 3,
99  /// The "long long" modifier.
101  };
102 
103 private:
104  base_type base_;
105  modifiers_type modifiers_;
106 
107 public:
108 
109  real_type();
110  real_type(const string& name);
112 
113  base_type
114  get_base_type() const;
115 
117  get_modifiers() const;
118 
119  void
121 
122  bool
123  operator==(const real_type&) const;
124 
125  string
126  to_string(bool internal=false) const;
127 
128  operator string() const;
129 }; // end class real_type
130 
133 
136 
139 
142 
145 
146 bool
147 parse_real_type(const string& type_name,
148  real_type& type);
149 
150 /// Private type to hold private members of @ref translation_unit
152 {
153  const environment& env_;
154  corpus* corp;
155  bool is_constructed_;
156  char address_size_;
157  language language_;
158  std::string path_;
159  std::string comp_dir_path_;
160  std::string abs_path_;
161  location_manager loc_mgr_;
162  mutable global_scope_sptr global_scope_;
163  mutable vector<type_base_sptr> synthesized_types_;
164  vector<function_type_sptr> live_fn_types_;
165  type_maps types_;
166 
167 
168  priv(const environment& env)
169  : env_(env),
170  corp(),
171  is_constructed_(),
172  address_size_(),
173  language_(LANG_UNKNOWN)
174  {}
175 
176  ~priv()
177  {}
178 
179  type_maps&
180  get_types()
181  {return types_;}
182 }; // end translation_unit::priv
183 
184 // <type_or_decl_base stuff>
185 
186 /// The private data of @ref type_or_decl_base.
188 {
189  // This holds the kind of dynamic type of particular instance.
190  // Yes, this is part of the implementation of a "poor man" runtime
191  // type identification. We are doing this because profiling shows
192  // that using dynamic_cast in some places is really to slow and is
193  // constituting a hotspot. This poor man's implementation made
194  // things be much faster.
195  enum type_or_decl_kind kind_;
196  // This holds the runtime type instance pointer of particular
197  // instance. In other words, this is the "this pointer" of the
198  // dynamic type of a particular instance.
199  void* rtti_;
200  // This holds a pointer to either the type_base sub-object (if the
201  // current instance is a type) or the decl_base sub-object (if the
202  // current instance is a decl). This is used by the is_decl() and
203  // is_type() functions, which also show up during profiling as
204  // hotspots, due to their use of dynamic_cast.
205  void* type_or_decl_ptr_;
206  mutable hashing::hashing_state hashing_state_;
207  bool is_recursive_artefact_;
208  hash_t hash_value_;
209  const environment& env_;
210  translation_unit* translation_unit_;
211  // The location of an artifact as seen from its input by the
212  // artifact reader. This might be different from the source
213  // location advertised by the original emitter of the artifact
214  // emitter.
215  location artificial_location_;
216  // Flags if the current ABI artifact is artificial (i.e, *NOT*
217  // generated from the initial source code, but rather either
218  // artificially by the compiler or by libabigail itself).
219  bool is_artificial_;
220 
221  /// Constructor of the type_or_decl_base::priv private type.
222  ///
223  /// @param e the environment in which the ABI artifact was created.
224  ///
225  /// @param k the identifier of the runtime type of the current
226  /// instance of ABI artifact.
227  priv(const environment& e,
228  enum type_or_decl_kind k = ABSTRACT_TYPE_OR_DECL)
229  : kind_(k),
230  rtti_(),
231  type_or_decl_ptr_(),
232  hashing_state_(hashing::HASHING_NOT_DONE_STATE),
233  is_recursive_artefact_(),
234  env_(e),
235  translation_unit_(),
236  is_artificial_()
237  {}
238 
239  /// Getter of the kind of the IR node.
240  ///
241  /// @return the kind of the IR node.
242  enum type_or_decl_kind
243  kind() const
244  {return kind_;}
245 
246  /// Setter of the kind of the IR node.
247  ///
248  /// @param k the new IR node kind.
249  void
251  {kind_ |= k;}
252 
253  /// Getter the hashing state of the current IR node.
254  ///
255  /// @return the hashing state of the current IR node.
258  {return hashing_state_;}
259 
260  /// Getter of the property which flags the current artefact as being
261  /// recursive or not.
262  ///
263  /// @return true iff the current artefact it recursive.
264  bool
266  {return is_recursive_artefact_;}
267 
268  /// Setter of the property which flags the current artefact as being
269  /// recursive or not.
270  ///
271  /// @param f the new value of the property.
272  void
274  {is_recursive_artefact_ = f;}
275 
276  /// Setter of the hashing state of the current IR node.
277  ///
278  /// @param s the hashing state of the current IR node.
279  void
281  {hashing_state_ = s;}
282 
283  /// Setter of the hashing value of the current IR node.
284  ///
285  /// An empty value is just ignored. Also, if the IR node is NEITHER
286  /// in the hashing::HASHING_NOT_DONE_STATE nor in the
287  /// hashing::HASHING_CYCLED_TYPE_STATE, then the function does
288  /// nothing.
289  ///
290  /// @param h the new hash value.
291  void
293  {
295 
300  if (h.has_value()
303  {
304  hash_value_ = h;
306  }
307  }
308 
309  /// Setter of the hashing value of the current IR node.
310  ///
311  /// Unlike set_hash_value above, this function always sets a new
312  /// hash value regardless of the hash value or of the hashing state
313  /// of the IR node.
314  ///
315  /// @param h the new hash value.
316  void
318  {
319  if (h.has_value())
320  {
321  hash_value_ = h;
323  }
324  }
325 }; // end struct type_or_decl_base::priv
326 
327 /// Compute the hash value of an IR node and return it.
328 ///
329 /// Note that if the IR node is a non-canonicalizeable type, no hash
330 /// value is computed and an empty hash is returned. Also, if the IR
331 /// node already has a hash value, then this function just returns it.
332 ///
333 /// This is a sub-routine of the internal hashing functions defined in
334 /// abg-hash.cc
335 ///
336 /// @param tod the IR node to compute the value for.
337 ///
338 /// @return the computed hash value computed.
339 template<typename T>
340 hash_t
341 do_hash_value(const T& tod)
342 {
343  if (type_base* type = is_type(&tod))
344  if (is_non_canonicalized_type(type))
345  // Non canonicalized types are not hashed. They must always be
346  // compared structurally.
347  return hash_t();
348 
349  typename T::hash do_hash;
350  hash_t h = do_hash(tod);
351  return h;
352 }
353 
354 /// Compute the hash value of an IR node and return it.
355 ///
356 /// Note that if the IR node is a non-canonicalizeable type, no hash
357 /// value is computed and an empty hash is returned. Also, if the IR
358 /// node already has a hash value, then this function just returns it.
359 ///
360 /// This is a sub-routine of the internal hashing functions defined in
361 /// abg-hash.cc
362 ///
363 /// @param tod the IR node to compute the value for.
364 ///
365 /// @return the computed hash value computed.
366 template<typename T>
367 hash_t
368 do_hash_value(const T* tod)
369 {
370  if (!tod)
371  return hash_t();
372  return hash_value(*tod);
373 }
374 
375 /// Compute the hash value of an IR node and return it.
376 ///
377 /// Note that if the IR node is a non-canonicalizeable type, no hash
378 /// value is computed and an empty hash is returned. Also, if the IR
379 /// node already has a hash value, then this function just returns it.
380 ///
381 /// This is a sub-routine of the internal hashing functions defined in
382 /// abg-hash.cc
383 ///
384 /// @param tod the IR node to compute the value for.
385 ///
386 /// @return the computed hash value computed.
387 template<typename T>
388 hash_t
389 do_hash_value(const shared_ptr<T>& tod)
390 {
391  if (!tod)
392  return hash_t();
393  return do_hash_value(*tod);
394 }
395 
396 
397 /// Set the hash value of an IR node and return it.
398 ///
399 /// If the IR node already has a hash value set, this function just
400 /// returns it. Otherwise, the function computes a new hash value and
401 /// sets it to the IR node.
402 ///
403 /// Note that if the IR node is a non-canonicalizeable type, no hash
404 /// value is computed and an empty hash is returned.
405 ///
406 /// This is a sub-routine of the type_or_decl_base::hash_value()
407 /// virtual member functions.
408 ///
409 /// @param type_or_decl the IR node to compute the value for.
410 ///
411 /// @return the hash value computed and set to the IR node, or the
412 /// hash value the IR node already had.
413 template<typename T>
414 hash_t
416 {
417  hash_t h = do_hash_value(tod);
418  const_cast<T&>(tod).set_hash_value(h);
419  return h;
420 }
421 
422 /// Set the hash value of an IR node and return it.
423 ///
424 /// If the IR node already has a hash value set, this function just
425 /// returns it. Otherwise, the function computes a new hash value and
426 /// sets it to the IR node.
427 ///
428 /// Note that if the IR node is a non-canonicalizeable type, no hash
429 /// value is computed and an empty hash is returned.
430 ///
431 /// This is a sub-routine of the type_or_decl_base::hash_value()
432 /// virtual member functions.
433 ///
434 /// @param type_or_decl the IR node to compute the value for.
435 ///
436 /// @return the hash value computed and set to the IR node, or the
437 /// hash value the IR node already had.
438 template<typename T>
439 hash_t
441 {
442  if (!artifact)
443  return hash_t();
444  return set_or_get_cached_hash_value(*artifact);
445 }
446 
447 // </type_or_decl_base stuff>
448 
449 
450 // <type_base definitions>
451 
452 size_t
454 
455 size_t
457 
458 size_t
459 get_canonical_type_index(const type_base_sptr& t);
460 
461 /// Definition of the private data of @ref type_base.
463 {
464  size_t size_in_bits;
465  size_t alignment_in_bits;
466  size_t canonical_type_index;
467  type_base_wptr canonical_type;
468  // The data member below holds the canonical type that is managed by
469  // the smart pointer referenced by the canonical_type data member
470  // above. We are storing this underlying (naked) pointer here, so
471  // that users can access it *fast*. Otherwise, accessing
472  // canonical_type above implies creating a shared_ptr, and that has
473  // been measured to be slow for some performance hot spots.
474  type_base* naked_canonical_type;
475  // Computing the representation of a type again and again can be
476  // costly. So we cache the internal and non-internal type
477  // representation strings here.
478  interned_string internal_cached_repr_;
479  interned_string cached_repr_;
480 
481  priv()
482  : size_in_bits(),
483  alignment_in_bits(),
484  canonical_type_index(),
485  naked_canonical_type()
486  {}
487 
488  priv(size_t s,
489  size_t a,
490  type_base_sptr c = type_base_sptr())
491  : size_in_bits(s),
492  alignment_in_bits(a),
493  canonical_type_index(),
494  canonical_type(c),
495  naked_canonical_type(c.get())
496  {}
497 }; // end struct type_base::priv
498 
499 bool
501 
502 // <environment definitions>
503 
504 /// The hashing functor for a pair of uint64_t.
506 {
507  /// Hashing function for a pair of uint64_t.
508  ///
509  /// @param p the pair to hash.
510  uint64_t
511  operator()(const std::pair<uint64_t, uint64_t>& p) const
512  {
513  return *abigail::hashing::combine_hashes(hash_t(p.first),
514  hash_t(p.second));
515  }
516 };
517 
518 /// A convenience typedef for a pair of uint64_t which is initially
519 /// intended to store a pair of pointer values.
520 typedef std::pair<uint64_t, uint64_t> uint64_t_pair_type;
521 
522 /// A convenience typedef for a set of @ref uint64_t_pair
523 typedef unordered_set<uint64_t_pair_type,
525 
526 /// A convenience typedef for a set of pointer to @ref class_or_union
527 typedef unordered_set<const class_or_union*> class_set_type;
528 
529 /// A convenience typedef for a set of pointer to @ref function_type.
530 typedef unordered_set<const function_type*> fn_set_type;
531 
532 /// A convenience typedef for a map which key is a pair of uint64_t
533 /// and which value is a boolean. This is initially intended to cache
534 /// the result of comparing two (sub-)types.
535 typedef unordered_map<uint64_t_pair_type, bool,
537 
538 /// The private data of the @ref environment type.
540 {
541  config config_;
542  canonical_types_map_type canonical_types_;
543  mutable vector<type_base_sptr> sorted_canonical_types_;
544  type_base_sptr void_type_;
545  type_base_sptr void_pointer_type_;
546  type_base_sptr variadic_marker_type_;
547  // The set of pairs of class types being currently compared. It's
548  // used to avoid endless loops while recursively comparing types.
549  // This should be empty when none of the 'equal' overloads are
550  // currently being invoked.
551  class_set_type left_classes_being_compared_;
552  class_set_type right_classes_being_compared_;
553  // The set of pairs of function types being currently compared. It's used
554  // to avoid endless loops while recursively comparing types. This
555  // should be empty when none of the 'equal' overloads are currently
556  // being invoked.
557  fn_set_type left_fn_types_being_compared_;
558  fn_set_type right_fn_types_being_compared_;
559  // This is a cache for the result of comparing two sub-types (of
560  // either class or function types) that are designated by their
561  // memory address in the IR.
562  type_comparison_result_type type_comparison_results_cache_;
563  vector<type_base_sptr> extra_live_types_;
564  interned_string_pool string_pool_;
565  // The two vectors below represent the stack of left and right
566  // operands of the current type comparison operation that is
567  // happening during type canonicalization.
568  //
569  // Basically, that stack of operand looks like below.
570  //
571  // First, suppose we have a type T_L that has two sub-types as this:
572  //
573  // T_L
574  // |
575  // +-- L_OP0
576  // |
577  // +-- L_OP1
578  //
579  // Now suppose that we have another type T_R that has two sub-types
580  // as this:
581  //
582  // T_R
583  // |
584  // +-- R_OP0
585  // |
586  // +-- R_OP1
587  //
588  // Now suppose that we compare T_L against T_R. We are going to
589  // have a stack of pair of types. Each pair of types represents
590  // two (sub) types being compared against each other.
591  //
592  // On the stack, we will thus first have the pair (T_L, T_R)
593  // being compared. Then, we will have the pair (L_OP0, R_OP0)
594  // being compared, and then the pair (L_OP1, R_OP1) being
595  // compared. Like this:
596  //
597  // | T_L | L_OP0 | L_OP1 | <-- this goes into left_type_comp_operands_;
598  // -------- -------------
599  // | T_R | R_OP0 | R_OP1 | <-- this goes into right_type_comp_operands_;
600  //
601  vector<const type_base*> left_type_comp_operands_;
602  vector<const type_base*> right_type_comp_operands_;
603 
604 #ifdef WITH_DEBUG_SELF_COMPARISON
605  // This is used for debugging purposes.
606  // When abidw is used with the option --debug-abidiff, some
607  // libabigail internals need to get a hold on the initial binary
608  // input of abidw, as well as as the abixml file that represents the
609  // ABI of that binary.
610  //
611  // So this one is the corpus for the input binary.
612  corpus_wptr first_self_comparison_corpus_;
613  // This one is the corpus for the ABIXML file representing the
614  // serialization of the input binary.
615  corpus_wptr second_self_comparison_corpus_;
616  // This is also used for debugging purposes, when using
617  // 'abidw --debug-abidiff <binary>'. It holds the set of mapping of
618  // an abixml (canonical) type and its type-id.
619  unordered_map<string, uintptr_t> type_id_canonical_type_map_;
620  // Likewise. It holds a map that associates the pointer to a type
621  // read from abixml and the type-id string it corresponds to.
622  unordered_map<uintptr_t, string> pointer_type_id_map_;
623 #endif
624  bool canonicalization_started_;
625  bool canonicalization_is_done_;
626  bool decl_only_class_equals_definition_;
627  bool use_enum_binary_only_equality_;
628  bool allow_type_comparison_results_caching_;
629  bool do_log_;
630  optional<bool> analyze_exported_interfaces_only_;
631 #ifdef WITH_DEBUG_SELF_COMPARISON
632  bool self_comparison_debug_on_;
633 #endif
634 #ifdef WITH_DEBUG_TYPE_CANONICALIZATION
635  // This controls whether to use canonical type comparison during
636  // type comparison or not. This is only used for debugging, when we
637  // want to ensure that comparing types using canonical or structural
638  // comparison yields the same result.
639  bool use_canonical_type_comparison_;
640  // Whether we are debugging type canonicalization or not. When
641  // debugging type canonicalization, a type is compared to its
642  // potential canonical type twice: The first time with canonical
643  // comparison activated, and the second time with structural
644  // comparison activated. The two comparison should yield the same
645  // result, otherwise, canonicalization is "broken" for that
646  // particular type.
647  bool debug_type_canonicalization_;
648  bool debug_die_canonicalization_;
649 #endif
650 
651  priv()
652  : canonicalization_started_(),
653  canonicalization_is_done_(),
654  decl_only_class_equals_definition_(false),
655  use_enum_binary_only_equality_(true),
656  allow_type_comparison_results_caching_(false),
657  do_log_(false)
658 #ifdef WITH_DEBUG_SELF_COMPARISON
659  ,
660  self_comparison_debug_on_(false)
661 #endif
662 #ifdef WITH_DEBUG_TYPE_CANONICALIZATION
663  ,
664  use_canonical_type_comparison_(true),
665  debug_type_canonicalization_(false),
666  debug_die_canonicalization_(false)
667 #endif
668  {}
669 
670  /// Allow caching of the sub-types comparison results during the
671  /// invocation of the @ref equal overloads for class and function
672  /// types.
673  ///
674  /// @param f if true, allow type comparison result caching.
675  void
677  {allow_type_comparison_results_caching_ = f;}
678 
679  /// Check whether if caching of the sub-types comparison results during the
680  /// invocation of the @ref equal overloads for class and function
681  /// types is in effect.
682  ///
683  /// @return true iff caching of the sub-types comparison results
684  /// during the invocation of the @ref equal overloads for class and
685  /// function types is in effect.
686  bool
688  {return allow_type_comparison_results_caching_;}
689 
690  void
691  do_log(bool f)
692  {do_log_ = f;}
693 
694  bool
695  do_log() const
696  {return do_log_;}
697 
698  /// Cache the result of comparing two sub-types.
699  ///
700  /// @param first the first sub-type that has been compared. Its
701  /// address is going to be stored in the cache.
702  ///
703  /// @param second the second sub-type that has been compared. Its
704  /// address is going to be stored in the cache.
705  ///
706  /// @param r the result of comparing @p first and @p second. This
707  /// is going to be stored in the cache, as well as the addresses of
708  /// @p first and @p second.
709  template<typename T>
710  void
711  cache_type_comparison_result(T& first, T& second, bool r)
712  {
714  {
715  type_comparison_results_cache_.emplace
716  (std::make_pair(reinterpret_cast<uint64_t>(&first),
717  reinterpret_cast<uint64_t>(&second)),
718  r);
719  }
720  }
721 
722  /// Retrieve the result of comparing two sub-types from the cache,
723  /// if it was previously stored.
724  ///
725  /// @param first the first sub-type to consider.
726  ///
727  /// @param second the second sub-type to consider. The pair of
728  /// addresses of {@p first, @p second} is going to be looked up in
729  /// the cache. If it's present, then the associated result of the
730  /// comparison of @p first against @p second is present as well, and
731  /// is returned.
732  ///
733  /// @param r this is an out parameter which is set to the result of
734  /// the comparison of @p first against @p second if the pair of
735  /// addresses of {@p first, @p second} is present in the cache.
736  ///
737  /// @return true iff the pair of addresses of {@p first, @p second}
738  /// is present in the cache. In that case, the associated result of
739  /// the comparison of @p first against @p second is returned in the
740  /// argument of @p r.
741  template<typename T>
742  bool
743  is_type_comparison_cached(T& first, T& second, bool& r)
744  {
746  return false;
747 
748  type_comparison_result_type::const_iterator it =
749  type_comparison_results_cache_.find
750  (std::make_pair(reinterpret_cast<uint64_t>(&first),
751  reinterpret_cast<uint64_t>(&second)));
752  if (it == type_comparison_results_cache_.end())
753  return false;
754 
755  r = it->second;
756  return true;
757  }
758 
759  /// Clear the cache type comparison results.
760  void
762  {type_comparison_results_cache_.clear();}
763 
764  /// Push a pair of operands on the stack of operands of the current
765  /// type comparison, during type canonicalization.
766  ///
767  /// For more information on this, please look at the description of
768  /// the right_type_comp_operands_ data member.
769  ///
770  /// @param left the left-hand-side comparison operand to push.
771  ///
772  /// @param right the right-hand-side comparison operand to push.
773  void
775  const type_base* right)
776  {
777  ABG_ASSERT(left && right);
778 
779  left_type_comp_operands_.push_back(left);
780  right_type_comp_operands_.push_back(right);
781  }
782 
783  /// Pop a pair of operands from the stack of operands to the current
784  /// type comparison.
785  ///
786  /// For more information on this, please look at the description of
787  /// the right_type_comp_operands_ data member.
788  ///
789  /// @param left the left-hand-side comparison operand we expect to
790  /// pop from the top of the stack. If this doesn't match the
791  /// operand found on the top of the stack, the function aborts.
792  ///
793  /// @param right the right-hand-side comparison operand we expect to
794  /// pop from the bottom of the stack. If this doesn't match the
795  /// operand found on the top of the stack, the function aborts.
796  void
798  const type_base* right)
799  {
800  const type_base *t = left_type_comp_operands_.back();
801  ABG_ASSERT(t == left);
802  t = right_type_comp_operands_.back();
803  ABG_ASSERT(t == right);
804 
805  left_type_comp_operands_.pop_back();
806  right_type_comp_operands_.pop_back();
807  }
808 
809 #ifdef WITH_DEBUG_SELF_COMPARISON
810 
811  const unordered_map<string, uintptr_t>&
812  get_type_id_canonical_type_map() const
813  {return type_id_canonical_type_map_;}
814 
815  unordered_map<string, uintptr_t>&
816  get_type_id_canonical_type_map()
817  {return type_id_canonical_type_map_;}
818 
819  const unordered_map<uintptr_t, string>&
820  get_pointer_type_id_map() const
821  {return pointer_type_id_map_;}
822 
823  unordered_map<uintptr_t, string>&
824  get_pointer_type_id_map()
825  {return pointer_type_id_map_;}
826 
827  string
828  get_type_id_from_pointer(uintptr_t ptr) const
829  {
830  auto it = get_pointer_type_id_map().find(ptr);
831  if (it != get_pointer_type_id_map().end())
832  return it->second;
833  return "";
834  }
835 
836  string
837  get_type_id_from_type(const type_base *t) const
838  {return get_type_id_from_pointer(reinterpret_cast<uintptr_t>(t));}
839 
840  uintptr_t
841  get_canonical_type_from_type_id(const char* type_id) const
842  {
843  if (!type_id)
844  return 0;
845  auto it = get_type_id_canonical_type_map().find(type_id);
846  if (it != get_type_id_canonical_type_map().end())
847  return it->second;
848  return 0;
849  }
850 
851  /// When debugging self comparison, verify that a type T
852  /// de-serialized from abixml has the same canonical type as the
853  /// initial type built from DWARF that was serialized into T in the
854  /// first place.
855  ///
856  /// @param t deserialized type (from abixml) to consider.
857  ///
858  /// @param c the canonical type that @p t has, as computed freshly
859  /// from the abixml file.
860  ///
861  /// @return true iff @p c has the same value as the canonical type
862  /// that @p t had before being serialized into abixml.
863  bool
864  check_canonical_type_from_abixml_during_self_comp(const type_base* t,
865  const type_base* c)
866  {
867  if (!t || !t->get_corpus() || !c)
868  return false;
869 
870  if (!(t->get_corpus()->get_origin() == ir::corpus::NATIVE_XML_ORIGIN))
871  return false;
872 
873  // Get the abixml type-id that this type was constructed from.
874  string type_id;
875  {
876  unordered_map<uintptr_t, string>::const_iterator it =
877  pointer_type_id_map_.find(reinterpret_cast<uintptr_t>(t));
878  if (it == pointer_type_id_map_.end())
879  // This type didn't have a type-id in the abixml file. Maybe
880  // it's a function or method type. So let's just keep going.
881  return true;
882  type_id = it->second;
883  }
884 
885  // Get the canonical type the original in-memory type (constructed
886  // from DWARF) had when it was serialized into abixml in the first place.
887  type_base *original_canonical_type = nullptr;
888  if (!type_id.empty())
889  {
890  unordered_map<string, uintptr_t>::const_iterator it =
891  type_id_canonical_type_map_.find(type_id);
892  if (it == type_id_canonical_type_map_.end())
893  return false;
894  original_canonical_type = reinterpret_cast<type_base*>(it->second);
895  }
896 
897  // Now perform the real check.
898  //
899  // We want to ensure that the canonical type 'c' of 't' is the
900  // same as the canonical type of initial in-memory type (built
901  // from DWARF) that was serialized into 't' (in abixml) in the
902  // first place.
903  if (original_canonical_type == c)
904  return true;
905 
906  return false;
907  }
908 
909  /// When debugging self comparison, verify that a type T
910  /// de-serialized from abixml has the same canonical type as the
911  /// initial type built from DWARF that was serialized into T in the
912  /// first place.
913  ///
914  /// @param t deserialized type (from abixml) to consider.
915  ///
916  /// @return true iff @p c is the canonical type that @p t should
917  /// have.
918  bool
919  check_abixml_canonical_type_propagation_during_self_comp(const type_base* t)
920  {
921  if (t->get_corpus()
922  && t->get_corpus()->get_origin() == ir::corpus::NATIVE_XML_ORIGIN)
923  {
924  type_base* c = t->get_naked_canonical_type();
925  if (c && !check_canonical_type_from_abixml_during_self_comp(t, c))
926  {
927  string repr = t->get_pretty_representation(true, true);
928  string type_id = get_type_id_from_type(t);
929  std::cerr << "error: canonical type propagation error for '"
930  << repr
931  << "' of type-id: '"
932  << type_id
933  << "' / type: @"
934  << std::hex
935  << t
936  << "/ canon: @"
937  << c
938  << ", should have had canonical type: "
939  << std::hex
940  << get_canonical_type_from_type_id(type_id.c_str())
941  << "\n";
942  return false;
943  }
944  }
945  return true;
946  }
947 
948  /// When debugging self comparison, verify that a type T
949  /// de-serialized from abixml has the same canonical type as the
950  /// initial type built from DWARF that was serialized into T in the
951  /// first place.
952  ///
953  /// @param t deserialized type (from abixml) to consider.
954  ///
955  /// @param c the canonical type @p t should have.
956  ///
957  /// @return true iff @p c is the canonical type that @p t should
958  /// have.
959  bool
960  check_canonical_type_from_abixml_during_self_comp(const type_base_sptr& t,
961  const type_base_sptr& c)
962  {
963  return check_canonical_type_from_abixml_during_self_comp(t.get(), c.get());
964  }
965 #endif
966 };// end struct environment::priv
967 
968 bool
969 compare_using_locations(const decl_base *f,
970  const decl_base *s);
971 
972 /// A functor to sort decls somewhat topologically. That is, types
973 /// are sorted in a way that makes the ones that are defined "first"
974 /// to come first.
975 ///
976 /// The topological criteria is a lexicographic sort of the definition
977 /// location of the type. For types that have no location (or the
978 /// same location), it's their qualified name that is used for the
979 /// lexicographic sort.
981 {
982  /// Test if a decl has an artificial or natural location.
983  ///
984  /// @param d the decl to consider
985  ///
986  /// @return true iff @p d has a location.
987  bool
990 
991  /// Test if a type has an artificial or natural location.
992  ///
993  /// @param t the type to consider
994  ///
995  /// @return true iff @p t has a location.
996  bool
998  {
999  if (decl_base *d = is_decl(t))
1001  return false;
1002  }
1003 
1004  /// The "Less Than" comparison operator of this functor.
1005  ///
1006  /// @param f the first decl to be considered for the comparison.
1007  ///
1008  /// @param s the second decl to be considered for the comparison.
1009  ///
1010  /// @return true iff @p f is less than @p s.
1011  bool
1013  const decl_base *s)
1014  {
1015  if (!!f != !!s)
1016  return f && !s;
1017 
1018  if (!f)
1019  return false;
1020 
1021  // Unique types that are artificially created in the environment
1022  // don't have locations. They ought to be compared on the basis
1023  // of their pretty representation before we start looking at IR
1024  // nodes' locations down the road.
1026  return (f->get_cached_pretty_representation(/*internal=*/false)
1027  < s->get_cached_pretty_representation(/*internal=*/false));
1028 
1029  // If both decls come from an abixml file, keep the order they
1030  // have from that abixml file.
1033  && (((!f->get_corpus() && !s->get_corpus())
1034  || (f->get_corpus() && f->get_corpus()->get_origin() == corpus::NATIVE_XML_ORIGIN
1035  && s->get_corpus() && s->get_corpus()->get_origin() == corpus::NATIVE_XML_ORIGIN))))
1036  return compare_using_locations(f, s);
1037 
1038  // If a decl has artificial location, then use that one over the
1039  // natural one.
1042 
1043  if (fl.get_value() && sl.get_value())
1044  return compare_using_locations(f, s);
1045  else if (!!fl != !!sl)
1046  // So one of the decls doesn't have location data.
1047  // The first decl is less than the second if it's the one not
1048  // having location data.
1049  return !fl && sl;
1050 
1051  // We reach this point if location data is useless.
1052  if (f->get_is_anonymous()
1053  && s->get_is_anonymous()
1054  && (f->get_cached_pretty_representation(/*internal=*/false)
1055  == s->get_cached_pretty_representation(/*internal=*/false)))
1056  return f->get_name() < s->get_name();
1057 
1058  return (f->get_cached_pretty_representation(/*internal=*/false)
1059  < s->get_cached_pretty_representation(/*internal=*/false));
1060  }
1061 
1062  /// The "Less Than" comparison operator of this functor.
1063  ///
1064  /// @param f the first decl to be considered for the comparison.
1065  ///
1066  /// @param s the second decl to be considered for the comparison.
1067  ///
1068  /// @return true iff @p f is less than @p s.
1069  bool
1070  operator()(const decl_base_sptr &f,
1071  const decl_base_sptr &s)
1072  {return operator()(f.get(), s.get());}
1073 
1074 }; // end struct decl_topo_comp
1075 
1076 bool
1078 
1079 /// A functor to sort types somewhat topologically. That is, types
1080 /// are sorted in a way that makes the ones that are defined "first"
1081 /// to come first.
1082 ///
1083 /// The topological criteria is a lexicographic sort of the definition
1084 /// location of the type. For types that have no location, it's their
1085 /// qualified name that is used for the lexicographic sort.
1087 {
1088  /// Test if a decl has an artificial or natural location.
1089  ///
1090  /// @param d the decl to consider
1091  ///
1092  /// @return true iff @p d has a location.
1093  bool
1096 
1097  /// Test if a type has an artificial or natural location.
1098  ///
1099  /// @param t the type to consider
1100  ///
1101  /// @return true iff @p t has a location.
1102  bool
1104  {
1105  if (decl_base *d = is_decl(t))
1107  return false;
1108  }
1109 
1110  /// The "Less Than" comparison operator of this functor.
1111  ///
1112  /// @param f the first type to be considered for the comparison.
1113  ///
1114  /// @param s the second type to be considered for the comparison.
1115  ///
1116  /// @return true iff @p f is less than @p s.
1117  bool
1118  operator()(const type_base_sptr &f,
1119  const type_base_sptr &s)
1120  {return operator()(f.get(), s.get());}
1121 
1122  /// The "Less Than" comparison operator of this functor.
1123  ///
1124  /// @param f the first type to be considered for the comparison.
1125  ///
1126  /// @param s the second type to be considered for the comparison.
1127  ///
1128  /// @return true iff @p f is less than @p s.
1129  bool
1131  const type_base *s)
1132  {
1133  if (f == s || !f || !s)
1134  return false;
1135 
1136  // If both decls come from an abixml file, keep the order they
1137  // have from that abixml file.
1138  if (is_decl(f) && is_decl(s)
1141  && ((!f->get_corpus() && !s->get_corpus())
1142  || (f->get_corpus()
1143  && f->get_corpus()->get_origin() == corpus::NATIVE_XML_ORIGIN
1144  && s->get_corpus()
1145  && (s->get_corpus()->get_origin()
1146  == corpus::NATIVE_XML_ORIGIN))))
1147  return compare_using_locations(is_decl(f), is_decl(s));
1148 
1149  bool f_is_ptr_ref_or_qual = is_ptr_ref_or_qual_type(f);
1150  bool s_is_ptr_ref_or_qual = is_ptr_ref_or_qual_type(s);
1151 
1152  if (f_is_ptr_ref_or_qual != s_is_ptr_ref_or_qual)
1153  return !f_is_ptr_ref_or_qual && s_is_ptr_ref_or_qual;
1154 
1155  if (f_is_ptr_ref_or_qual && s_is_ptr_ref_or_qual
1158  {
1159  interned_string s1 = f->get_cached_pretty_representation(/*internal=*/false);
1160  interned_string s2 = s->get_cached_pretty_representation(/*internal=*/false);
1161  if (s1 == s2)
1162  {
1164  {
1165  if (q->get_cv_quals() == qualified_type_def::CV_NONE)
1166  if (!is_qualified_type(s))
1167  // We are looking at two types that are the result of
1168  // an optimization that happens during the IR
1169  // construction. Namely, type f is a cv-qualified
1170  // type with no qualifier (no const, no volatile, no
1171  // nothing, we call it an empty-qualified type).
1172  // These are the result of an optimization which
1173  // removes "redundant qualifiers" from some types.
1174  // For instance, consider a "const reference". The
1175  // const there is redundant because a reference is
1176  // always const. So as a result of the optimizaton
1177  // that type is going to be transformed into an
1178  // empty-qualified reference. If we don't make that
1179  // optimization, then we risk having spurious change
1180  // reports down the road. But then, as a consequence
1181  // of that optimization, we need to sort the
1182  // empty-qualified type and its non-qualified variant
1183  // e.g, to ensure stability in the abixml output; both
1184  // types are logically equal, but here, we decide that
1185  // the empty-qualified one is topologically "less
1186  // than" the non-qualified counterpart.
1187  //
1188  // So here, type f is an empty-qualified type and type
1189  // s is its non-qualified variant. We decide that f
1190  // is topologically less than s.
1191  return true;
1192  }
1193  // Now let's peel off the pointer (or reference types) and
1194  // see if the ultimate underlying types have the same
1195  // textual representation; if not, use that as sorting
1196  // criterion.
1197  type_base *peeled_f =
1199  type_base *peeled_s =
1201 
1202  s1 = peeled_f->get_cached_pretty_representation(/*internal=*/false);
1203  s2 = peeled_s->get_cached_pretty_representation(/*internal=*/false);
1204  if (s1 != s2)
1205  return s1 < s2;
1206 
1207  // The underlying type of pointer/reference have the same
1208  // textual representation; let's try to peel of typedefs
1209  // as well and we'll consider sorting the result as decls.
1210  peeled_f = peel_typedef_pointer_or_reference_type(peeled_f, true);
1211  peeled_s = peel_typedef_pointer_or_reference_type(peeled_s, true);
1212 
1213  s1 = peeled_f->get_cached_pretty_representation(false);
1214  s2 = peeled_s->get_cached_pretty_representation(false);
1215  if (s1 != s2)
1216  return s1 < s2;
1217  }
1218  }
1219 
1222 
1223  if (s1 != s2)
1224  return s1 < s2;
1225 
1226  if (is_typedef(f) && is_typedef(s))
1227  {
1228  s1 = is_typedef(f)->get_underlying_type()->get_cached_pretty_representation(false);
1229  s2 = is_typedef(s)->get_underlying_type()->get_cached_pretty_representation(false);
1230  if (s1 != s2)
1231  return s1 < s2;
1232  }
1233 
1236 
1237  s1 = peeled_f->get_cached_pretty_representation(false);
1238  s2 = peeled_s->get_cached_pretty_representation(false);
1239 
1240  if (s1 != s2)
1241  return s1 < s2;
1242 
1243  if (method_type* m_f = is_method_type(peeled_f))
1244  if (method_type* m_s = is_method_type(peeled_s))
1245  {
1246  // If two method types differ from their const-ness, make the
1247  // const one come first.
1248  if (m_f->get_is_const() != m_s->get_is_const())
1249  return m_f->get_is_const();
1250 
1251  // If two method types have the same name (textual
1252  // representation), make the non-static one come first.
1253  if (m_f->get_is_for_static_method() != m_s->get_is_for_static_method())
1254  return m_f->get_is_for_static_method() < m_s->get_is_for_static_method();
1255  }
1256 
1257  decl_base *fd = is_decl(f);
1258  decl_base *sd = is_decl(s);
1259 
1260  if (!!fd != !!sd)
1261  return fd && !sd;
1262 
1263  if (!fd
1264  && f->get_translation_unit()
1265  && s->get_translation_unit())
1266  {
1267  string s1 = f->get_translation_unit()->get_absolute_path();
1268  string s2 = s->get_translation_unit()->get_absolute_path();
1269  return s1 < s2;
1270  }
1271 
1272  // If all pretty representions are equal, sort by
1273  // hash value and canonical type index.
1274  hash_t h_f = peek_hash_value(*f);
1275  hash_t h_s = peek_hash_value(*s);
1276  if (h_f && h_s && *h_f != *h_s)
1277  return *h_f < *h_s;
1278 
1279  size_t cti_f = get_canonical_type_index(*f);
1280  size_t cti_s = get_canonical_type_index(*s);
1281  if (cti_f != cti_s)
1282  return cti_f < cti_s;
1283 
1284  // If the two types have no decls, how come we could not sort them
1285  // until now? Let's investigate.
1286  ABG_ASSERT(fd);
1287 
1288  // From this point, fd and sd should be non-nil
1289  decl_topo_comp decl_comp;
1290  return decl_comp(fd, sd);
1291  }
1292 }; //end struct type_topo_comp
1293 
1294 /// Functor used to sort types before hashing them.
1296 {
1297  /// Return the rank of a given kind of IR node.
1298  ///
1299  /// The rank is used to sort a kind of IR node relative to another
1300  /// one of a different kind. For instance, a an IR node of
1301  /// BASIC_TYPE kind has a lower rank than an IR node of ENUM_TYPE
1302  /// kind.
1303  ///
1304  /// @param k the kind of a given IR node.
1305  ///
1306  /// @return the rank of the IR node.
1307  size_t
1309  {
1310  size_t result = 0;
1311 
1312  if (k & type_or_decl_base::BASIC_TYPE)
1313  result = 1;
1314  if (k & type_or_decl_base::SUBRANGE_TYPE)
1315  result = 2;
1316  else if (k & type_or_decl_base::ENUM_TYPE)
1317  result = 3;
1318  else if (k & type_or_decl_base::CLASS_TYPE)
1319  result = 4;
1320  else if (k & type_or_decl_base::UNION_TYPE)
1321  result = 5;
1322  else if (k & type_or_decl_base::FUNCTION_TYPE)
1323  result = 6;
1324  else if (k & type_or_decl_base::METHOD_TYPE)
1325  result = 7;
1326  else if (k & type_or_decl_base::TYPEDEF_TYPE)
1327  result = 8;
1328  else if (k & type_or_decl_base::QUALIFIED_TYPE)
1329  result = 9;
1330  else if (k & type_or_decl_base::POINTER_TYPE)
1331  result = 10;
1332  else if (k & type_or_decl_base::REFERENCE_TYPE)
1333  result = 11;
1334  else if (k & type_or_decl_base::POINTER_TO_MEMBER_TYPE)
1335  result = 12;
1336  else if (k & type_or_decl_base::ARRAY_TYPE)
1337  result = 13;
1338 
1339  return result;
1340  }
1341 
1342  /// "Less Than" operator for type IR nodes.
1343  ///
1344  /// This returns true iff the first operand is less than the second
1345  /// one.
1346  ///
1347  /// IR nodes are first sorted using their rank. Two IR node of the
1348  /// same rank are then sorted using their qualified name.
1349  ///
1350  /// @param f the first operand to consider.
1351  ///
1352  /// @param s the second operand to consider.
1353  bool
1354  operator()(const type_base& f, const type_base& s)
1355  {
1356  size_t rank_f = rank(f.kind()),
1357  rank_s = rank(s.kind());
1358 
1359  // If rank_f or rank_s is zero, it probably means there is a new
1360  // type IR kind that needs proper ranking.
1361  ABG_ASSERT(rank_f != 0 && rank_s != 0);
1362 
1363  bool result = false;
1364  if (rank_f < rank_s)
1365  result = true;
1366  else if (rank_f == rank_s)
1367  {
1368  type_topo_comp comp;
1369  result = comp(&f,&s);
1370  }
1371  return result;
1372  }
1373 
1374  /// "Less Than" operator for type IR nodes.
1375  ///
1376  /// This returns true iff the first operand is less than the second
1377  /// one.
1378  ///
1379  /// IR nodes are first sorted using their rank. Two IR node of the
1380  /// same rank are then sorted using their qualified name.
1381  ///
1382  /// @param f the first operand to consider.
1383  ///
1384  /// @param s the second operand to consider.
1385  bool
1386  operator()(const type_base* f, const type_base* s)
1387  {
1388  return operator()(*f, *s);
1389  }
1390 
1391  /// "Less Than" operator for type IR nodes.
1392  ///
1393  /// This returns true iff the first operand is less than the second
1394  /// one.
1395  ///
1396  /// IR nodes are first sorted using their rank. Two IR node of the
1397  /// same rank are then sorted using their qualified name.
1398  ///
1399  /// @param f the first operand to consider.
1400  ///
1401  /// @param s the second operand to consider.
1402  bool
1403  operator()(const type_base_sptr& f, const type_base_sptr& s)
1404  {
1405  return operator()(f.get(), s.get());
1406  }
1407 };//end struct sort_for_hash_functor
1408 
1409 /// Sort types before hashing (and then canonicalizing) them.
1410 ///
1411 /// @param begin an iterator pointing to the beginning of the sequence
1412 /// of types to sort.
1413 ///
1414 /// @param end an iterator pointing to the end of the sequence of
1415 /// types to sort.
1416 template <typename IteratorType>
1417 void
1419  IteratorType end)
1420 {
1421  sort_for_hash_functor comp;
1422  return std::stable_sort(begin, end, comp);
1423 }
1424 
1425 void
1426 sort_types_for_hash_computing_and_c14n(vector<type_base_sptr>& types);
1427 
1428 /// Compute the canonical type for all the IR types of the system.
1429 ///
1430 /// After invoking this function, the time it takes to compare two
1431 /// types of the IR is equivalent to the time it takes to compare
1432 /// their pointer value. That is faster than performing a structural
1433 /// (A.K.A. member-wise) comparison.
1434 ///
1435 /// Note that this function performs some sanity checks after* the
1436 /// canonicalization process. It ensures that at the end of the
1437 /// canonicalization process, all types have been canonicalized. This
1438 /// is important because the canonicalization algorithm sometimes
1439 /// clears some canonical types after having speculatively set them
1440 /// for performance purposes. At the end of the process however, all
1441 /// types must be canonicalized, and this function detects violations
1442 /// of that assertion.
1443 ///
1444 /// @tparam input_iterator the type of the input iterator of the @p
1445 /// beging and @p end.
1446 ///
1447 /// @tparam deref_lambda a lambda function which takes in parameter
1448 /// the input iterator of type @p input_iterator and dereferences it
1449 /// to return the type to canonicalize.
1450 ///
1451 /// @param begin an iterator pointing to the first type of the set of types
1452 /// to canonicalize.
1453 ///
1454 /// @param end an iterator pointing past-the-end (after the last type) of
1455 /// the set of types to canonicalize.
1456 ///
1457 /// @param deref a lambda function that knows how to dereference the
1458 /// iterator @p begin to return the type to canonicalize.
1459 template<typename input_iterator,
1460  typename deref_lambda>
1461 void
1462 canonicalize_types(const input_iterator& begin,
1463  const input_iterator& end,
1464  deref_lambda deref,
1465  bool do_log = false,
1466  bool show_stats = false)
1467 {
1468  if (begin == end)
1469  return;
1470 
1471  auto first_iter = begin;
1472  auto first = deref(first_iter);
1473  environment& env = const_cast<environment&>(first->get_environment());
1474 
1475  env.canonicalization_started(true);
1476 
1477  int i;
1478  input_iterator t;
1479  // First, let's compute the canonical type of this type.
1480  tools_utils::timer tmr;
1481  if (do_log)
1482  {
1483  std::cerr << "Canonicalizing types ...\n";
1484  tmr.start();
1485  }
1486 
1487  for (t = begin,i = 0; t != end; ++t, ++i)
1488  {
1489  if (do_log && show_stats)
1490  std::cerr << "#" << std::dec << i << " ";
1491 
1492  canonicalize(deref(t));
1493  }
1494 
1495  env.canonicalization_is_done(true);
1496 
1497  if (do_log)
1498  {
1499  tmr.stop();
1500  std::cerr << "Canonicalizing of types DONE in: " << tmr << "\n\n";
1501  tmr.start();
1502  }
1503 }
1504 
1505 /// Hash and canonicalize a sequence of types.
1506 ///
1507 /// Note that this function first sorts the types, then hashes them
1508 /// and then canonicalizes them.
1509 ///
1510 /// Operations must be done in that order to get predictable results.
1511 ///
1512 /// @param begin an iterator pointing to the first element of the
1513 /// sequence of types to hash and canonicalize.
1514 ///
1515 /// @param begin an iterator pointing past-the-end of the sequence of
1516 /// types to hash and canonicalize.
1517 ///
1518 /// @param deref this is a lambda that is used to dereference the
1519 /// types contained in the sequence referenced by iterators @p begin
1520 /// and @p end.
1521 template <typename IteratorType,
1522  typename deref_lambda>
1523 void
1524 hash_and_canonicalize_types(IteratorType begin,
1525  IteratorType end,
1526  deref_lambda deref,
1527  bool do_log = false,
1528  bool show_stats = false)
1529 {
1530  tools_utils::timer tmr;
1531  if (do_log)
1532  {
1533  std::cerr << "sorting types before canonicalization ... \n";
1534  tmr.start();
1535  }
1536 
1538 
1539  if (do_log)
1540  {
1541  tmr.stop();
1542  std::cerr << "sorted types for c14n in: " << tmr << "\n\n";
1543 
1544  std::cerr << "hashing types before c14n ...\n";
1545  tmr.start();
1546  }
1547 
1548  for (IteratorType t = begin; t != end; ++t)
1549  if (!peek_hash_value(*deref(t)))
1550  (*t)->hash_value();
1551 
1552  if (do_log)
1553  {
1554  tmr.stop();
1555  std::cerr << "hashed types in: " << tmr << "\n\n";
1556  }
1557 
1558  canonicalize_types(begin, end, deref, do_log, show_stats);
1559 }
1560 
1561 /// Sort and canonicalize a sequence of types.
1562 ///
1563 /// Note that this function does NOT hash the types. It thus assumes
1564 /// that the types are allready hashed.
1565 ///
1566 /// Operations must be done in that order (sorting and then
1567 /// canonicalizing) to get predictable results.
1568 ///
1569 /// @param begin an iterator pointing to the first element of the
1570 /// sequence of types to hash and canonicalize.
1571 ///
1572 /// @param begin an iterator pointing past-the-end of the sequence of
1573 /// types to hash and canonicalize.
1574 ///
1575 /// @param deref this is a lambda that is used to dereference the
1576 /// types contained in the sequence referenced by iterators @p begin
1577 /// and @p end.
1578 template <typename IteratorType,
1579  typename deref_lambda>
1580 void
1581 sort_and_canonicalize_types(IteratorType begin,
1582  IteratorType end,
1583  deref_lambda deref)
1584 {
1586  canonicalize_types(begin, end, deref);
1587 }
1588 
1589 // <class_or_union::priv definitions>
1591 {
1592  typedef_decl_wptr naming_typedef_;
1593  data_members data_members_;
1594  data_members static_data_members_;
1595  data_members non_static_data_members_;
1596  member_functions member_functions_;
1597  // A map that associates a linkage name to a member function.
1598  string_mem_fn_sptr_map_type mem_fns_map_;
1599  // A map that associates function signature strings to member
1600  // function.
1601  string_mem_fn_ptr_map_type signature_2_mem_fn_map_;
1602  member_function_templates member_function_templates_;
1603  member_class_templates member_class_templates_;
1604  bool is_printing_flat_representation_ = false;
1605  // The set of classes which layouts are currently being compared
1606  // against this one. This is to avoid endless loops.
1607  unordered_set<type_base*> comparing_class_layouts_;
1608  priv()
1609  {}
1610 
1613  : data_members_(data_mbrs),
1614  member_functions_(mbr_fns)
1615  {
1616  for (const auto& data_member: data_members_)
1617  if (get_member_is_static(data_member))
1618  static_data_members_.push_back(data_member);
1619  else
1620  non_static_data_members_.push_back(data_member);
1621  }
1622 
1623  /// Mark a pair of classes or unions as being currently compared
1624  /// using the class_or_union== operator.
1625  ///
1626  /// Note that this marking business is to avoid infinite loop when
1627  /// comparing a pair of classes or unions. If via the comparison of
1628  /// a data member or a member function a recursive re-comparison of
1629  /// the class or union is attempted, the marking process helps to
1630  /// detect that infinite loop possibility and avoid it.
1631  ///
1632  /// @param first the class or union (of the pair) to mark as being
1633  /// currently compared.
1634  ///
1635  /// @param second the second class or union (of the pair) to mark as
1636  /// being currently compared.
1637  void
1639  const class_or_union& second) const
1640  {
1641  const environment& env = first.get_environment();
1642 
1643  env.priv_->left_classes_being_compared_.insert(&first);
1644  env.priv_->right_classes_being_compared_.insert(&second);
1645  }
1646 
1647  /// Mark a pair of classes or unions as being currently compared
1648  /// using the class_or_union== operator.
1649  ///
1650  /// Note that this marking business is to avoid infinite loop when
1651  /// comparing a pair of classes or unions. If via the comparison of
1652  /// a data member or a member function a recursive re-comparison of
1653  /// the class or union is attempted, the marking process helps to
1654  /// detect that infinite loop possibility and avoid it.
1655  ///
1656  /// @param first the class or union (of the pair) to mark as being
1657  /// currently compared.
1658  ///
1659  /// @param second the second class or union (of the pair) to mark as
1660  /// being currently compared.
1661  void
1663  const class_or_union* second) const
1664  {mark_as_being_compared(*first, *second);}
1665 
1666  /// Mark a pair of classes or unions as being currently compared
1667  /// using the class_or_union== operator.
1668  ///
1669  /// Note that this marking business is to avoid infinite loop when
1670  /// comparing a pair of classes or unions. If via the comparison of
1671  /// a data member or a member function a recursive re-comparison of
1672  /// the class or union is attempted, the marking process helps to
1673  /// detect that infinite loop possibility and avoid it.
1674  ///
1675  /// @param first the class or union (of the pair) to mark as being
1676  /// currently compared.
1677  ///
1678  /// @param second the second class or union (of the pair) to mark as
1679  /// being currently compared.
1680  void
1681  mark_as_being_compared(const class_or_union_sptr& first,
1682  const class_or_union_sptr& second) const
1683  {mark_as_being_compared(*first, *second);}
1684 
1685  /// If a pair of class_or_union has been previously marked as
1686  /// being compared -- via an invocation of mark_as_being_compared()
1687  /// this method unmarks it. Otherwise is has no effect.
1688  ///
1689  /// This method is not thread safe because it uses the static data
1690  /// member classes_being_compared_. If you wish to use it in a
1691  /// multi-threaded environment you should probably protect the
1692  /// access to that static data member with a mutex or somesuch.
1693  ///
1694  /// @param first the first instance of class_or_union (of the pair)
1695  /// to unmark.
1696  ///
1697  /// @param second the second instance of class_or_union (of the
1698  /// pair) to unmark.
1699  void
1701  const class_or_union& second) const
1702  {
1703  const environment& env = first.get_environment();
1704 
1705  env.priv_->left_classes_being_compared_.erase(&first);
1706  env.priv_->right_classes_being_compared_.erase(&second);
1707  }
1708 
1709  /// If a pair of class_or_union has been previously marked as
1710  /// being compared -- via an invocation of mark_as_being_compared()
1711  /// this method unmarks it. Otherwise is has no effect.
1712  ///
1713  /// This method is not thread safe because it uses the static data
1714  /// member classes_being_compared_. If you wish to use it in a
1715  /// multi-threaded environment you should probably protect the
1716  /// access to that static data member with a mutex or somesuch.
1717  ///
1718  /// @param first the first instance of class_or_union (of the pair)
1719  /// to unmark.
1720  ///
1721  /// @param second the second instance of class_or_union (of the
1722  /// pair) to unmark.
1723  void
1725  const class_or_union* second) const
1726  {
1727  if (!first || !second)
1728  return;
1729  unmark_as_being_compared(*first, *second);
1730  }
1731 
1732  /// Test if a pair of class_or_union is being currently compared.
1733  ///
1734  ///@param first the first class or union (of the pair) to test for.
1735  ///
1736  ///@param second the second class or union (of the pair) to test for.
1737  ///
1738  /// @return true if the pair {@p first, @p second} is being
1739  /// compared, false otherwise.
1740  bool
1742  const class_or_union& second) const
1743  {
1744  const environment& env = first.get_environment();
1745 
1746  return (env.priv_->left_classes_being_compared_.count(&first)
1747  || env.priv_->right_classes_being_compared_.count(&second)
1748  || env.priv_->right_classes_being_compared_.count(&first)
1749  || env.priv_->left_classes_being_compared_.count(&second));
1750  }
1751 
1752  /// Test if a pair of class_or_union is being currently compared.
1753  ///
1754  ///@param first the first class or union (of the pair) to test for.
1755  ///
1756  ///@param second the second class or union (of the pair) to test for.
1757  ///
1758  /// @return true if the pair {@p first, @p second} is being
1759  /// compared, false otherwise.
1760  bool
1762  const class_or_union* second) const
1763  {
1764  if (first && second)
1765  return comparison_started(*first, *second);
1766  return false;
1767  }
1768 
1769  /// Set the 'is_printing_flat_representation_' boolean to true.
1770  ///
1771  /// That boolean marks the fact that the current @ref class_or_union
1772  /// (and its sub-types graph) is being walked for the purpose of
1773  /// printing its flat representation. This is useful to detect
1774  /// cycles in the graph and avoid endless loops.
1775  void
1777  {is_printing_flat_representation_ = true;}
1778 
1779  /// Set the 'is_printing_flat_representation_' boolean to false.
1780  ///
1781  /// That boolean marks the fact that the current @ref class_or_union
1782  /// (and its sub-types graph) is being walked for the purpose of
1783  /// printing its flat representation. This is useful to detect
1784  /// cycles in the graph and avoid endless loops.
1785  void
1787  {is_printing_flat_representation_ = false;}
1788 
1789  /// Getter of the 'is_printing_flat_representation_' boolean.
1790  ///
1791  /// That boolean marks the fact that the current @ref class_or_union
1792  /// (and its sub-types graph) is being walked for the purpose of
1793  /// printing its flat representation. This is useful to detect
1794  /// cycles in the graph and avoid endless loops.
1795  bool
1797  {return is_printing_flat_representation_;}
1798 }; // end struct class_or_union::priv
1799 
1800 // <function_type::priv definitions>
1801 
1802 /// The type of the private data of the @ref function_type type.
1804 {
1805  parameters parms_;
1806  type_base_wptr return_type_;
1807  interned_string cached_name_;
1808  interned_string internal_cached_name_;
1809  interned_string temp_internal_cached_name_;
1810  bool is_pretty_printing_ = false;
1811  priv()
1812  {}
1813 
1814  priv(const parameters& parms,
1815  type_base_sptr return_type)
1816  : parms_(parms),
1817  return_type_(return_type)
1818  {}
1819 
1820  priv(type_base_sptr return_type)
1821  : return_type_(return_type)
1822  {}
1823 
1824  /// Mark a given pair of @ref function_type as being compared.
1825  ///
1826  /// @param first the first @ref function_type of the pair being
1827  /// compared, to mark.
1828  ///
1829  /// @param second the second @ref function_type of the pair being
1830  /// compared, to mark.
1831  void
1833  const function_type& second) const
1834  {
1835  const environment& env = first.get_environment();
1836 
1837  env.priv_->left_fn_types_being_compared_.insert(&first);
1838  env.priv_->right_fn_types_being_compared_.insert(&second);
1839  }
1840 
1841  /// Mark a given pair of @ref function_type as being compared.
1842  ///
1843  /// @param first the first @ref function_type of the pair being
1844  /// compared, to mark.
1845  ///
1846  /// @param second the second @ref function_type of the pair being
1847  /// compared, to mark.
1848  void
1850  const function_type& second) const
1851  {
1852  const environment& env = first.get_environment();
1853 
1854  env.priv_->left_fn_types_being_compared_.erase(&first);
1855  env.priv_->right_fn_types_being_compared_.erase(&second);
1856  }
1857 
1858  /// Tests if a @ref function_type is currently being compared.
1859  ///
1860  /// @param type the function type to take into account.
1861  ///
1862  /// @return true if @p type is being compared.
1863  bool
1865  const function_type& second) const
1866  {
1867  const environment& env = first.get_environment();
1868 
1869  return (env.priv_->left_fn_types_being_compared_.count(&first)
1870  ||
1871  env.priv_->right_fn_types_being_compared_.count(&second));
1872  }
1873 
1874  /// Set the 'is_pretty_printing_' boolean to true.
1875  ///
1876  /// That boolean marks the fact that the current @ref function_type
1877  /// (and its sub-types graph) is being walked for the purpose of
1878  /// printing its flat representation. This is useful to detect
1879  /// cycles in the graph and avoid endless loops.
1880  void
1882  {is_pretty_printing_ = true;}
1883 
1884  /// Set the 'is_pretty_printing_' boolean to false.
1885  ///
1886  /// That boolean marks the fact that the current @ref function_type
1887  /// (and its sub-types graph) is being walked for the purpose of
1888  /// printing its flat representation. This is useful to detect
1889  /// cycles in the graph and avoid endless loops.
1890  void
1892  {is_pretty_printing_ = false;}
1893 
1894  /// Getter of the 'is_pretty_printing_' boolean.
1895  ///
1896  /// That boolean marks the fact that the current @ref function_type
1897  /// (and its sub-types graph) is being walked for the purpose of
1898  /// printing its flat representation. This is useful to detect
1899  /// cycles in the graph and avoid endless loops.
1900  bool
1902  {return is_pretty_printing_;}
1903 };// end struc function_type::priv
1904 
1905 // </function_type::priv definitions>
1906 
1907 size_t
1909 
1910 bool
1911 type_originates_from_corpus(type_base_sptr t, corpus_sptr& c);
1912 } // end namespace ir
1913 
1914 } // end namespace abigail
1915 
1916 #endif // __ABG_IR_PRIV_H__
bool operator()(const decl_base *f, const decl_base *s)
The "Less Than" comparison operator of this functor.
Definition: abg-ir-priv.h:1012
A type used to time various part of the libabigail system.
The type of the private data of the function_type type.
Definition: abg-ir-priv.h:1803
void set_hashing_state(hashing::hashing_state s) const
Setter of the hashing state of the current IR node.
Definition: abg-ir-priv.h:280
bool is_type(const type_or_decl_base &tod)
Test whether a declaration is a type.
Definition: abg-ir.cc:10807
The base type of all declarations.
Definition: abg-ir.h:1584
friend bool get_member_is_static(const decl_base &d)
Gets a flag saying if a class member is static or not.
Definition: abg-ir.cc:5575
type_base * peel_pointer_or_reference_type(const type_base *type, bool peel_qual_type)
Return the leaf underlying or pointed-to type node of a, pointer_type_def, reference_type_def or qual...
Definition: abg-ir.cc:7511
modifiers_type
The modifiers of the base types above. Several modifiers can be combined for a given base type...
Definition: abg-ir-priv.h:88
void mark_as_being_compared(const class_or_union_sptr &first, const class_or_union_sptr &second) const
Mark a pair of classes or unions as being currently compared using the class_or_union== operator...
Definition: abg-ir-priv.h:1681
bool canonicalization_is_done() const
Test if the canonicalization of types created out of the current environment is done.
Definition: abg-ir.cc:3531
bool has_artificial_or_natural_location(const type_base *t)
Test if a type has an artificial or natural location.
Definition: abg-ir-priv.h:1103
comparison_result
The result of structural comparison of type ABI artifacts.
Definition: abg-ir-priv.h:35
hash_t do_hash_value(const T &tod)
Compute the hash value of an IR node and return it.
Definition: abg-ir-priv.h:341
bool operator==(const real_type &) const
Equality operator for the real_type.
Definition: abg-ir.cc:16837
bool parse_real_type(const string &type_name, real_type &type)
Parse a real type from a string.
Definition: abg-ir.cc:16768
bool start()
Start the timer.
bool is_recursive_artefact() const
Getter of the property which flags the current artefact as being recursive or not.
Definition: abg-ir-priv.h:265
base_type
The possible base types of integral types. We might have forgotten many of these, so do not hesitate ...
Definition: abg-ir-priv.h:56
hash_t set_or_get_cached_hash_value(const T &tod)
Set the hash value of an IR node and return it.
Definition: abg-ir-priv.h:415
An abstraction helper for type declarations.
Definition: abg-ir.h:2002
unordered_map< uint64_t_pair_type, bool, uint64_t_pair_hash > type_comparison_result_type
A convenience typedef for a map which key is a pair of uint64_t and which value is a boolean...
Definition: abg-ir-priv.h:536
This is the abstraction of a set of translation units (themselves seen as bundles of unitary abi arte...
Definition: abg-corpus.h:24
const location & get_artificial_or_natural_location(const decl_base *decl)
Get the artificial location of a decl.
Definition: abg-ir.cc:10071
Definition of the private data of type_base.
Definition: abg-ir-priv.h:462
bool has_artificial_or_natural_location(const decl_base *d)
Test if a decl has an artificial or natural location.
Definition: abg-ir-priv.h:1094
weak_ptr< typedef_decl > typedef_decl_wptr
Convenience typedef for a weak pointer on a typedef_decl.
Definition: abg-fwd.h:170
size_t rank(enum type_or_decl_base::type_or_decl_kind k)
Return the rank of a given kind of IR node.
Definition: abg-ir-priv.h:1308
bool operator()(const decl_base_sptr &f, const decl_base_sptr &s)
The "Less Than" comparison operator of this functor.
Definition: abg-ir-priv.h:1070
void set_printing_flat_representation()
Set the 'is_printing_flat_representation_' boolean to true.
Definition: abg-ir-priv.h:1776
The abstraction of a qualified type.
Definition: abg-ir.h:2235
unordered_set< const function_type * > fn_set_type
A convenience typedef for a set of pointer to function_type.
Definition: abg-ir-priv.h:530
bool operator()(const type_base_sptr &f, const type_base_sptr &s)
"Less Than" operator for type IR nodes.
Definition: abg-ir-priv.h:1403
void is_recursive_artefact(bool f)
Setter of the property which flags the current artefact as being recursive or not.
Definition: abg-ir-priv.h:273
This is the abstraction of the set of relevant artefacts (types, variable declarations, functions, templates, etc) bundled together into a translation unit.
Definition: abg-ir.h:694
bool comparison_started(const class_or_union *first, const class_or_union *second) const
Test if a pair of class_or_union is being currently compared.
Definition: abg-ir-priv.h:1761
shared_ptr< scope_decl > global_scope_sptr
Convenience typedef for a shared pointer on a global_scope.
Definition: abg-ir.h:704
Abstracts the type of a class member function.
Definition: abg-ir.h:3505
A cycle has been detected in the graph on the current node node.
Definition: abg-hash.h:46
unordered_set< const class_or_union * > class_set_type
A convenience typedef for a set of pointer to class_or_union.
Definition: abg-ir-priv.h:527
void push_composite_type_comparison_operands(const type_base *left, const type_base *right)
Push a pair of operands on the stack of operands of the current type comparison, during type canonica...
Definition: abg-ir-priv.h:774
virtual const interned_string & get_name() const
Getter for the name of the current decl.
Definition: abg-ir.cc:4811
void mark_as_being_compared(const class_or_union &first, const class_or_union &second) const
Mark a pair of classes or unions as being currently compared using the class_or_union== operator...
Definition: abg-ir-priv.h:1638
void sort_types_for_hash_computing_and_c14n(IteratorType begin, IteratorType end)
Sort types before hashing (and then canonicalizing) them.
Definition: abg-ir-priv.h:1418
void unmark_as_being_compared(const function_type &first, const function_type &second) const
Mark a given pair of function_type as being compared.
Definition: abg-ir-priv.h:1849
hash_t combine_hashes(hash_t val1, hash_t val2)
Combine two hash values to produce a third hash value.
Definition: abg-hash.cc:172
const std::string & get_absolute_path() const
Get the concatenation of the build directory and the relative path of the translation unit...
Definition: abg-ir.cc:1341
void canonicalize_types(const input_iterator &begin, const input_iterator &end, deref_lambda deref, bool do_log=false, bool show_stats=false)
Compute the canonical type for all the IR types of the system.
Definition: abg-ir-priv.h:1462
unordered_map< string, method_decl_sptr > string_mem_fn_sptr_map_type
Convenience typedef.
Definition: abg-ir.h:4011
The private data of the environment type.
Definition: abg-ir-priv.h:539
void hash_and_canonicalize_types(IteratorType begin, IteratorType end, deref_lambda deref, bool do_log=false, bool show_stats=false)
Hash and canonicalize a sequence of types.
Definition: abg-ir-priv.h:1524
void force_set_hash_value(hash_t h)
Setter of the hashing value of the current IR node.
Definition: abg-ir-priv.h:317
void unset_printing_flat_representation()
Set the 'is_printing_flat_representation_' boolean to false.
Definition: abg-ir-priv.h:1786
real_type::modifiers_type operator~(real_type::modifiers_type l)
Bitwise one's complement operator for real_type::modifiers_type.
Definition: abg-ir.cc:16575
The private data of type_or_decl_base.
Definition: abg-ir-priv.h:187
enum type_or_decl_kind kind() const
Getter of the kind of the IR node.
Definition: abg-ir-priv.h:243
corpus::origin operator&=(corpus::origin &l, corpus::origin r)
Bitwise &= operator for the corpus::origin type.
Definition: abg-corpus.cc:1816
bool is_non_canonicalized_type(const type_base *t)
Test if a given type is allowed to be non canonicalized.
Definition: abg-ir.cc:28634
Simplified implementation of std::optional just enough to be used as a replacement for our purposes a...
weak_ptr< type_base > type_base_wptr
Convenience typedef for a weak pointer on a type_base.
Definition: abg-fwd.h:128
const environment & get_environment() const
Getter of the environment of the current ABI artifact.
Definition: abg-ir.cc:4202
A functor to sort decls somewhat topologically. That is, types are sorted in a way that makes the one...
Definition: abg-ir-priv.h:980
bool is_unique_type(const type_base_sptr &t)
Test if a type is unique in the entire environment.
Definition: abg-ir.cc:28670
Private type to hold private members of translation_unit.
Definition: abg-ir-priv.h:151
void kind(enum type_or_decl_kind k)
Setter of the kind of the IR node.
Definition: abg-ir-priv.h:250
typedef_decl_sptr is_typedef(const type_or_decl_base_sptr t)
Test whether a type is a typedef.
Definition: abg-ir.cc:11011
Toplevel namespace for libabigail.
A functor to sort types somewhat topologically. That is, types are sorted in a way that makes the one...
Definition: abg-ir-priv.h:1086
bool has_artificial_or_natural_location(const decl_base *d)
Test if a decl has an artificial or natural location.
Definition: abg-ir-priv.h:988
No hashing has been done/started.
Definition: abg-hash.h:27
decl_base * is_decl(const type_or_decl_base *d)
Test if an ABI artifact is a declaration.
Definition: abg-ir.cc:10747
std::vector< parameter_sptr > parameters
Convenience typedef for a vector of parameter_sptr.
Definition: abg-ir.h:3432
size_t get_canonical_type_index(const type_base &t)
Getter of the canonical type index of a given type.
Definition: abg-ir.cc:345
bool operator()(const type_base &f, const type_base &s)
"Less Than" operator for type IR nodes.
Definition: abg-ir-priv.h:1354
hash_t peek_hash_value(const type_or_decl_base &artefact)
Get the hash value associated to an IR node.
Definition: abg-ir.cc:28607
modifiers_type get_modifiers() const
Getter of the modifiers bitmap of the real_type.
Definition: abg-ir.cc:16820
bool operator()(const type_base_sptr &f, const type_base_sptr &s)
The "Less Than" comparison operator of this functor.
Definition: abg-ir-priv.h:1118
void mark_as_being_compared(const function_type &first, const function_type &second) const
Mark a given pair of function_type as being compared.
Definition: abg-ir-priv.h:1832
bool is_ptr_ref_or_qual_type(const type_base *t)
Helper to detect if a type is either a reference, a pointer, or a qualified type. ...
Definition: abg-ir.cc:3396
const interned_string & get_cached_pretty_representation(bool internal=false) const
Get the pretty representation of the current type.
Definition: abg-ir.cc:16413
The base type of class_decl and union_decl.
Definition: abg-ir.h:3976
The source location of a token.
Definition: abg-ir.h:306
void mark_as_being_compared(const class_or_union *first, const class_or_union *second) const
Mark a pair of classes or unions as being currently compared using the class_or_union== operator...
Definition: abg-ir-priv.h:1662
This is a type that aggregates maps of all the kinds of types that are supported by libabigail...
Definition: abg-ir.h:601
The "bool" base type in C++ or "_Bool" in C11.
Definition: abg-ir-priv.h:63
This is an abstraction of the set of resources necessary to manage several aspects of the internal re...
Definition: abg-ir.h:147
vector< method_decl_sptr > member_functions
Convenience typedef.
Definition: abg-ir.h:4008
weak_ptr< corpus > corpus_wptr
Convenience typedef for a weak pointer to a corpus.
Definition: abg-fwd.h:131
void set_is_pretty_printing()
Set the 'is_pretty_printing_' boolean to true.
Definition: abg-ir-priv.h:1881
type_base_sptr canonicalize(type_base_sptr t, bool do_log, bool show_stats)
Compute the canonical type of a given type.
Definition: abg-ir.cc:16251
#define ABG_ASSERT(cond)
This is a wrapper around the 'assert' glibc call. It allows for its argument to have side effects...
Definition: abg-fwd.h:1743
std::unordered_map< string, std::vector< type_base_sptr > > canonical_types_map_type
A convenience typedef for a map of canonical types. The key is the pretty representation string of a ...
Definition: abg-ir.h:158
void cache_type_comparison_result(T &first, T &second, bool r)
Cache the result of comparing two sub-types.
Definition: abg-ir-priv.h:711
bool is_pretty_printing() const
Getter of the 'is_pretty_printing_' boolean.
Definition: abg-ir-priv.h:1901
bool type_originates_from_corpus(type_base_sptr t, corpus_sptr &c)
Test if a type originates from a corpus.
Definition: abg-ir.cc:378
void sort_and_canonicalize_types(IteratorType begin, IteratorType end, deref_lambda deref)
Sort and canonicalize a sequence of types.
Definition: abg-ir-priv.h:1581
abg_compat::optional< uint64_t > hash_t
The abstraction for an 8 bytes hash value.
Definition: abg-ir.h:105
bool is_type_comparison_cached(T &first, T &second, bool &r)
Retrieve the result of comparing two sub-types from the cache, if it was previously stored...
Definition: abg-ir-priv.h:743
type_or_decl_kind
This is a bitmap type which instance is meant to contain the runtime type of a given ABI artifact...
Definition: abg-ir.h:1417
void set_modifiers(modifiers_type)
Setter of the modifiers bitmap of the real_type.
Definition: abg-ir.cc:16827
corpus::origin operator|(corpus::origin l, corpus::origin r)
Bitwise | operator for the corpus::origin type.
Definition: abg-corpus.cc:1774
bool operator()(const type_base *f, const type_base *s)
"Less Than" operator for type IR nodes.
Definition: abg-ir-priv.h:1386
bool compare_using_locations(const decl_base *f, const decl_base *s)
Compare decls using their locations.
Definition: abg-ir.cc:3413
priv(const environment &e, enum type_or_decl_kind k=ABSTRACT_TYPE_OR_DECL)
Constructor of the type_or_decl_base::priv private type.
Definition: abg-ir-priv.h:227
void unset_is_pretty_printing()
Set the 'is_pretty_printing_' boolean to false.
Definition: abg-ir-priv.h:1891
The aray size type used by Clang.
Definition: abg-ir-priv.h:79
const interned_string & get_cached_pretty_representation(bool internal=false) const
Get the pretty representation of the current decl.
Definition: abg-ir.cc:4894
bool comparison_started(const function_type &first, const function_type &second) const
Tests if a function_type is currently being compared.
Definition: abg-ir-priv.h:1864
qualified_type_def * is_qualified_type(const type_or_decl_base *t)
Test whether a type is a reference_type_def.
Definition: abg-ir.cc:11838
Hashing a sub-type while hashing another type.
Definition: abg-hash.h:55
const translation_unit * get_translation_unit() const
Get the translation_unit this ABI artifact belongs to.
Definition: abg-ir.cc:4295
language
The language of the translation unit.
Definition: abg-ir.h:707
uint64_t operator()(const std::pair< uint64_t, uint64_t > &p) const
Hashing function for a pair of uint64_t.
Definition: abg-ir-priv.h:511
corpus::origin operator|=(corpus::origin &l, corpus::origin r)
Bitwise |= operator for the corpus::origin type.
Definition: abg-corpus.cc:1788
void unmark_as_being_compared(const class_or_union *first, const class_or_union *second) const
If a pair of class_or_union has been previously marked as being compared – via an invocation of mark...
Definition: abg-ir-priv.h:1724
bool allow_type_comparison_results_caching() const
Check whether if caching of the sub-types comparison results during the invocation of the equal overl...
Definition: abg-ir-priv.h:687
unordered_map< string, method_decl * > string_mem_fn_ptr_map_type
Convenience typedef.
Definition: abg-ir.h:4010
std::pair< uint64_t, uint64_t > uint64_t_pair_type
A convenience typedef for a pair of uint64_t which is initially intended to store a pair of pointer v...
Definition: abg-ir-priv.h:520
unordered_set< uint64_t_pair_type, uint64_t_pair_hash > uint64_t_pairs_set_type
A convenience typedef for a set of uint64_t_pair.
Definition: abg-ir-priv.h:524
The abstraction of an interned string.
bool get_is_anonymous() const
Test if the current declaration is anonymous.
Definition: abg-ir.cc:4668
bool operator()(const type_base *f, const type_base *s)
The "Less Than" comparison operator of this functor.
Definition: abg-ir-priv.h:1130
bool canonicalization_started() const
Getter of a flag saying if the canonicalization process has started or not.
Definition: abg-ir.cc:3558
hashing::hashing_state get_hashing_state() const
Getter the hashing state of the current IR node.
Definition: abg-ir-priv.h:257
void clear_type_comparison_results_cache()
Clear the cache type comparison results.
Definition: abg-ir-priv.h:761
Hashing of given IR node started and is now done. If an ABI artifact is in this state, then it must have an hash value available and should be get by peek_hash_value or type_or_decl_base::hash_value().
Definition: abg-hash.h:61
base_type get_base_type() const
Getter of the base type of the real_type.
Definition: abg-ir.cc:16813
The interned string pool.
type_base_sptr peel_typedef_pointer_or_reference_type(const type_base_sptr type)
Return the leaf underlying or pointed-to type node of a typedef_decl, pointer_type_def, reference_type_def, or array_type_def node.
Definition: abg-ir.cc:7409
void allow_type_comparison_results_caching(bool f)
Allow caching of the sub-types comparison results during the invocation of the equal overloads for cl...
Definition: abg-ir-priv.h:676
This type abstracts the configuration information of the library.
Definition: abg-config.h:17
origin get_origin() const
Getter for the origin of the corpus.
Definition: abg-corpus.cc:930
string to_string(bool internal=false) const
Return the string representation of the current instance of real_type.
Definition: abg-ir.cc:16850
vector< var_decl_sptr > data_members
Convenience typedef.
Definition: abg-ir.h:4007
Functor used to sort types before hashing them.
Definition: abg-ir-priv.h:1295
bool is_printing_flat_representation() const
Getter of the 'is_printing_flat_representation_' boolean.
Definition: abg-ir-priv.h:1796
const corpus * get_corpus() const
Get the corpus this ABI artifact belongs to.
Definition: abg-ir.cc:4270
corpus::origin operator&(corpus::origin l, corpus::origin r)
Bitwise & operator for the corpus::origin type.
Definition: abg-corpus.cc:1802
The hashing functor for a pair of uint64_t.
Definition: abg-ir-priv.h:505
void unmark_as_being_compared(const class_or_union &first, const class_or_union &second) const
If a pair of class_or_union has been previously marked as being compared – via an invocation of mark...
Definition: abg-ir-priv.h:1700
bool comparison_started(const class_or_union &first, const class_or_union &second) const
Test if a pair of class_or_union is being currently compared.
Definition: abg-ir-priv.h:1741
void pop_composite_type_comparison_operands(const type_base *left, const type_base *right)
Pop a pair of operands from the stack of operands to the current type comparison. ...
Definition: abg-ir-priv.h:797
The internal representation of an integral type.
Definition: abg-ir-priv.h:48
bool type_is_suitable_for_hash_computing(const type_base &)
Test if we should attempt to compute a hash value for a given type.
Definition: abg-ir.cc:15825
void set_hash_value(hash_t h)
Setter of the hashing value of the current IR node.
Definition: abg-ir-priv.h:292
unsigned get_value() const
Get the value of the location.
Definition: abg-ir.h:395
method_type_sptr is_method_type(const type_or_decl_base_sptr &t)
Test whether a type is a method_type.
Definition: abg-ir.cc:11888
hashing_state
Enumeration of the different hashing states of an IR node being hashed.
Definition: abg-hash.h:24
bool has_artificial_or_natural_location(const type_base *t)
Test if a type has an artificial or natural location.
Definition: abg-ir-priv.h:997
Abstraction of a function type.
Definition: abg-ir.h:3419
enum type_or_decl_kind kind() const
Getter for the "kind" property of type_or_decl_base type.
Definition: abg-ir.cc:4114
hash_t hash(uint64_t v, uint64_t seed)
Hash an integer value and combine it with a hash previously computed.
Definition: abg-hash.cc:196
The entry point to manage locations.
Definition: abg-ir.h:448
bool stop()
Stop the timer.
real_type()
Default constructor of the real_type.
Definition: abg-ir.cc:16783