Handle per translation unit and per corpus types maps
authorDodji Seketeli <dodji@redhat.com>
Mon, 2 Jan 2017 21:40:39 +0000 (22:40 +0100)
committerDodji Seketeli <dodji@redhat.com>
Thu, 5 Jan 2017 11:18:33 +0000 (12:18 +0100)
Today, whenever a type is added to its scope, a map that associates
the qualified type name to the type is updated.  There is only one
such map in a given ABI corpus.

So whenever a type is looked up from its name, it's that per-corpus
type map that is used.

This setup makes libabigail type lookup be tailored only for binaries
that respect the One Definition Rule of C++[1] (aka ODR) which
basically says that there should be only one type of a given name in
an ABI corpus.

It turns out that many binaries, especically C binaries, don't respect
the ODR.  So a type "struct foo" can be defined in a file a.c and
another *different* type "struct foo" can also be defined in b.c.
What a useful and safe feature! Not.

For those binaries, just having one type map doesn't work.  We need to
have one type map per translation unit, and one map per-corpus map.

This is the strategy implemented by this patch.

With this patch, whenever a type is added to its scope, a
per translation unit type map is updated.  The per corpus map is
updated as well.  If there are more than one type of a given name, the
entry in the per corpus type map for that type is left empty.

Type lookup now potentially becomes a two phases lookup.  Whenever a
type is looked up from its name, the per corpus type map is looked at
first.  If the type is not in that per corpus type map, then the per
translation unit type maps are lookup up, in sequence.

The patch thus re-visits the type maps updating and lookup routines to
adapt them to the new scheme.  The patch also updates the clients of
the type map updating and lookup code.

Note that this patch is part of a series of patches which aims to move
libabigails away from its ODR-centric organization to make it work
well also on binary where the ODR is not relevant.  As such, the patch
doesn't assure that "make check" passes.  To have "make check" pass,
you need to have all the patches of the series applied.

[1]: https://en.wikipedia.org/wiki/One_Definition_Rule

* include/abg-fwd.h (lookup_type_in_corpus): Remove.  This is to
be replaced by the new lookup_type below.
(lookup_{basic, class, union, enum, typedef, qualified, pointer,
reference, array, function, class_or_typedef,
class_typedef_or_enum}_type):
(lookup_class_type_through_scopes, lookup_type)
(lookup_type_through_scopes, lookup_or_synthesize_fn_type)
* src/abg-ir-priv.h (struct translation_unit::priv):  Move this
private type here, from abg-ir.h.
(synthesize_type_from_translation_unit): Declare new functions.
* include/abg-ir.h (class type_maps): Define new type.
(translation_unit::get_function_types): Remove.
(translation_unit::get_types): Now return a type_maps.
(translation_unit::get_live_fn_types): Declare new type.
(class decl_base): Make canonicalize be a friend of this class.
* src/abg-ir.cc (struct translation_unit::priv): Move this to
abg-ir-priv.h
(struct type_maps::priv): Define new type.
(type_maps::{basic, class, union, enum, typedef, qualified,
pointer, reference, array, function}_types): Define new accessors.
(translation_unit::bind_function_type_life_time): Adjust.
(translation_unit::get_function_types): Remove accessor.
(translation_unit::get_types, get_live_fn_types): Define new
accessors.
(lookup_type_in_translation_unit)
(lookup_class_type_in_translation_unit)
(lookup_function_type_in_translation_unit)
(synthesize_type_from_translation_unit)
(synthesize_function_type_from_translation_unit)
(lookup_class_type_in_translation_unit) Remove function
definitions.
(lookup_type_in_map): Define function template.
(lookup_{basic, class, union, typedef, class_or_typedef,
class_typedef_or_enum, qualified, pointer, reference, array,
function}_type): Define functions.
(lookup_function_type, lookup_type_through_scopes)
(lookup_class_type_through_scopes)
(lookup_basic_type_through_translation_units)
(lookup_union_type_through_translation_units)
(lookup_enum_type_through_translation_units)
(lookup_class_type_through_translation_units)
(lookup_typedef_type_through_translation_units)
(lookup_qualified_type_through_translation_units)
(lookup_pointer_type_through_translation_units)
(lookup_reference_type_through_translation_units)
(lookup_array_type_through_translation_units)
(lookup_function_type_through_translation_units)
(lookup_type_through_translation_units)
(lookup_or_synthesize_fn_type, lookup_type): Likewise.
(maybe_update_types_lookup_map)
(maybe_update_types_lookup_map<class_decl>)
(maybe_update_types_lookup_map<function_type>): Define function
template, specilizations and functions.
(synthesize_type_from_translation_unit)
(synthesize_function_type_from_translation_unit): Define
functions.
* include/abg-corpus.h (corpus::get_types): Declare new accessor.
* src/abg-corpus.cc (corpus::priv::get_types): Define new
accessor.
(corpus::get_types): Likewise.
(lookup_type_in_corpus, lookup_class_type_in_corpus)
(lookup_type_in_corpus, lookup_function_type_in_corpus)
(maybe_update_types_lookup_map)
(maybe_update_types_lookup_map<class_decl>)
(maybe_update_types_lookup_map<function_type>): Remove.
(lookup_{basic, class, union, enum, typedef, qualified, pointer,
reference, array, function, class_or_typedef,
class_typedef_or_enum}_type): Likewise.
* src/abg-corpus-priv.h (corpus::priv::{basic, class, union,
typedef, qualified, pointer, reference, array, function}_types):
Remove these data members.
(corpus::priv::get_scopes): Remove member function.
(corpus::priv::get_{basic, class, union, enum, typedef, qualified,
pointer, reference, array, function}_types): Remove member
function declarations.
(corpus::priv::types_): New data member.
(corpus::priv::get_types): Declare new member function.
(lookup_{basic, class, enum, typedef, class_or_typedef, qualified,
pointer, reference, array, function}_type): Declare new functions.
* src/abg-dwarf-reader.cc
(read_context::resolve_declaration_only_classes)
(build_translation_unit_and_add_to_ir): Adjust use of
lookup_class_type.
* src/abg-reader.cc (read_context::type_is_from_translation_unit):
Adjust to the use of lookup_function_type_in_translation_unit that
got renamed into lookup_function_type.
* src/abg-writer.cc (type_ptr_cmp::operator()): New operator
implementation.
(read_context::sort_type): Add new overloads.
(write_translation_unit): Adjust to get the function types from
the new translation_unit::get_live_fn_types and sort them.
* tools/abicompat.cc (perform_compat_check_in_weak_mode): Adjust
to use the new lookup_or_synthesize_fn_type, in lieu of
lookup_function_type_in_corpus.  Adjust to use lookup_type in lieu
of lookup_type_in_corpus.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
include/abg-corpus.h
include/abg-fwd.h
include/abg-ir.h
src/abg-corpus-priv.h
src/abg-corpus.cc
src/abg-dwarf-reader.cc
src/abg-ir-priv.h
src/abg-ir.cc
src/abg-reader.cc
src/abg-writer.cc
tools/abicompat.cc

index 97ebc8dd5bdfcc7f4326fa8af159e4e2251536e5..54279e488113fa95fc6e5c2ffca530d56c627696 100644 (file)
@@ -100,6 +100,12 @@ public:
   void
   drop_translation_units();
 
+  type_maps&
+  get_types();
+
+  const type_maps&
+  get_types() const;
+
   origin
   get_origin() const;
 
index a261efcf4e37a60f485af435302a546cce7fd6bd..efa6c19864db110688b4e71bd17348624a4551c3 100644 (file)
@@ -836,57 +836,197 @@ fqn_to_components(const std::string&,
 string
 components_to_type_name(const std::list<string>&);
 
-const shared_ptr<decl_base>
-lookup_type_in_corpus(const string&, const corpus&);
+type_decl_sptr
+lookup_basic_type(const type_decl&, const translation_unit&);
+
+type_decl_sptr
+lookup_basic_type(const interned_string&, const translation_unit&);
+
+type_decl_sptr
+lookup_basic_type(const string&, const translation_unit&);
+
+type_decl_sptr
+lookup_basic_type(const type_decl&, const corpus&);;
+
+type_decl_sptr
+lookup_basic_type(const string&, const corpus&);
+
+type_decl_sptr
+lookup_basic_type(const interned_string&, const corpus&);
+
+class_decl_sptr
+lookup_class_type(const class_decl&, const translation_unit&);
+
+class_decl_sptr
+lookup_class_type(const interned_string&, const translation_unit&);
+
+class_decl_sptr
+lookup_class_type(const string&, const translation_unit&);
+
+class_decl_sptr
+lookup_class_type(const class_decl&, const corpus&);
+
+class_decl_sptr
+lookup_class_type(const interned_string&, const corpus&);
 
-const shared_ptr<class_decl>
-lookup_class_type_in_corpus(const string&, const corpus&);
+class_decl_sptr
+lookup_class_type(const string&, const corpus&);
+
+class_decl_sptr
+lookup_class_type_through_scopes(const std::list<string>&,
+                                const translation_unit&);
 
-const shared_ptr<function_type>
-lookup_function_type_in_corpus(const function_type&, const corpus&);
+union_decl_sptr
+lookup_union_type(const interned_string&, const translation_unit&);
+
+union_decl_sptr
+lookup_union_type(const interned_string&, const corpus&);
+
+union_decl_sptr
+lookup_union_type(const string&, const corpus&);
+
+enum_type_decl_sptr
+lookup_enum_type(const enum_type_decl&, const translation_unit&);
+
+enum_type_decl_sptr
+lookup_enum_type(const string&, const translation_unit&);
+
+enum_type_decl_sptr
+lookup_enum_type(const enum_type_decl&, const corpus&);
+
+enum_type_decl_sptr
+lookup_enum_type(const string&, const corpus&);
+
+enum_type_decl_sptr
+lookup_enum_type(const interned_string&, const corpus&);
+
+typedef_decl_sptr
+lookup_typedef_type(const typedef_decl&, const translation_unit&);
+
+typedef_decl_sptr
+lookup_typedef_type(const typedef_decl&, const corpus&);
+
+typedef_decl_sptr
+lookup_typedef_type(const interned_string&, const corpus&);
+
+typedef_decl_sptr
+lookup_typedef_type(const string&, const corpus&);
 
 type_base_sptr
-lookup_type_through_scopes(const std::list<string>&,
-                          const translation_unit&);
+lookup_class_or_typedef_type(const string&, const translation_unit&);
 
-const shared_ptr<decl_base>
-lookup_type_in_translation_unit(const std::list<string>&,
-                               const translation_unit&);
-const shared_ptr<decl_base>
-lookup_type_in_translation_unit(const string&,
-                               const translation_unit&);
+type_base_sptr
+lookup_class_typedef_or_enum_type(const string&, const translation_unit&);
 
-const shared_ptr<class_decl>
-lookup_class_type_in_translation_unit(const std::list<string>& fqn,
-                                     const translation_unit& tu);
+type_base_sptr
+lookup_class_or_typedef_type(const string&, const corpus&);
 
-const shared_ptr<class_decl>
-lookup_class_type_in_translation_unit(const string& fqn,
-                                     const translation_unit& tu);
+type_base_sptr
+lookup_class_typedef_or_enum_type(const string&, const corpus&);
 
-const shared_ptr<type_base>
-lookup_type_in_translation_unit(const shared_ptr<type_base>,
-                               const translation_unit&);
+qualified_type_def_sptr
+lookup_qualified_type(const qualified_type_def&, const translation_unit&);
 
-shared_ptr<function_type>
-lookup_function_type_in_translation_unit(const function_type&,
-                                        const translation_unit&);
+qualified_type_def_sptr
+lookup_qualified_type(const string&, const translation_unit&);
 
+qualified_type_def_sptr
+lookup_qualified_type(const qualified_type_def&, const corpus&);
 
+qualified_type_def_sptr
+lookup_qualified_type(const interned_string&, const corpus&);
+
+pointer_type_def_sptr
+lookup_pointer_type(const pointer_type_def&, const translation_unit&);
+
+pointer_type_def_sptr
+lookup_pointer_type(const string&, const translation_unit&);
+
+pointer_type_def_sptr
+lookup_pointer_type(const pointer_type_def&, const corpus&);
+
+pointer_type_def_sptr
+lookup_pointer_type(const interned_string&, const corpus&);
+
+const reference_type_def_sptr
+lookup_reference_type(const reference_type_def&, const translation_unit&);
+
+const reference_type_def_sptr
+lookup_reference_type(const string&, const translation_unit&);
+
+reference_type_def_sptr
+lookup_reference_type(const reference_type_def&, const corpus&);
+
+reference_type_def_sptr
+lookup_reference_type(const interned_string&, const corpus&);
+
+array_type_def_sptr
+lookup_array_type(const array_type_def&, const translation_unit&);
+
+array_type_def_sptr
+lookup_array_type(const string&, const translation_unit&);
+
+array_type_def_sptr
+lookup_array_type(const array_type_def&, const corpus&);
+
+array_type_def_sptr
+lookup_array_type(const interned_string&, const corpus&);
+
+function_type_sptr
+lookup_function_type(const string&,
+                    const translation_unit&);
+
+function_type_sptr
+lookup_function_type(const interned_string&,
+                    const translation_unit&);
 
-shared_ptr<function_type>
-lookup_function_type_in_translation_unit(const shared_ptr<function_type>&,
-                                        const translation_unit&);
+function_type_sptr
+lookup_function_type(const function_type&,
+                    const translation_unit&);
+
+function_type_sptr
+lookup_function_type(const function_type_sptr&,
+                    const translation_unit&);
+
+function_type_sptr
+lookup_function_type(const function_type&, const corpus&);
+
+function_type_sptr
+lookup_function_type(const function_type_sptr&, const corpus&);
+
+function_type_sptr
+lookup_function_type(const function_type&, const corpus&);
+
+function_type_sptr
+lookup_function_type(const interned_string&, const corpus&);
+
+type_base_sptr
+lookup_type(const string&, const translation_unit&);
+
+const type_base_sptr
+lookup_type(const type_base_sptr, const translation_unit&);
+
+type_base_sptr
+lookup_type(const interned_string&, const corpus&);
+
+type_base_sptr
+lookup_type(const type_base&, const corpus&);
+
+type_base_sptr
+lookup_type(const type_base_sptr&, const corpus&);
+
+type_base_sptr
+lookup_type_through_scopes(const std::list<string>&,
+                          const translation_unit&);
+
+function_type_sptr
+lookup_or_synthesize_fn_type(const function_type_sptr&,
+                            const corpus&);
 
-shared_ptr<function_type>
-lookup_function_type_in_corpus(const shared_ptr<function_type>&,
-                              corpus&);
 type_base_sptr
-synthesize_type_from_translation_unit(const type_base_sptr& type,
-                                     translation_unit& tu);
+synthesize_type_from_translation_unit(const type_base_sptr&,
+                                     translation_unit&);
 
-shared_ptr<type_base>
-lookup_type_in_corpus(const shared_ptr<type_base>&, corpus&);
 function_type_sptr
 synthesize_function_type_from_translation_unit(const function_type&,
                                               translation_unit&);
index d3cd997cefe5a24e15c240035cf0d2ef2ff74d9f..b046db45d75cf3dc9438d703f78ee834c7932454 100644 (file)
@@ -328,6 +328,83 @@ typedef unordered_map<interned_string,
                      hash_interned_string>
 istring_type_or_decl_base_sptr_map_type;
 
+/// This is a type that aggregates maps of all the kinds of types that
+/// are supported by libabigail.
+///
+/// For instance, the type_maps contains a map of string to basic
+/// type, a map of string to class type, a map of string to union
+/// types, etc.
+class type_maps
+{
+  struct priv;
+  typedef shared_ptr<priv> priv_sptr;
+  priv_sptr priv_;
+
+public:
+
+  type_maps();
+
+  const istring_type_base_wptr_map_type&
+  basic_types() const;
+
+  istring_type_base_wptr_map_type&
+  basic_types();
+
+  const istring_type_base_wptr_map_type&
+  class_types() const;
+
+  istring_type_base_wptr_map_type&
+  class_types();
+
+  istring_type_base_wptr_map_type&
+  union_types();
+
+  const istring_type_base_wptr_map_type&
+  union_types() const;
+
+  istring_type_base_wptr_map_type&
+  enum_types();
+
+  const istring_type_base_wptr_map_type&
+  enum_types() const;
+
+  istring_type_base_wptr_map_type&
+  typedef_types();
+
+  const istring_type_base_wptr_map_type&
+  typedef_types() const;
+
+  istring_type_base_wptr_map_type&
+  qualified_types();
+
+  const istring_type_base_wptr_map_type&
+  qualified_types() const;
+
+  istring_type_base_wptr_map_type&
+  pointer_types();
+
+  const istring_type_base_wptr_map_type&
+  pointer_types() const;
+
+  istring_type_base_wptr_map_type&
+  reference_types();
+
+  const istring_type_base_wptr_map_type&
+  reference_types() const;
+
+  istring_type_base_wptr_map_type&
+  array_types();
+
+  const istring_type_base_wptr_map_type&
+  array_types() const;
+
+  istring_type_base_wptr_map_type&
+  function_types();
+
+  const istring_type_base_wptr_map_type&
+  function_types() const;
+}; // end class type_maps;
+
 /// This is the abstraction of the set of relevant artefacts (types,
 /// variable declarations, functions, templates, etc) bundled together
 /// into a translation unit.
@@ -416,15 +493,15 @@ public:
   const global_scope_sptr
   get_global_scope() const;
 
-  const function_types_type
-  get_function_types() const;
-
-  const string_type_base_wptr_map_type&
+  const type_maps&
   get_types() const;
 
-  string_type_base_wptr_map_type&
+  type_maps&
   get_types();
 
+  const vector<function_type_sptr>&
+  get_live_fn_types() const;
+
   location_manager&
   get_loc_mgr();
 
@@ -1129,6 +1206,9 @@ public:
   void
   set_visibility(visibility v);
 
+  friend type_base_sptr
+  canonicalize(type_base_sptr);
+
   friend bool
   equals(const decl_base&, const decl_base&, change_kind*);
 
index b7e35e9b3a1647d551777aff49643e9a2f94ebe0..120aaca0b2aeeffc4517329934d77b7a193ca145 100644 (file)
@@ -702,19 +702,18 @@ struct corpus::priv
   elf_symbols                                  sorted_undefined_fun_symbols;
   elf_symbols                                  unrefed_fun_symbols;
   elf_symbols                                  unrefed_var_symbols;
-  // A scope (namespace of class) is shared among all translation
-  // units of a given corpus.
-  //mutable istring_scopes_sptr_map_type               scopes_;
-  mutable istring_type_base_wptr_map_type      basic_types_;
-  mutable istring_type_base_wptr_map_type      class_types_;
-  mutable istring_type_base_wptr_map_type      union_types_;
-  mutable istring_type_base_wptr_map_type      enum_types_;
-  mutable istring_type_base_wptr_map_type      typedef_types_;
-  mutable istring_type_base_wptr_map_type      qualified_types_;
-  mutable istring_type_base_wptr_map_type      pointer_types_;
-  mutable istring_type_base_wptr_map_type      reference_types_;
-  mutable istring_type_base_wptr_map_type      array_types_;
-  mutable istring_type_base_wptr_map_type      function_types_;
+  // The type maps contained in this data member are populated if the
+  // corpus follows the One Definition Rule and thus if there is only
+  // one copy of a type with a given name, per corpus. Otherwise, if
+  // there can be several *different* types with the same name, then
+  // the type maps are all empty.  The types are then maintained in
+  // type maps that are in each translation units.
+  //
+  // In other words, to lookup a given type, if the corpus allows the
+  // One Definition Rule, then lookup can be done by looking into this
+  // data member.  Otherwise, the lookup must be made by looking into
+  // the type maps of each translation unit.
+  type_maps                                    types_;
 
 private:
   priv();
@@ -730,133 +729,11 @@ public:
   void
   build_unreferenced_symbols_tables();
 
-  // istring_scope_sptr_map_type&
-  // get_scopes()
-  // {return scopes_;}
-
-  // istring_scope_sptr_map_type&
-  // get_scopes() const
-  // {return const_cast<priv*>(this)->get_scopes();}
-
-  /// Getter for the map that associates the name of a basic type to
-  /// the @ref type_decl_sptr that represents that type.
-  istring_type_base_wptr_map_type&
-  get_basic_types()
-  {return basic_types_;}
-
-  /// Getter for the map that associates the name of a basic type to
-  /// the @ref type_decl_sptr that represents that type
-  const istring_type_base_wptr_map_type&
-  get_basic_types() const
-  {return const_cast<priv*>(this)->get_basic_types();}
-
-  /// Getter for the map that associates the name of a class type to
-  /// the @ref class_decl_sptr that represents that type.
-  istring_type_base_wptr_map_type&
-  get_class_types()
-  {return class_types_;}
-
-  /// Getter for the map that associates the name of a class type to
-  /// the @ref class_decl_sptr that represents that type.
-  const istring_type_base_wptr_map_type&
-  get_class_types() const
-  {return const_cast<priv*>(this)->get_class_types();}
-
-  /// Getter for the map that associates the name of a union type to
-  /// the @ref union_decl_sptr that represents that type.
-  istring_type_base_wptr_map_type&
-  get_union_types()
-  {return union_types_;}
-
-  /// Getter for the map that associates the name of a union type to
-  /// the @ref union_decl_sptr that represents that type.
-  const istring_type_base_wptr_map_type&
-  get_union_types() const
-  {return const_cast<priv*>(this)->get_union_types();}
-
-  /// Getter for the map that associates the name of an enum type to
-  /// the @ref enum_type_decl_sptr that represents that type.
-  istring_type_base_wptr_map_type&
-  get_enum_types()
-  {return enum_types_;}
-
-  /// Getter for the map that associates the name of an enum type to
-  /// the @ref enum_type_decl_sptr that represents that type.
-  const istring_type_base_wptr_map_type&
-  get_enum_types() const
-  {return const_cast<priv*>(this)->get_enum_types();}
-
-  /// Getter for the map that associates the name of a typedef to the
-  /// @ref typedef_decl_sptr that represents tha type.
-  istring_type_base_wptr_map_type&
-  get_typedef_types()
-  {return typedef_types_;}
-
-  /// Getter for the map that associates the name of a typedef to the
-  /// @ref typedef_decl_sptr that represents that type.
-  const istring_type_base_wptr_map_type&
-  get_typedef_types() const
-  {return const_cast<priv*>(this)->get_typedef_types();}
-
-  /// Getter for the map that associates the name of a qualified type
-  /// to the @ref qualified_type_def_sptr.
-  istring_type_base_wptr_map_type&
-  get_qualified_types()
-  {return qualified_types_;}
-
-  /// Getter for the map that associates the name of a qualified type
-  /// to the @ref qualified_type_def_sptr.
-  const istring_type_base_wptr_map_type&
-  get_qualified_types() const
-  {return const_cast<priv*>(this)->get_qualified_types();}
-
-  /// Getter for the map that associates the name of a pointer type to
-  /// the @ref pointer_type_def_sptr that represents that type.
-  istring_type_base_wptr_map_type&
-  get_pointer_types()
-  {return pointer_types_;}
-
-  /// Getter for the map that associates the name of a pointer type to
-  /// the @ref pointer_type_def_sptr that represents that type.
-  const istring_type_base_wptr_map_type&
-  get_pointer_types() const
-  {return const_cast<priv*>(this)->get_pointer_types();}
-
-  /// Getter for the map that associates the name of a pointer type to
-  /// the @ref reference_type_def_sptr that represents that type.
-  istring_type_base_wptr_map_type&
-  get_reference_types()
-  {return reference_types_;}
-
-  /// Getter for the map that associates the name of a pointer type to
-  /// the @ref reference_type_def_sptr that represents that type.
-  const istring_type_base_wptr_map_type&
-  get_reference_types() const
-  {return const_cast<priv*>(this)->get_reference_types();}
-
-  /// Getter for the map that associates the name of an array type to
-  /// the @ref array_type_def_sptr that represents that type.
-  istring_type_base_wptr_map_type&
-  get_array_types()
-  {return array_types_;}
-
-  /// Getter for the map that associates the name of an array type to
-  /// the @ref array_type_def_sptr that represents that type.
-  const istring_type_base_wptr_map_type&
-  get_array_types() const
-  {return const_cast<priv*>(this)->get_array_types();}
-
-  /// Getter for the map that associates the name of a function type
-  /// to the @ref function_type_sptr that represents that type.
-  istring_type_base_wptr_map_type&
-  get_function_types()
-  {return function_types_;}
-
-  /// Getter for the map that associates the name of a function type
-  /// to the @ref function_type_sptr that represents that type.
-  const istring_type_base_wptr_map_type&
-  get_function_types() const
-  {return const_cast<priv*>(this)->get_function_types();}
+  type_maps&
+  get_types();
+
+   const type_maps&
+  get_types() const;
 }; // end struct corpus::priv
 
 void
@@ -902,66 +779,6 @@ maybe_update_types_lookup_map(const decl_base_sptr& decl);
 void
 maybe_update_types_lookup_map(const type_base_sptr& type);
 
-type_decl_sptr
-lookup_basic_type(const type_decl&, corpus&);
-
-type_decl_sptr
-lookup_basic_type(const string&, corpus&);
-
-class_decl_sptr
-lookup_class_type(const class_decl&, corpus&);
-
-class_decl_sptr
-lookup_class_type(const string&, corpus&);
-
-enum_type_decl_sptr
-lookup_enum_type(const enum_type_decl&, corpus&);
-
-enum_type_decl_sptr
-lookup_enum_type(const string&, corpus&);
-
-typedef_decl_sptr
-lookup_typedef_type(const typedef_decl&, corpus&);
-
-typedef_decl_sptr
-lookup_typedef_type(const string&, corpus&);
-
-type_base_sptr
-lookup_class_or_typedef_type(const string&, corpus&);
-
-type_base_sptr
-lookup_class_typedef_or_enum_type(const string&, corpus&);
-
-qualified_type_def_sptr
-lookup_qualified_type(const qualified_type_def&, corpus&);
-
-qualified_type_def_sptr
-lookup_qualified_type(const string&, corpus&);
-
-pointer_type_def_sptr
-lookup_pointer_type(const pointer_type_def&, corpus&);
-
-pointer_type_def_sptr
-lookup_pointer_type(const string&, corpus&);
-
-reference_type_def_sptr
-lookup_reference_type(const reference_type_def&, corpus&);
-
-reference_type_def_sptr
-lookup_reference_type(const string&, corpus&);
-
-array_type_def_sptr
-lookup_array_type(const array_type_def&, corpus&);
-
-array_type_def_sptr
-lookup_array_type(const string&, corpus&);
-
-function_type_sptr
-lookup_function_type(const function_type&, corpus&);
-
-function_type_sptr
-lookup_function_type(const string&, corpus&);
-
 }// end namespace ir
 
 }// end namespace abigail
index b2c87fa79a9d5aa9ac63d2e8a42bd213dfd47317..319a41870eda028a4c93b0f365eed285495e82d0 100644 (file)
@@ -48,6 +48,7 @@ ABG_END_EXPORT_DECLARATIONS
 // </headers defining libabigail's API>
 
 #include "abg-corpus-priv.h"
+#include "abg-ir-priv.h"
 
 namespace abigail
 {
@@ -440,6 +441,16 @@ corpus::priv::build_unreferenced_symbols_tables()
     }
 }
 
+/// Get the maps that associate a name to a certain kind of type.
+type_maps&
+corpus::priv::get_types()
+{return types_;}
+
+/// Get the maps that associate a name to a certain kind of type.
+const type_maps&
+corpus::priv::get_types() const
+{return types_;}
+
 /// Record a canonical type which has been computed for the current
 /// corpus.
 ///
@@ -543,6 +554,21 @@ void
 corpus::drop_translation_units()
 {priv_->members.clear();}
 
+/// Get the maps that associate a name to a certain kind of type.
+///
+/// @return the maps that associate a name to a certain kind of type.
+type_maps&
+corpus::get_types()
+{return priv_->types_;}
+
+/// Get the maps that associate a name to a certain kind of type.
+///
+/// @return the maps that associate a name to a certain kind of
+/// type.
+const type_maps&
+corpus::get_types() const
+{return priv_->types_;}
+
 /// Getter for the origin of the corpus.
 ///
 /// @return the origin of the corpus.
@@ -1399,767 +1425,6 @@ corpus::get_exported_decls_builder() const
   return priv_->exported_decls_builder;
 }
 
-/// Lookup a type definition in all the translation units of a given
-/// ABI corpus.
-///
-/// @param @param qn the fully qualified name of the type to lookup.
-///
-/// @param abi_corpus the ABI corpus which to look the type up in.
-///
-/// @return the type definition if any was found, or a NULL pointer.
-const decl_base_sptr
-lookup_type_in_corpus(const string& qn, const corpus& abi_corpus)
-{
-  decl_base_sptr result;
-
-  for (translation_units::const_iterator tu =
-        abi_corpus.get_translation_units().begin();
-       tu != abi_corpus.get_translation_units().end();
-       ++tu)
-    if ((result = lookup_type_in_translation_unit(qn, **tu)))
-      break;
-
-  return result;
-}
-
-/// Lookup a class type definition in all the translation units of a
-/// given ABI corpus.
-///
-/// @param @param qn the fully qualified name of the class type to lookup.
-///
-/// @param abi_corpus the ABI corpus which to look the type up in.
-///
-/// @return the type definition if any was found, or a NULL pointer.
-const class_decl_sptr
-lookup_class_type_in_corpus(const string& qn, const corpus& abi_corpus)
-{
-  class_decl_sptr result;
-
-  for (translation_units::const_iterator tu =
-        abi_corpus.get_translation_units().begin();
-       tu != abi_corpus.get_translation_units().end();
-       ++tu)
-    if ((result = lookup_class_type_in_translation_unit(qn, **tu)))
-      break;
-
-  return result;
-}
-
-/// Lookup a type in an ABI corpus.
-///
-/// @param type the type to lookup.
-///
-/// @param corpus the ABI corpus to consider for the lookup.
-///
-/// @param the type found in the corpus or NULL if no such type was
-/// found.
-type_base_sptr
-lookup_type_in_corpus(const type_base_sptr& type, corpus& corpus)
-{
-  assert(type);
-
-  type_base_sptr result;
-  for (translation_units::const_iterator i =
-        corpus.get_translation_units().begin();
-       i != corpus.get_translation_units().end();
-       ++i)
-    if ((result = lookup_type_in_translation_unit(type, **i)))
-      break;
-
-  return result;
-}
-
-/// Look into an ABI corpus for a function type.
-///
-/// @param fn_type the function type to be looked for in the ABI
-/// corpus.
-///
-/// @param corpus the ABI corpus into which to look for the function
-/// type.
-///
-/// @return the function type found in the corpus.
-function_type_sptr
-lookup_function_type_in_corpus(const function_type_sptr& fn_type,
-                              corpus& corpus)
-{
-  assert(fn_type);
-
-  function_type_sptr result;
-
-  for (translation_units::const_iterator i =
-        corpus.get_translation_units().begin();
-       i != corpus.get_translation_units().end();
-       ++i)
-    if ((result = lookup_function_type_in_translation_unit(fn_type, **i)))
-      return result;
-
-  if (!result)
-    for (translation_units::const_iterator i =
-          corpus.get_translation_units().begin();
-        i != corpus.get_translation_units().end();
-        ++i)
-      if ((result = synthesize_function_type_from_translation_unit(*fn_type,
-                                                                  **i)))
-       return result;
-
-  return result;
-}
-
-/// Update the map that associates a fully qualified name of a given
-/// type to that type.
-///
-/// @param scope the scope of the type we are considering.
-///
-/// @param type the type we are considering.
-///
-/// @param types_map the map to update.  It's a map that assciates a
-/// fully qualified name of a type to the type itself.
-template<typename TypeKind>
-void
-maybe_update_types_lookup_map(scope_decl *scope,
-                             const shared_ptr<TypeKind>& type,
-                             istring_type_base_wptr_map_type& types_map)
-{
-  corpus *type_corpus = scope->get_corpus();
-  assert(type_corpus);
-
-  interned_string s = get_type_name(type);
-  if (types_map.find(s) == types_map.end())
-    types_map[s]= type;
-}
-
-/// This is the specialization for type @ref class_decl of the
-/// function template:
-///
-///    maybe_update_types_lookup_map<T>(scope_decl*,
-///                                    const shared_ptr<T>&,
-///                                    istring_type_base_wptr_map_type&)
-///
-/// @param scope the scope of the type to consider.
-///
-/// @param class_type the type to consider.
-///
-/// @param types_map the type map to update.
-template<>
-void
-maybe_update_types_lookup_map<class_decl>(scope_decl *scope,
-                                         const class_decl_sptr& class_type,
-                                         istring_type_base_wptr_map_type& map)
-{
-  class_decl_sptr type = class_type;
-
-  bool update_qname_map = true;
-  if (type->get_is_declaration_only())
-    {
-      if (class_decl_sptr def = class_type->get_definition_of_declaration())
-       type = def;
-      else
-       update_qname_map = false;
-    }
-
-  if (!update_qname_map)
-    return;
-
-  corpus *type_corpus = scope->get_corpus();
-  assert(type_corpus);
-
-  string qname = type->get_qualified_name();
-  interned_string s = type_corpus->get_environment()->intern(qname);
-  if (map.find(s) == map.end())
-    map[s]= type;
-}
-
-/// This is the specialization for type @ref function_type of the
-/// function template:
-///
-///    maybe_update_types_lookup_map<T>(scope_decl*,
-///                                    const shared_ptr<T>&,
-///                                    istring_type_base_wptr_map_type&)
-///
-/// @param scope the scope of the type to consider.
-///
-/// @param class_type the type to consider.
-///
-/// @param types_map the type map to update.
-template<>
-void
-maybe_update_types_lookup_map<function_type>
-(scope_decl *scope,
- const function_type_sptr& type,
- istring_type_base_wptr_map_type& types_map)
-{
-  corpus *type_corpus = scope->get_corpus();
-  assert(type_corpus);
-
-  string str = get_pretty_representation(type, /*internal=*/true);
-  interned_string s = type->get_environment()->intern(str);
-
-  if (types_map.find(s) == types_map.end())
-    types_map[s]= type;
-}
-
-/// Update the map that associates a fully qualified name of a given
-/// type to that type.
-///
-/// @param type the type we are considering.
-///
-/// @param types_map the map to update.  It's a map that assciates a
-/// fully qualified name of a type to the type itself.
-template<typename TypeKind>
-void
-maybe_update_types_lookup_map(const shared_ptr<TypeKind>& type,
-                             istring_type_base_wptr_map_type& types_map)
-{
-  scope_decl *scope = get_type_scope(type);
-  if (scope)
-    maybe_update_types_lookup_map(scope, type, types_map);
-  else
-    {
-      // This type doesn't have a scope; this is maybe b/c it's a
-      // function type.  Those beasts are usually put in the global
-      // scope of the current translation unit by
-      // translation_unit::bind_function_type_life_time.  For now,
-      // let's say that this function should not be called on those
-      // function types.
-      //
-      // XXXX: But if we really want function types to have a scope,
-      // we should prolly add a get_scope member function to
-      // function_type and make get_type_scope() to call that one.
-      ABG_ASSERT_NOT_REACHED;
-    }
-}
-
-/// Update the map that associates the fully qualified name of a basic
-/// type with the type itself.
-///
-/// @param basic_type the basic type to consider.
-void
-maybe_update_types_lookup_map(const type_decl_sptr& basic_type)
-{
-  if (corpus *type_corpus = basic_type->get_corpus())
-    return maybe_update_types_lookup_map<type_decl>
-      (basic_type, type_corpus->priv_->get_basic_types());
-}
-
-/// Update the map that associates the fully qualified name of a class
-/// type with the type itself.
-///
-/// @param class_type the class type to consider.
-void
-maybe_update_types_lookup_map(const class_decl_sptr& class_type)
-{
-  if (corpus *type_corpus = class_type->get_corpus())
-    maybe_update_types_lookup_map<class_decl>
-      (class_type, type_corpus->priv_->get_class_types());
-}
-
-/// Update the map that associates the fully qualified name of a union
-/// type with the type itself.
-///
-/// @param union_type the union type to consider.
-void
-maybe_update_types_lookup_map(const union_decl_sptr& union_type)
-{
-  if (corpus *type_corpus = union_type->get_corpus())
-    maybe_update_types_lookup_map<union_decl>
-      (union_type, type_corpus->priv_->get_union_types());
-}
-
-/// Update the map that associates the fully qualified name of an enum
-/// type with the type itself.
-///
-/// @param enum_type the type to consider.
-void
-maybe_update_types_lookup_map(const enum_type_decl_sptr& enum_type)
-
-{
-  if (corpus *type_corpus = enum_type->get_corpus())
-    maybe_update_types_lookup_map<enum_type_decl>
-      (enum_type, type_corpus->priv_->get_enum_types());
-}
-
-/// Update the map that associates the fully qualified name of a
-/// typedef type with the type itself.
-///
-/// @param typedef_type the type to consider.
-void
-maybe_update_types_lookup_map(const typedef_decl_sptr& typedef_type)
-
-{
-  if (corpus *type_corpus = typedef_type->get_corpus())
-    maybe_update_types_lookup_map<typedef_decl>
-      (typedef_type, type_corpus->priv_->get_typedef_types());
-}
-
-/// Update the map that associates the fully qualified name of a
-/// qualified type with the type itself.
-///
-/// @param qualified_type the type to consider.
-void
-maybe_update_types_lookup_map(const qualified_type_def_sptr& qualified_type)
-{
-  if (corpus *type_corpus = qualified_type->get_corpus())
-    maybe_update_types_lookup_map<qualified_type_def>
-      (qualified_type, type_corpus->priv_->get_qualified_types());
-}
-
-/// Update the map that associates the fully qualified name of a
-/// pointer type with the type itself.
-///
-/// @param pointer_type the type to consider.
-void
-maybe_update_types_lookup_map(const pointer_type_def_sptr& pointer_type)
-{
-  if (corpus *type_corpus = pointer_type->get_corpus())
-    maybe_update_types_lookup_map<pointer_type_def>
-      (pointer_type, type_corpus->priv_->get_pointer_types());
-}
-
-/// Update the map that associates the fully qualified name of a
-/// reference type with the type itself.
-///
-/// @param reference_type the type to consider.
-void
-maybe_update_types_lookup_map(const reference_type_def_sptr& reference_type)
-{
-  if (corpus *type_corpus = reference_type->get_corpus())
-    maybe_update_types_lookup_map<reference_type_def>
-      (reference_type, type_corpus->priv_->get_reference_types());
-}
-
-/// Update the map that associates the fully qualified name of a type
-/// with the type itself.
-///
-/// @param array_type the type to consider.
-void
-maybe_update_types_lookup_map(const array_type_def_sptr& array_type)
-{
-  if (corpus *type_corpus = array_type->get_corpus())
-    maybe_update_types_lookup_map<array_type_def>
-      (array_type, type_corpus->priv_->get_array_types());
-}
-
-/// Update the map that associates the fully qualified name of a
-/// function type with the type itself.
-///
-/// @param scope the scope of the function type.
-/// @param fn_type the type to consider.
-void
-maybe_update_types_lookup_map(scope_decl *scope,
-                             const function_type_sptr& fn_type)
-{
-  if (corpus *type_corpus = scope->get_corpus())
-    maybe_update_types_lookup_map<function_type>
-      (scope, fn_type, type_corpus->priv_->get_function_types());
-}
-
-/// Update the map that associates the fully qualified name of a type
-/// declaration with the type itself.
-///
-/// @param decl the declaration of the type to consider.
-void
-maybe_update_types_lookup_map(const decl_base_sptr& decl)
-{
-  if (!is_type(decl))
-    return;
-
-  if (type_decl_sptr basic_type = is_type_decl(decl))
-    maybe_update_types_lookup_map(basic_type);
-  else if (class_decl_sptr class_type = is_class_type(decl))
-    maybe_update_types_lookup_map(class_type);
-  else if (union_decl_sptr union_type = is_union_type(decl))
-    maybe_update_types_lookup_map(union_type);
-  else if (enum_type_decl_sptr enum_type = is_enum_type(decl))
-    maybe_update_types_lookup_map(enum_type);
-  else if (typedef_decl_sptr typedef_type = is_typedef(decl))
-    maybe_update_types_lookup_map(typedef_type);
-  else if (qualified_type_def_sptr qualified_type = is_qualified_type(decl))
-    maybe_update_types_lookup_map(qualified_type);
-  else if (pointer_type_def_sptr pointer_type = is_pointer_type(decl))
-    maybe_update_types_lookup_map(pointer_type);
-  else if (reference_type_def_sptr reference_type = is_reference_type(decl))
-    maybe_update_types_lookup_map(reference_type);
-  else if (array_type_def_sptr array_type = is_array_type(decl))
-    maybe_update_types_lookup_map(array_type);
-  else
-    ABG_ASSERT_NOT_REACHED;
-}
-
-/// Update the map that associates the fully qualified name of a type
-/// with the type itself.
-///
-/// @param type the type to consider.
-void
-maybe_update_types_lookup_map(const type_base_sptr& type)
-{
-  if (decl_base_sptr decl = get_type_declaration(type))
-    maybe_update_types_lookup_map(decl);
-  else
-    ABG_ASSERT_NOT_REACHED;
-}
-
-/// Look into a given corpus to find a type which has the same
-/// qualified name as a giventype.
-///
-/// @param t the type which has the same qualified name as the type we
-/// are looking for.
-///
-/// @param corp the ABI corpus to look into for the type.
-type_decl_sptr
-lookup_basic_type(const type_decl& t, corpus& corp)
-{return lookup_basic_type(t.get_name(), corp);}
-
-/// Look into a given corpus to find a basic type which has a given
-/// qualified name.
-///
-/// @param qualified_name the qualified name of the basic type to look
-/// for.
-///
-/// @param corp the corpus to look into.
-type_decl_sptr
-lookup_basic_type(const string &qualified_name, corpus& corp)
-{
-  istring_type_base_wptr_map_type& basic_types = corp.priv_->get_basic_types();
-  istring_type_base_wptr_map_type::iterator i =
-    basic_types.find(corp.get_environment()->intern(qualified_name));
-  if (i == basic_types.end())
-    return type_decl_sptr();
-  return is_type_decl(type_base_sptr(i->second));
-}
-
-/// Look into a given corpus to find a class type which has the same
-/// qualified name as a given type.
-///
-/// @param t the class decl type which has the same qualified name as
-/// the type we are looking for.
-///
-/// @param corp the corpus to look into.
-class_decl_sptr
-lookup_class_type(const class_decl& t, corpus& corp)
-{
-  string s = t.get_pretty_representation(/*internal*/true);
-  return lookup_class_type(s, corp);
-}
-
-/// Look into a given corpus to find a type which has a given
-/// qualified name.
-///
-/// @param qualified_name the qualified name of the type to look for.
-///
-/// @param corp the corpus to look into.
-class_decl_sptr
-lookup_class_type(const string& qualified_name, corpus& corp)
-{
-  istring_type_base_wptr_map_type& class_types = corp.priv_->get_class_types();
-  istring_type_base_wptr_map_type::iterator i =
-    class_types.find(corp.get_environment()->intern(qualified_name));
-  if (i == class_types.end())
-    return class_decl_sptr();
-  return is_class_type(type_base_sptr(i->second));
-}
-
-/// Look into a given corpus to find a enum type which has the same
-/// qualified name as a given enum type.
-///
-/// @param t the enum type which has the same qualified name as the
-/// type we are looking for.
-///
-/// @param corp the corpus to look into.
-enum_type_decl_sptr
-lookup_enum_type(const enum_type_decl& t, corpus& corp)
-{
-  string s = t.get_pretty_representation(/*internal=*/true);
-  return lookup_enum_type(s, corp);
-}
-
-/// Look into a given corpus to find an enum type which has a given
-/// qualified name.
-///
-/// @param qualified_name the qualified name of the enum type to look
-/// for.
-///
-/// @param corp the corpus to look into.
-enum_type_decl_sptr
-lookup_enum_type(const string& qualified_name, corpus& corp)
-{
-  istring_type_base_wptr_map_type& enum_types = corp.priv_->get_enum_types();
-  istring_type_base_wptr_map_type::iterator i =
-    enum_types.find(corp.get_environment()->intern(qualified_name));
-  if (i == enum_types.end())
-    return enum_type_decl_sptr();
-  return is_enum_type(type_base_sptr(i->second));
-}
-
-/// Look into a given corpus to find a typedef type which has the
-/// same qualified name as a given typedef type.
-///
-/// @param t the typedef type which has the same qualified name as the
-/// typedef type we are looking for.
-///
-/// @param corp the corpus to look into.
-typedef_decl_sptr
-lookup_typedef_type(const typedef_decl& t, corpus& corp)
-{
-  string s = t.get_pretty_representation(/*internal=*/true);
-  return lookup_typedef_type(s, corp);
-}
-
-/// Look into a given corpus to find a typedef type which has a
-/// given qualified name.
-///
-/// @param qualified_name the qualified name of the typedef type to
-/// look for.
-///
-/// @param corp the corpus to look into.
-typedef_decl_sptr
-lookup_typedef_type(const string& qualified_name, corpus& corp)
-{
-  istring_type_base_wptr_map_type& typedef_types =
-    corp.priv_->get_typedef_types();
-  istring_type_base_wptr_map_type::iterator i =
-    typedef_types.find(corp.get_environment()->intern(qualified_name));
-  if (i == typedef_types.end())
-    return typedef_decl_sptr();
-  return is_typedef(type_base_sptr(i->second));
-}
-
-/// Look into a corpus to find a class or typedef type which has a
-/// given qualified name.
-///
-/// @param qualified_name the name of the type to find.
-///
-/// @param corp the corpus to look into.
-///
-/// @return the typedef or class type found.
-type_base_sptr
-lookup_class_or_typedef_type(const string& qualified_name, corpus& corp)
-{
-  istring_type_base_wptr_map_type& class_types =
-    corp.priv_->get_class_types();
-  istring_type_base_wptr_map_type& typedef_types =
-    corp.priv_->get_typedef_types();
-
-  interned_string name = corp.get_environment()->intern(qualified_name);
-
-  istring_type_base_wptr_map_type::iterator i = class_types.find(name);
-  if (i == class_types.end())
-    {
-      i = typedef_types.find(name);
-      if (i == typedef_types.end())
-       return type_base_sptr();
-    }
-  return type_base_sptr(i->second);
-}
-
-/// Look into a corpus to find a class, typedef or enum type which has
-/// a given qualified name.
-///
-/// @param qualified_name the qualified name of the type to look for.
-///
-/// @param corp the corpus to look into.
-///
-/// @return the typedef, class or enum type found.
-type_base_sptr
-lookup_class_typedef_or_enum_type(const string& qualified_name, corpus& corp)
-{
-  istring_type_base_wptr_map_type& enum_types = corp.priv_->get_class_types();
-  type_base_sptr result = lookup_class_or_typedef_type(qualified_name, corp);
-
-  if (!result)
-    {
-      interned_string name = corp.get_environment()->intern(qualified_name);
-      istring_type_base_wptr_map_type::iterator i = enum_types.find(name);
-      if (i != enum_types.end())
-       result = type_base_sptr(i->second);
-    }
-
-  return result;
-}
-
-/// Look into a given corpus to find a qualified type which has the
-/// same qualified name as a given type.
-///
-/// @param t the type which has the same qualified name as the
-/// qualified type we are looking for.
-///
-/// @param corp the corpus to look into.
-///
-/// @return the qualified type found.
-qualified_type_def_sptr
-lookup_qualified_type(const qualified_type_def& t, corpus& corp)
-{
-  string s = t.get_pretty_representation(/*internal=*/true);
-  return lookup_qualified_type(s, corp);
-}
-
-/// Look into a given corpus to find a qualified type which has a
-/// given qualified name.
-///
-/// @param qualified_name the qualified name of the type to look for.
-///
-/// @param corp the corpus to look into.
-///
-/// @return the type found.
-qualified_type_def_sptr
-lookup_qualified_type(const string& qualified_name, corpus& corp)
-{
-  istring_type_base_wptr_map_type& qualified_types =
-    corp.priv_->get_qualified_types();
-  istring_type_base_wptr_map_type::iterator i =
-    qualified_types.find(corp.get_environment()->intern(qualified_name));
-  if (i == qualified_types.end())
-    return qualified_type_def_sptr();
-  return is_qualified_type(type_base_sptr(i->second));
-}
-
-/// Look into a given corpus to find a pointer type which has the same
-/// qualified name as a given pointer type.
-///
-/// @param t the pointer type which has the same qualified name as the
-/// type we are looking for.
-///
-/// @param corp the corpus to look into.
-///
-/// @return the pointer type found.
-pointer_type_def_sptr
-lookup_pointer_type(const pointer_type_def& t, corpus& corp)
-{
-  string s = t.get_pretty_representation(/*internal=*/true);
-  return lookup_pointer_type(s, corp);
-}
-
-/// Look into a given corpus to find a pointer type which has a given
-/// qualified name.
-///
-/// @param qualified_name the qualified name of the pointer type to
-/// look for.
-///
-/// @param corp the corpus to look into.
-///
-/// @return the pointer type found.
-pointer_type_def_sptr
-lookup_pointer_type(const string& qualified_name, corpus& corp)
-{
-  istring_type_base_wptr_map_type& pointer_types =
-    corp.priv_->get_pointer_types();
-  istring_type_base_wptr_map_type::iterator i =
-    pointer_types.find(corp.get_environment()->intern(qualified_name));
-  if (i == pointer_types.end())
-    return pointer_type_def_sptr();
-  return is_pointer_type(type_base_sptr(i->second));
-}
-
-/// Look into a given corpus to find a reference type which has the
-/// same qualified name as a given reference type.
-///
-/// @param t the reference type which has the same qualified name as
-/// the reference type we are looking for.
-///
-/// @param corp the corpus to look into.
-///
-/// @return the reference type found.
-reference_type_def_sptr
-lookup_reference_type(const reference_type_def& t, corpus& corp)
-{
-  string s = t.get_pretty_representation(/*internal=*/true);
-  return lookup_reference_type(s, corp);
-}
-
-/// Look into a given corpus to find a reference type which has a
-/// given qualified name.
-///
-/// @param qualified_name the qualified name of the reference type to
-/// look for.
-///
-/// @param corp the corpus to look into.
-///
-/// @return the reference type found.
-reference_type_def_sptr
-lookup_reference_type(const string& qualified_name, corpus& corp)
-{
-  istring_type_base_wptr_map_type& reference_types =
-    corp.priv_->get_reference_types();
-  istring_type_base_wptr_map_type::iterator i =
-    reference_types.find(corp.get_environment()->intern(qualified_name));
-  if (i == reference_types.end())
-    return reference_type_def_sptr();
-  return is_reference_type(type_base_sptr(i->second));
-}
-
-/// Look into a given corpus to find an array type which has a given
-/// qualified name.
-///
-/// @param qualified_name the qualified name of the array type to look
-/// for.
-///
-/// @param corp the corpus to look into.
-///
-/// @return the array type found.
-array_type_def_sptr
-lookup_array_type(const array_type_def& t, corpus& corp)
-{
-  string s = t.get_pretty_representation(/*internal=*/true);
-  return lookup_array_type(s, corp);
-}
-
-/// Look into a given corpus to find an array type which has the same
-/// qualified name as a given array type.
-///
-/// @param t the type which has the same qualified name as the type we
-/// are looking for.
-///
-/// @param corp the corpus to look into.
-///
-/// @return the type found.
-array_type_def_sptr
-lookup_array_type(const string& qualified_name, corpus& corp)
-{
-  istring_type_base_wptr_map_type& array_types =
-    corp.priv_->get_array_types();
-  istring_type_base_wptr_map_type::iterator i =
-    array_types.find(corp.get_environment()->intern(qualified_name));
-  if (i == array_types.end())
-    return array_type_def_sptr();
-  return is_array_type(type_base_sptr(i->second));
-}
-
-/// Look into a given corpus to find a function type which has the same
-/// qualified name as a given function type.
-///
-/// @param t the function type which has the same qualified name as
-/// the function type we are looking for.
-///
-/// @param corp the corpus to look into.
-///
-/// @return the function type found.
-function_type_sptr
-lookup_function_type(const function_type&t, corpus& corp)
-{
-  string s = t.get_pretty_representation(/*internal*/true);
-  return lookup_function_type(s, corp);
-}
-
-/// Look into a given corpus to find a function type which has a given
-/// qualified name.
-///
-/// @param qualified_name the qualified name of the function type to
-/// look for.
-///
-/// @param corp the corpus to look into.
-///
-/// @return the function type found.
-function_type_sptr
-lookup_function_type(const string& qualified_name, corpus& corp)
-{
-  istring_type_base_wptr_map_type& function_types =
-    corp.priv_->get_function_types();
-  istring_type_base_wptr_map_type::iterator i =
-    function_types.find(corp.get_environment()->intern(qualified_name));
-  if (i == function_types.end())
-    return function_type_sptr();
-  return is_function_type(type_base_sptr(i->second));
-}
-
 // </corpus stuff>
 }// end namespace ir
 }// end namespace abigail
index 2894119a015d92d85217f83965aa6920c352297a..c739d3f651c1703f3d40cb50ef6f2291a2b64cb9 100644 (file)
@@ -3638,8 +3638,7 @@ public:
          }
 
        if (decl_base_sptr type_decl =
-           lookup_class_type_in_corpus(i->first,
-                                       *current_corpus()))
+           lookup_class_type(i->first, *current_corpus()))
          {
            class_decl_sptr klass = is_class_type(type_decl);
            assert(klass);
@@ -9461,16 +9460,15 @@ build_translation_unit_and_add_to_ir(read_context&      ctxt,
            fqn_to_components(demangled_name, fqn_comps);
            string mem_name = fqn_comps.back();
            fqn_comps.pop_back();
-           decl_base_sptr ty_decl;
+           class_decl_sptr class_type;
            string ty_name;
            if (!fqn_comps.empty())
              {
                ty_name = components_to_type_name(fqn_comps);
-               ty_decl =
-                 lookup_type_in_translation_unit(ty_name,
-                                                 *ctxt.cur_transl_unit());
+               class_type =
+                 lookup_class_type(ty_name, *ctxt.cur_transl_unit());
              }
-           if (class_decl_sptr cl = dynamic_pointer_cast<class_decl>(ty_decl))
+           if (class_type)
              {
                // So we are seeing a member variable for which there
                // is a global variable definition DIE not having a
@@ -9479,7 +9477,7 @@ build_translation_unit_and_add_to_ir(read_context&        ctxt,
                // variable definition from its current non-class
                // scope ...
                decl_base_sptr d;
-               if (d = lookup_var_decl_in_scope(mem_name,cl))
+               if (d = lookup_var_decl_in_scope(mem_name, class_type))
                  // This is the data member with the same name in cl.
                  // We just need to flag it as static.
                  ;
@@ -9489,15 +9487,13 @@ build_translation_unit_and_add_to_ir(read_context&      ctxt,
                    // same name in cl already.  Let's add it there then
                    // ...
                    remove_decl_from_scope(*v);
-                   d = add_decl_to_scope(*v, cl);
+                   d = add_decl_to_scope(*v, class_type);
                  }
 
                assert(dynamic_pointer_cast<var_decl>(d));
                // Let's flag the data member as static.
                set_member_is_static(d, true);
              }
-           if (ty_decl)
-             assert(ty_decl->get_scope());
          }
       }
   ctxt.var_decls_to_re_add_to_tree().clear();
index fa160f8b34b31aa8e22d4064f06aeaf48aafcc68..853954919b608095ae9fc6e3b9f01efe266d190f 100644 (file)
@@ -30,6 +30,8 @@
 
 #include <string>
 
+#include "abg-ir.h"
+
 namespace abigail
 {
 
@@ -130,6 +132,38 @@ bool
 parse_integral_type(const string& type_name,
                    integral_type& type);
 
+/// Private type to hold private members of @ref translation_unit
+struct translation_unit::priv
+{
+  const environment*                           env_;
+  corpus*                                      corp;
+  bool                                         is_constructed_;
+  char                                         address_size_;
+  language                                     language_;
+  std::string                                  path_;
+  location_manager                             loc_mgr_;
+  mutable global_scope_sptr                    global_scope_;
+  mutable vector<type_base_sptr>               synthesized_types_;
+  vector<function_type_sptr>                   live_fn_types_;
+  type_maps                                    types_;
+
+
+  priv(const environment* env)
+    : env_(env),
+      corp(),
+      is_constructed_(),
+      address_size_(),
+      language_(LANG_UNKNOWN)
+  {}
+
+  ~priv()
+  {}
+
+  type_maps&
+  get_types()
+  {return types_;}
+}; // end translation_unit::priv
+
 } // end namespace ir
 
 } // end namespace abigail
index 96882c88fa2264a9fd843e9c1354ff3b5ab17de8..86d8a984071adc5b9144d1b77b77be84adb5167b 100644 (file)
@@ -33,7 +33,6 @@
 #include <sstream>
 #include <tr1/memory>
 #include <tr1/unordered_map>
-#include "abg-ir-priv.h"
 
 #include "abg-internal.h"
 // <headers defining libabigail's API go under here>
@@ -47,6 +46,9 @@ ABG_BEGIN_EXPORT_DECLARATIONS
 ABG_END_EXPORT_DECLARATIONS
 // </headers defining libabigail's API>
 
+#include "abg-tools-utils.h"
+#include "abg-ir-priv.h"
+
 namespace
 {
 /// This internal type is a tree walker that walks the sub-tree of a
@@ -395,32 +397,147 @@ typedef unordered_map<function_type_sptr,
                      function_type::hash,
                      type_shared_ptr_equal> fn_type_ptr_map;
 
-/// Private type to hold private members of @ref translation_unit
-struct translation_unit::priv
-{
-  const environment*                           env_;
-  corpus*                                      corp;
-  bool                                         is_constructed_;
-  char                                         address_size_;
-  language                                     language_;
-  std::string                                  path_;
-  location_manager                             loc_mgr_;
-  mutable global_scope_sptr                    global_scope_;
-  mutable function_types_type                  function_types_;
-  mutable vector<type_base_sptr>               synthesized_types_;
-  mutable string_type_base_wptr_map_type       types_;
-
-  priv(const environment* env)
-    : env_(env),
-      corp(),
-      is_constructed_(),
-      address_size_(),
-      language_(LANG_UNKNOWN)
-  {}
+// <type_maps stuff>
 
-  ~priv()
-  {}
-}; // end translation_unit::priv
+struct type_maps::priv
+{
+  mutable istring_type_base_wptr_map_type      basic_types_;
+  mutable istring_type_base_wptr_map_type      class_types_;
+  mutable istring_type_base_wptr_map_type      union_types_;
+  mutable istring_type_base_wptr_map_type      enum_types_;
+  mutable istring_type_base_wptr_map_type      typedef_types_;
+  mutable istring_type_base_wptr_map_type      qualified_types_;
+  mutable istring_type_base_wptr_map_type      pointer_types_;
+  mutable istring_type_base_wptr_map_type      reference_types_;
+  mutable istring_type_base_wptr_map_type      array_types_;
+  mutable istring_type_base_wptr_map_type      function_types_;
+}; // end struct type_maps::priv
+
+type_maps::type_maps()
+  : priv_(new priv)
+{}
+
+/// Getter for the map that associates the name of a basic type to
+/// the @ref type_decl_sptr that represents that type.
+const istring_type_base_wptr_map_type&
+type_maps::basic_types() const
+{return priv_->basic_types_;}
+
+/// Getter for the map that associates the name of a basic type to
+/// the @ref type_decl_sptr that represents that type.
+istring_type_base_wptr_map_type&
+type_maps::basic_types()
+{return priv_->basic_types_;}
+
+/// Getter for the map that associates the name of a class type to
+/// the @ref class_decl_sptr that represents that type.
+const istring_type_base_wptr_map_type&
+type_maps::class_types() const
+{return priv_->class_types_;}
+
+/// Getter for the map that associates the name of a class type to
+/// the @ref class_decl_sptr that represents that type.
+istring_type_base_wptr_map_type&
+type_maps::class_types()
+{return priv_->class_types_;}
+
+/// Getter for the map that associates the name of a union type to
+/// the @ref union_decl_sptr that represents that type.
+istring_type_base_wptr_map_type&
+type_maps::union_types()
+{return priv_->union_types_;}
+
+/// Getter for the map that associates the name of a union type to
+/// the @ref union_decl_sptr that represents that type.
+const istring_type_base_wptr_map_type&
+type_maps::union_types() const
+{return priv_->union_types_;}
+
+/// Getter for the map that associates the name of an enum type to
+/// the @ref enum_type_decl_sptr that represents that type.
+istring_type_base_wptr_map_type&
+type_maps::enum_types()
+{return priv_->enum_types_;}
+
+/// Getter for the map that associates the name of an enum type to
+/// the @ref enum_type_decl_sptr that represents that type.
+const istring_type_base_wptr_map_type&
+type_maps::enum_types() const
+{return priv_->enum_types_;}
+
+/// Getter for the map that associates the name of a typedef to the
+/// @ref typedef_decl_sptr that represents tha type.
+istring_type_base_wptr_map_type&
+type_maps::typedef_types()
+{return priv_->typedef_types_;}
+
+/// Getter for the map that associates the name of a typedef to the
+/// @ref typedef_decl_sptr that represents tha type.
+const istring_type_base_wptr_map_type&
+type_maps::typedef_types() const
+{return priv_->typedef_types_;}
+
+/// Getter for the map that associates the name of a qualified type
+/// to the @ref qualified_type_def_sptr.
+istring_type_base_wptr_map_type&
+type_maps::qualified_types()
+{return priv_->qualified_types_;}
+
+/// Getter for the map that associates the name of a qualified type
+/// to the @ref qualified_type_def_sptr.
+const istring_type_base_wptr_map_type&
+type_maps::qualified_types() const
+{return priv_->qualified_types_;}
+
+/// Getter for the map that associates the name of a pointer type to
+/// the @ref pointer_type_def_sptr that represents that type.
+istring_type_base_wptr_map_type&
+type_maps::pointer_types()
+{return priv_->pointer_types_;}
+
+/// Getter for the map that associates the name of a pointer type to
+/// the @ref pointer_type_def_sptr that represents that type.
+const istring_type_base_wptr_map_type&
+type_maps::pointer_types() const
+{return priv_->pointer_types_;}
+
+/// Getter for the map that associates the name of a reference type to
+/// the @ref reference_type_def_sptr that represents that type.
+istring_type_base_wptr_map_type&
+type_maps::reference_types()
+{return priv_->reference_types_;}
+
+/// Getter for the map that associates the name of a reference type to
+/// the @ref reference_type_def_sptr that represents that type.
+const istring_type_base_wptr_map_type&
+type_maps::reference_types() const
+{return priv_->reference_types_;}
+
+/// Getter for the map that associates the name of an array type to
+/// the @ref array_type_def_sptr that represents that type.
+istring_type_base_wptr_map_type&
+type_maps::array_types()
+{return priv_->array_types_;}
+
+/// Getter for the map that associates the name of an array type to
+/// the @ref array_type_def_sptr that represents that type.
+const istring_type_base_wptr_map_type&
+type_maps::array_types() const
+{return priv_->array_types_;}
+
+/// Getter for the map that associates the name of a function type
+/// to the @ref function_type_sptr that represents that type.
+const istring_type_base_wptr_map_type&
+type_maps::function_types() const
+{return priv_->function_types_;}
+
+/// Getter for the map that associates the name of a function type
+/// to the @ref function_type_sptr that represents that type.
+istring_type_base_wptr_map_type&
+type_maps::function_types()
+{return priv_->function_types_;}
+
+// </type_maps stuff>
 
 // <translation_unit stuff>
 
@@ -466,29 +583,29 @@ translation_unit::get_global_scope() const
   return priv_->global_scope_;
 }
 
-/// Getter of the function types of the current @ref translation_unit.
-///
-/// @return the function types of the current translation unit.
-const function_types_type
-translation_unit::get_function_types() const
-{ return priv_->function_types_; }
-
 /// Getter of the types of the current @ref translation_unit.
 ///
-/// @return a map of the types of the translation unit.  The key of
-/// the map is the qualified name of the type, and value is the type.
-const string_type_base_wptr_map_type&
+/// @return the maps of the types of the translation unit.
+const type_maps&
 translation_unit::get_types() const
 {return priv_->types_;}
 
 /// Getter of the types of the current @ref translation_unit.
 ///
-/// @return a map of the types of the translation unit.  The key of
-/// the map is the qualified name of the type, and value is the type.
-string_type_base_wptr_map_type&
+/// @return the maps of the types of the translation unit.
+type_maps&
 translation_unit::get_types()
 {return priv_->types_;}
 
+/// Get the vector of function types that are used in the current
+/// translation unit.
+///
+/// @return the vector of function types that are used in the current
+/// translation unit.
+const vector<function_type_sptr>&
+translation_unit::get_live_fn_types() const
+{return priv_->live_fn_types_;}
+
 /// Getter of the environment of the current @ref translation_unit.
 ///
 /// @return the translation unit of the current translation unit.
@@ -669,16 +786,20 @@ translation_unit::operator!=(const translation_unit& o) const
 void
 translation_unit::bind_function_type_life_time(function_type_sptr ftype) const
 {
-  priv_->function_types_.push_back(ftype);
+  const environment* env = get_environment();
+  assert(env);
+
+  const_cast<translation_unit*>(this)->priv_->live_fn_types_.push_back(ftype);
+
+  interned_string repr = get_type_name(ftype);
+  const_cast<translation_unit*>(this)->get_types().function_types()[repr]
+    = ftype;
 
   // The function type must be out of the same environment as its
   // translation unit.
-  if (const environment* env = get_environment())
-    {
-      if (const environment* e = ftype->get_environment())
-       assert(env == e);
-      ftype->set_environment(const_cast<environment*>(env));
-    }
+  if (const environment* e = ftype->get_environment())
+    assert(env == e);
+  ftype->set_environment(const_cast<environment*>(env));
 
   if (const translation_unit* existing_tu = ftype->get_translation_unit())
     assert(existing_tu == this);
@@ -6333,31 +6454,58 @@ iterator_is_last(T& container,
   return (next == container.end());
 }
 
-/// Lookup a type in a translation unit, starting from the global
-/// namespace.
+//--------------------------------
+// <type and decls lookup stuff>
+// ------------------------------
+
+/// Lookup a type (with a given name) in a map that associates a type
+/// name to a type.
 ///
-/// @param fqn the fully qualified name of the type to lookup.
+/// @tparam TypeKind the type of the type this function is supposed to
+/// return.
 ///
-/// @param tu the translation unit to consider.
+/// @param type_name the name of the type to lookup.
 ///
-/// @return the declaration of the type if found, NULL otherwise.
-const decl_base_sptr
-lookup_type_in_translation_unit(const string& fqn,
-                               const translation_unit& tu)
+/// @param type_map the map in which to look.
+///
+/// @return a shared_ptr to the type found.  If no type was found or
+/// if the type found was not of type @p TypeKind then the function
+/// returns nil.
+template <class TypeKind>
+static shared_ptr<TypeKind>
+lookup_type_in_map(const interned_string& type_name,
+                  const istring_type_base_wptr_map_type& type_map)
 {
-  decl_base_sptr result;
-  const string_type_base_wptr_map_type& types = tu.get_types();
-  string_type_base_wptr_map_type::const_iterator it, nil = types.end();
-  it = types.find(fqn);
-  if (it != nil)
-    if (!it->second.expired())
-      result = get_type_declaration(type_base_sptr(it->second));
+  istring_type_base_wptr_map_type::const_iterator i = type_map.find(type_name);
+  if (i != type_map.end())
+    return dynamic_pointer_cast<TypeKind>(type_base_sptr(i->second));
+  return shared_ptr<TypeKind>();
+}
 
-  return result;
+/// Lookup a basic type from a translation unit.
+///
+/// This is done by looking the type up in the type map that is
+/// maintained in the translation unit.  So this is as fast as
+/// possible.
+///
+/// @param type_name the name of the basic type to look for.
+///
+/// @param tu the translation unit to look into.
+///
+/// @return the basic type found or nil if no basic type was found.
+type_decl_sptr
+lookup_basic_type(const interned_string& type_name, const translation_unit& tu)
+{
+  return lookup_type_in_map<type_decl>(type_name,
+                                      tu.get_types().basic_types());
 }
 
 /// Lookup a class type from a translation unit.
 ///
+/// This is done by looking the type up in the type map that is
+/// maintained in the translation unit.  So this is as fast as
+/// possible.
+///
 /// @param fqn the fully qualified name of the class type node to look
 /// up.
 ///
@@ -6365,281 +6513,367 @@ lookup_type_in_translation_unit(const string& fqn,
 ///
 /// @return the declaration of the class type IR node found, NULL
 /// otherwise.
-const class_decl_sptr
-lookup_class_type_in_translation_unit(const string& fqn,
-                                     const translation_unit& tu)
-{return is_class_type(lookup_type_in_translation_unit(fqn, tu));}
+class_decl_sptr
+lookup_class_type(const string& fqn, const translation_unit& tu)
+{
+  const environment* env = tu.get_environment();
+  assert(env);
 
-/// Lookup a function type from a translation unit.
+  interned_string s = env->intern(fqn);
+  return lookup_class_type(s, tu);
+}
+
+/// Lookup a class type from a translation unit.
 ///
-/// This walks all the function types held by the translation unit and
-/// compare their sub-type *names*.  If the names match then return
-/// the function type found in the translation unit.
+/// This is done by looking the type up in the type map that is
+/// maintained in the translation unit.  So this is as fast as
+/// possible.
 ///
-/// @param t the function type to look for.
+/// @param type_name the name of the class type to look for.
 ///
 /// @param tu the translation unit to look into.
 ///
-/// @return the function type found, or NULL of none was found.
-function_type_sptr
-lookup_function_type_in_translation_unit(const function_type& t,
-                                        const translation_unit& tu)
+/// @return the class type found or nil if no class type was found.
+class_decl_sptr
+lookup_class_type(const interned_string& type_name, const translation_unit& tu)
 {
-  interned_string type_name = get_type_name(t), n;
-  function_types_type& fn_types = tu.priv_->function_types_;
-  for (function_types_type::const_iterator i = fn_types.begin();
-       i != fn_types.end();
-       ++i)
-    {
-      n = get_type_name(**i);
-      bool skip_this = false;
-      if (type_name == n)
-       {
-         for (function_decl::parameters::const_iterator p0 =
-                t.get_parameters().begin(),
-                p1 = (**i).get_parameters().begin();
-              (p0 != t.get_parameters().end()
-               && p1 != (**i).get_parameters().end());
-              ++p0, ++p1)
-           if ((*p0)->get_artificial() != (*p1)->get_artificial()
-               || (*p0)->get_variadic_marker() != (*p1)->get_variadic_marker())
-             {
-               skip_this = true;
-               break;
-             }
-         if (skip_this)
-           continue;
-         return *i;
-       }
-    }
-  return function_type_sptr();
+  return lookup_type_in_map<class_decl>(type_name,
+                                       tu.get_types().class_types());
 }
 
-/// Lookup a function type from a translation unit.
+/// Lookup a union type from a translation unit.
 ///
-/// This walks all the function types held by the translation unit and
-/// compare their sub-type *names*.  If the names match then return
-/// the function type found in the translation unit.
+/// This is done by looking the type up in the type map that is
+/// maintained in the translation unit.  So this is as fast as
+/// possible.
 ///
-/// @param t the function type to look for.
+/// @param type_name the name of the union type to look for.
 ///
 /// @param tu the translation unit to look into.
 ///
-/// @return the function type found, or NULL of none was found.
-function_type_sptr
-lookup_function_type_in_translation_unit(const function_type_sptr& t,
-                                        const translation_unit& tu)
-{return lookup_function_type_in_translation_unit(*t, tu);}
+/// @return the union type found or nil if no union type was found.
+union_decl_sptr
+lookup_union_type(const interned_string& type_name, const translation_unit& tu)
+{
+  return lookup_type_in_map<union_decl>(type_name,
+                                       tu.get_types().union_types());
+}
 
-/// In a translation unit, lookup a given type or synthesize it if
-/// it's a qualified type.
+/// Lookup a enum type from a translation unit.
 ///
-/// So this function first looks the type up in the translation unit.
-/// If it's found, then OK, it's returned.  Otherwise, if it's a
-/// qualified type, lookup the unqualified underlying type and
-/// synthesize the qualified type from it.
+/// This is done by looking the type up in the type map that is
+/// maintained in the translation unit.  So this is as fast as
+/// possible.
 ///
-/// If the unqualified underlying type is not found either, then give
-/// up and return nil.
+/// @param type_name the name of the enum type to look for.
 ///
-/// If the type is not
-type_base_sptr
-synthesize_type_from_translation_unit(const type_base_sptr& type,
-                                     translation_unit& tu)
+/// @param tu the translation unit to look into.
+///
+/// @return the enum type found or nil if no enum type was found.
+enum_type_decl_sptr
+lookup_enum_type(const interned_string& type_name, const translation_unit& tu)
 {
-  type_base_sptr result;
-
-  // TODO: Maybe handle the case of a function type here?
-  result = lookup_type_in_translation_unit(type, tu);
-
-  if (!result)
-    {
-      if (qualified_type_def_sptr qual = is_qualified_type(type))
-       {
-         type_base_sptr underlying_type =
-           synthesize_type_from_translation_unit(qual->get_underlying_type(),
-                                                 tu);
-         if (underlying_type)
-           {
-             result.reset(new qualified_type_def(underlying_type,
-                                                 qual->get_cv_quals(),
-                                                 qual->get_location()));
-           }
-       }
-      else if (pointer_type_def_sptr p = is_pointer_type(type))
-       {
-         type_base_sptr pointed_to_type =
-           synthesize_type_from_translation_unit(p->get_pointed_to_type(),
-                                                 tu);
-         if (pointed_to_type)
-           {
-             result.reset(new pointer_type_def(pointed_to_type,
-                                               p->get_size_in_bits(),
-                                               p->get_alignment_in_bits(),
-                                               p->get_location()));
-             result->set_environment(pointed_to_type->get_environment());
-           }
-       }
-      else if (reference_type_def_sptr r = is_reference_type(type))
-       {
-         type_base_sptr pointed_to_type =
-           synthesize_type_from_translation_unit(r->get_pointed_to_type(), tu);
-         if (pointed_to_type)
-           {
-             result.reset(new reference_type_def(pointed_to_type,
-                                                 r->is_lvalue(),
-                                                 r->get_size_in_bits(),
-                                                 r->get_alignment_in_bits(),
-                                                 r->get_location()));
-             result->set_environment(pointed_to_type->get_environment());
-           }
-       }
-    }
-
-  if (result)
-    tu.priv_->synthesized_types_.push_back(result);
-
-  return result;
+  return lookup_type_in_map<enum_type_decl>(type_name,
+                                           tu.get_types().enum_types());
 }
 
-/// In a translation unit, lookup the sub-types that make up a given
-/// function type and if the sub-types are all found, synthesize and
-/// return a function_type with them.
+/// Lookup a typedef type from a translation unit.
 ///
-/// This function is like lookup_function_type_in_translation_unit()
-/// execept that it constructs the function type from the sub-types
-/// found in the translation, rather than just looking for the
-/// function types held by the translation unit.  This can be useful
-/// if the translation unit doesnt hold the function type we are
-/// looking for (i.e, lookup_function_type_in_translation_unit()
-/// returned NULL) but we still want to see if the sub-types of the
-/// function types are present in the translation unit.
+/// This is done by looking the type up in the type map that is
+/// maintained in the translation unit.  So this is as fast as
+/// possible.
 ///
-/// @param fn_type the function type to consider.
+/// @param type_name the name of the typedef type to look for.
 ///
 /// @param tu the translation unit to look into.
 ///
-/// @return the resulting synthesized function type if all its
-/// sub-types have been found, NULL otherwise.
-function_type_sptr
-synthesize_function_type_from_translation_unit(const function_type& fn_type,
-                                              translation_unit& tu)
+/// @return the typedef type found or nil if no typedef type was
+/// found.
+typedef_decl_sptr
+lookup_typedef_type(const interned_string& type_name,
+                   const translation_unit& tu)
 {
-  function_type_sptr nil = function_type_sptr();
-
-  environment* env = tu.get_environment();
-  assert(env);
-
-  type_base_sptr return_type = fn_type.get_return_type();
-  type_base_sptr result_return_type;
-  if (!return_type || env->is_void_type(return_type))
-    result_return_type = env->get_void_type();
-  else
-    result_return_type = synthesize_type_from_translation_unit(return_type, tu);
-  if (!result_return_type)
-    return nil;
-
-  function_type::parameters parms;
-  type_base_sptr parm_type;
-  function_decl::parameter_sptr parm;
-  for (function_type::parameters::const_iterator i =
-        fn_type.get_parameters().begin();
-       i != fn_type.get_parameters().end();
-       ++i)
-    {
-      type_base_sptr t = (*i)->get_type();
-      parm_type = synthesize_type_from_translation_unit(t, tu);
-      if (!parm_type)
-       return nil;
-      parm.reset(new function_decl::parameter(parm_type,
-                                             (*i)->get_index(),
-                                             (*i)->get_name(),
-                                             (*i)->get_location()));
-      parms.push_back(parm);
-    }
-
-  function_type_sptr result_fn_type
-    (new function_type(result_return_type,
-                      parms,
-                      fn_type.get_size_in_bits(),
-                      fn_type.get_alignment_in_bits()));
-
-  tu.priv_->synthesized_types_.push_back(result_fn_type);
-  // The new synthesized type must be in the same environment as its
-  // translation unit.
-  result_fn_type->set_environment(tu.get_environment());
-
-  return result_fn_type;
+  return lookup_type_in_map<typedef_decl>(type_name,
+                                         tu.get_types().typedef_types());
 }
 
-/// Lookup a type in a scope.
+/// Lookup a qualified type from a translation unit.
 ///
-/// @param fqn the fully qualified name of the type to lookup.
+/// This is done by looking the type up in the type map that is
+/// maintained in the translation unit.  So this is as fast as
+/// possible.
 ///
-/// @param skope the scope to look into.
+/// @param type_name the name of the qualified type to look for.
 ///
-/// @return the declaration of the type if found, NULL otherwise.
-const type_base_sptr
-lookup_type_in_scope(const string& fqn,
-                    const scope_decl_sptr& skope)
+/// @param tu the translation unit to look into.
+///
+/// @return the qualified type found or nil if no qualified type was
+/// found.
+qualified_type_def_sptr
+lookup_qualified_type(const interned_string& type_name,
+                     const translation_unit& tu)
 {
-  list<string> comps;
-  fqn_to_components(fqn, comps);
-  return lookup_type_in_scope(comps, skope);
+  const type_maps& m = tu.get_types();
+  return lookup_type_in_map<qualified_type_def>(type_name,
+                                               m.qualified_types());
 }
 
-/// Lookup a @ref var_decl in a scope.
+/// Lookup a pointer type from a translation unit.
 ///
-/// @param fqn the fuly qualified name of the @var_decl to lookup.
+/// This is done by looking the type up in the type map that is
+/// maintained in the translation unit.  So this is as fast as
+/// possible.
 ///
-/// @param skope the scope to look into.
+/// @param type_name the name of the pointer type to look for.
 ///
-/// @return the declaration of the @ref var_decl if found, NULL
-/// otherwise.
-const decl_base_sptr
-lookup_var_decl_in_scope(const string& fqn,
-                        const scope_decl_sptr& skope)
+/// @param tu the translation unit to look into.
+///
+/// @return the pointer type found or nil if no pointer type was
+/// found.
+pointer_type_def_sptr
+lookup_pointer_type(const interned_string& type_name,
+                   const translation_unit& tu)
 {
-  list<string> comps;
-  fqn_to_components(fqn, comps);
-  return lookup_var_decl_in_scope(comps, skope);
+  const type_maps& m = tu.get_types();
+  return lookup_type_in_map<pointer_type_def>(type_name,
+                                             m.pointer_types());
 }
 
-/// A generic function (template) to get the name of a node, whatever
-/// node it is.  This has to specialized for the kind of node we want
+/// Lookup a reference type from a translation unit.
 ///
-/// @tparam NodeKind the kind of node to consider.
+/// This is done by looking the type up in the type map that is
+/// maintained in the translation unit.  So this is as fast as
+/// possible.
 ///
-/// @param node the node to get the name from.
+/// @param type_name the name of the reference type to look for.
 ///
-/// @return the name of the node.
-template<typename NodeKind>
-static const interned_string&
-get_node_name(shared_ptr<NodeKind> node);
+/// @param tu the translation unit to look into.
+///
+/// @return the reference type found or nil if no reference type was
+/// found.
+reference_type_def_sptr
+lookup_reference_type(const interned_string& type_name,
+                     const translation_unit& tu)
+{
+  const type_maps& m = tu.get_types();
+  return lookup_type_in_map<reference_type_def>(type_name,
+                                               m.reference_types());
+}
 
-/// Gets the name of a class_decl node.
+/// Lookup an array type from a translation unit.
 ///
-/// @param node the decl_base node to get the name from.
+/// This is done by looking the type up in the type map that is
+/// maintained in the translation unit.  So this is as fast as
+/// possible.
 ///
-/// @return the name of the node.
-template<>
-const interned_string&
-get_node_name(class_decl_sptr node)
-{return node->get_name();}
-
-/// Gets the name of a type_base node.
+/// @param type_name the name of the array type to look for.
 ///
-/// @param node the type_base node to get the name from.
+/// @param tu the translation unit to look into.
 ///
-/// @return the name of the node.
-template<>
-const interned_string&
-get_node_name(type_base_sptr node)
-{return get_type_declaration(node)->get_name();}
+/// @return the array type found or nil if no array type was found.
+array_type_def_sptr
+lookup_array_type(const interned_string& type_name,
+                 const translation_unit& tu)
+{
+  const type_maps& m = tu.get_types();
+  return lookup_type_in_map<array_type_def>(type_name,
+                                           m.array_types());
+}
 
-/// Gets the name of a var_decl node.
+/// Lookup a function type from a translation unit.
 ///
-/// @param node the var_decl node to get the name from.
+/// This is done by looking the type up in the type map that is
+/// maintained in the translation unit.  So this is as fast as
+/// possible.
+///
+/// @param type_name the name of the type to lookup.
+///
+/// @param tu the translation unit to look into.
+///
+/// @return the function type found, or NULL of none was found.
+function_type_sptr
+lookup_function_type(const interned_string& type_name,
+                    const translation_unit& tu)
+{
+  const type_maps& m = tu.get_types();
+  return lookup_type_in_map<function_type>(type_name,
+                                          m.function_types());
+}
+
+/// Lookup a function type from a translation unit.
+///
+/// This walks all the function types held by the translation unit and
+/// compare their sub-type *names*.  If the names match then return
+/// the function type found in the translation unit.
+///
+/// @param t the function type to look for.
+///
+/// @param tu the translation unit to look into.
+///
+/// @return the function type found, or NULL of none was found.
+function_type_sptr
+lookup_function_type(const function_type& t,
+                    const translation_unit& tu)
+{
+  interned_string type_name = get_type_name(t);
+  return lookup_function_type(type_name, tu);
+}
+
+/// Lookup a function type from a translation unit.
+///
+/// This is done by looking the type up in the type map that is
+/// maintained in the translation unit.  So this is as fast as
+/// possible.
+///
+/// @param t the function type to look for.
+///
+/// @param tu the translation unit to look into.
+///
+/// @return the function type found, or NULL of none was found.
+function_type_sptr
+lookup_function_type(const function_type_sptr& t,
+                    const translation_unit& tu)
+{return lookup_function_type(*t, tu);}
+
+/// Lookup a type in a translation unit.
+///
+/// @param fqn the fully qualified name of the type to lookup.
+///
+/// @param tu the translation unit to consider.
+///
+/// @return the declaration of the type if found, NULL otherwise.
+const type_base_sptr
+lookup_type(const interned_string& fqn,
+           const translation_unit& tu)
+{
+  type_base_sptr result;
+  ((result = lookup_typedef_type(fqn, tu))
+   || (result = lookup_class_type(fqn, tu))
+   || (result = lookup_union_type(fqn, tu))
+   || (result = lookup_enum_type(fqn, tu))
+   || (result = lookup_qualified_type(fqn, tu))
+   || (result = lookup_pointer_type(fqn, tu))
+   || (result = lookup_reference_type(fqn, tu))
+   || (result = lookup_array_type(fqn, tu))
+   || (result = lookup_function_type(fqn, tu))
+   || (result = lookup_basic_type(fqn, tu)));
+
+  return result;
+}
+
+/// Lookup a type in a translation unit, starting from the global
+/// namespace.
+///
+/// @param fqn the fully qualified name of the type to lookup.
+///
+/// @param tu the translation unit to consider.
+///
+/// @return the declaration of the type if found, NULL otherwise.
+type_base_sptr
+lookup_type(const string& fqn, const translation_unit& tu)
+{
+  const environment *env = tu.get_environment();
+  assert(env);
+  interned_string ifqn = env->intern(fqn);
+  return lookup_type(ifqn, tu);
+}
+
+/// Lookup a type from a translation unit.
+///
+/// @param fqn the components of the fully qualified name of the node
+/// to look up.
+///
+/// @param tu the translation unit to perform lookup from.
+///
+/// @return the declaration of the IR node found, NULL otherwise.
+const type_base_sptr
+lookup_type(const type_base_sptr type,
+           const translation_unit& tu)
+{
+  interned_string type_name = get_type_name(type);
+  return lookup_type(type_name, tu);
+}
+
+/// Lookup a type in a scope.
+///
+/// This is really slow as it walks the member types of the scope in
+/// sequence to find the type with a given name.
+///
+/// If possible, users should prefer looking up types from the
+/// enclosing translation unit or even ABI corpus because both the
+/// translation unit and the corpus have a map of type, indexed by
+/// their name.  Looking up a type from those maps is thus much
+/// faster.
+///
+/// @param fqn the fully qualified name of the type to lookup.
+///
+/// @param skope the scope to look into.
+///
+/// @return the declaration of the type if found, NULL otherwise.
+const type_base_sptr
+lookup_type_in_scope(const string& fqn,
+                    const scope_decl_sptr& skope)
+{
+  list<string> comps;
+  fqn_to_components(fqn, comps);
+  return lookup_type_in_scope(comps, skope);
+}
+
+/// Lookup a @ref var_decl in a scope.
+///
+/// @param fqn the fuly qualified name of the @var_decl to lookup.
+///
+/// @param skope the scope to look into.
+///
+/// @return the declaration of the @ref var_decl if found, NULL
+/// otherwise.
+const decl_base_sptr
+lookup_var_decl_in_scope(const string& fqn,
+                        const scope_decl_sptr& skope)
+{
+  list<string> comps;
+  fqn_to_components(fqn, comps);
+  return lookup_var_decl_in_scope(comps, skope);
+}
+
+/// A generic function (template) to get the name of a node, whatever
+/// node it is.  This has to be specialized for the kind of node we
+/// want.
+///
+/// Note that a node is a member of a scope.
+///
+/// @tparam NodeKind the kind of node to consider.
+///
+/// @param node the node to get the name from.
+///
+/// @return the name of the node.
+template<typename NodeKind>
+static const interned_string&
+get_node_name(shared_ptr<NodeKind> node);
+
+/// Gets the name of a class_decl node.
+///
+/// @param node the decl_base node to get the name from.
+///
+/// @return the name of the node.
+template<>
+const interned_string&
+get_node_name(class_decl_sptr node)
+{return node->get_name();}
+
+/// Gets the name of a type_base node.
+///
+/// @param node the type_base node to get the name from.
+///
+/// @return the name of the node.
+template<>
+const interned_string&
+get_node_name(type_base_sptr node)
+{return get_type_declaration(node)->get_name();}
+
+/// Gets the name of a var_decl node.
+///
+/// @param node the var_decl node to get the name from.
 ///
 /// @return the name of the node.
 template<>
@@ -6693,8 +6927,8 @@ convert_node_to_decl(var_decl_sptr node)
 ///
 /// @tparam the type of the node to lookup.
 ///
-/// @param fqn the components of the fully qualified name of the the
-/// node to lookup.
+/// @param fqn the components of the fully qualified name of the node
+/// to lookup.
 ///
 /// @param skope the scope to look into.
 ///
@@ -6755,6 +6989,16 @@ lookup_node_in_scope(const list<string>& fqn,
 
 /// lookup a type in a scope.
 ///
+///
+/// This is really slow as it walks the member types of the scope in
+/// sequence to find the type with a given name.
+///
+/// If possible, users should prefer looking up types from the
+/// enclosing translation unit or even ABI corpus because both the
+/// translation unit and the corpus have a map of type, indexed by
+/// their name.  Looking up a type from those maps is thus much
+/// faster.
+///
 /// @param comps the components of the fully qualified name of the
 /// type to lookup.
 ///
@@ -6768,6 +7012,15 @@ lookup_type_in_scope(const list<string>& comps,
 
 /// lookup a type in a scope.
 ///
+/// This is really slow as it walks the member types of the scope in
+/// sequence to find the type with a given name.
+///
+/// If possible, users should prefer looking up types from the
+/// enclosing translation unit or even ABI corpus because both the
+/// translation unit and the corpus have a map of type, indexed by
+/// their name.  Looking up a type from those maps is thus much
+/// faster.
+///
 /// @param type the type to look for.
 ///
 /// @param access_path a vector of scopes the path of scopes to follow
@@ -6830,6 +7083,15 @@ lookup_type_in_scope(const type_base& type,
 
 /// lookup a type in a scope.
 ///
+/// This is really slow as it walks the member types of the scope in
+/// sequence to find the type with a given name.
+///
+/// If possible, users should prefer looking up types from the
+/// enclosing translation unit or even ABI corpus because both the
+/// translation unit and the corpus have a map of type, indexed by
+/// their name.  Looking up a type from those maps is thus much
+/// faster.
+///
 /// @param type the type to look for.
 ///
 /// @param scope the top-most scope into which to look for @p type.
@@ -6854,6 +7116,34 @@ lookup_type_in_scope(const type_base_sptr type,
   return lookup_type_in_scope(*type, access_path, scope);
 }
 
+/// Lookup a type from a translation unit by walking the scopes of the
+/// translation unit in sequence and looking into them.
+///
+/// This is really slow as it walks the member types of the scopes in
+/// sequence to find the type with a given name.
+///
+/// If possible, users should prefer looking up types from the
+/// translation unit or even ABI corpus in a more direct way, by using
+/// the lookup_type() functins.
+///
+///
+/// This is because both the translation unit and the corpus have a
+/// map of types, indexed by their name.  Looking up a type from those
+/// maps is thus much faster.  @param fqn the components of the fully
+/// qualified name of the node to look up.
+///
+/// @param tu the translation unit to perform lookup from.
+///
+/// @return the declaration of the IR node found, NULL otherwise.
+const type_base_sptr
+lookup_type_through_scopes(const type_base_sptr type,
+                          const translation_unit& tu)
+{
+  if (function_type_sptr fn_type = is_function_type(type))
+    return lookup_function_type(fn_type, tu);
+  return lookup_type_in_scope(type, tu.get_global_scope().get());
+}
+
 /// lookup a var_decl in a scope.
 ///
 /// @param comps the components of the fully qualified name of the
@@ -6882,7 +7172,10 @@ lookup_node_in_translation_unit(const list<string>& fqn,
                                const translation_unit& tu)
 {return lookup_node_in_scope<NodeKind>(fqn, tu.get_global_scope());}
 
-/// Lookup a type from a translation unit.
+/// Lookup a type from a translation unit by walking its scopes in
+/// sequence and by looking into them.
+///
+/// This is much slower than using the lookup_type() function.
 ///
 /// @param fqn the components of the fully qualified name of the node
 /// to look up.
@@ -6893,9 +7186,15 @@ lookup_node_in_translation_unit(const list<string>& fqn,
 type_base_sptr
 lookup_type_through_scopes(const list<string>& fqn,
                           const translation_unit& tu)
-{return is_type(lookup_node_in_translation_unit<type_base>(fqn,tu));}
+{return is_type(lookup_node_in_translation_unit<type_base>(fqn, tu));}
 
-/// Lookup a class type from a translation unit.
+
+/// Lookup a class type from a translation unit by walking its scopes
+/// in sequence and by looking into them.
+///
+/// This is much slower than using the lookup_class_type() function
+/// because it walks all the scopes of the translation unit in
+/// sequence and lookup the types to find one that has a given name.
 ///
 /// @param fqn the components of the fully qualified name of the class
 /// type node to look up.
@@ -6904,26 +7203,1585 @@ lookup_type_through_scopes(const list<string>& fqn,
 ///
 /// @return the declaration of the class type IR node found, NULL
 /// otherwise.
-const class_decl_sptr
-lookup_class_type_in_translation_unit(const list<string>& fqn,
-                                     const translation_unit& tu)
+class_decl_sptr
+lookup_class_type_through_scopes(const list<string>& fqn,
+                                const translation_unit& tu)
 {return is_class_type(lookup_node_in_translation_unit<class_decl>(fqn, tu));}
 
-/// Lookup a type from a translation unit.
+/// Lookup a basic type from all the translation units of a given
+/// corpus.
 ///
-/// @param fqn the components of the fully qualified name of the node
-/// to look up.
+/// @param fqn the components of the fully qualified name of the basic
+/// type node to look up.
 ///
 /// @param tu the translation unit to perform lookup from.
 ///
-/// @return the declaration of the IR node found, NULL otherwise.
-const type_base_sptr
-lookup_type_in_translation_unit(const type_base_sptr type,
-                               const translation_unit& tu)
+/// @return the declaration of the basic type IR node found, NULL
+/// otherwise.
+static type_decl_sptr
+lookup_basic_type_through_translation_units(const interned_string& type_name,
+                                           const corpus& abi_corpus)
 {
-  if (function_type_sptr fn_type = is_function_type(type))
-    return lookup_function_type_in_translation_unit(fn_type, tu);
-  return lookup_type_in_scope(type, tu.get_global_scope().get());
+  type_decl_sptr result;
+
+  for (translation_units::const_iterator tu =
+        abi_corpus.get_translation_units().begin();
+       tu != abi_corpus.get_translation_units().end();
+       ++tu)
+    if ((result = lookup_basic_type(type_name, **tu)))
+      break;
+
+  return result;
+}
+
+/// Lookup a union type from all the translation units of a given
+/// corpus.
+///
+/// @param fqn the components of the fully qualified name of the union
+/// type node to look up.
+///
+/// @param tu the translation unit to perform lookup from.
+///
+/// @return the declaration of the union type IR node found, NULL
+/// otherwise.
+static union_decl_sptr
+lookup_union_type_through_translation_units(const interned_string& type_name,
+                                           const corpus & abi_corpus)
+{
+ union_decl_sptr result;
+
+  for (translation_units::const_iterator tu =
+        abi_corpus.get_translation_units().begin();
+       tu != abi_corpus.get_translation_units().end();
+       ++tu)
+    if ((result = lookup_union_type(type_name, **tu)))
+      break;
+
+  return result;
+}
+
+/// Lookup an enum type from all the translation units of a given
+/// corpus.
+///
+/// @param fqn the components of the fully qualified name of the enum
+/// type node to look up.
+///
+/// @param tu the translation unit to perform lookup from.
+///
+/// @return the declaration of the enum type IR node found, NULL
+/// otherwise.
+static enum_type_decl_sptr
+lookup_enum_type_through_translation_units(const interned_string& type_name,
+                                          const corpus & abi_corpus)
+{
+  enum_type_decl_sptr result;
+
+  for (translation_units::const_iterator tu =
+        abi_corpus.get_translation_units().begin();
+       tu != abi_corpus.get_translation_units().end();
+       ++tu)
+    if ((result = lookup_enum_type(type_name, **tu)))
+      break;
+
+  return result;
+}
+
+/// Lookup a class type definition in all the translation units of a
+/// given ABI corpus.
+///
+/// @param @param qn the fully qualified name of the class type to lookup.
+///
+/// @param abi_corpus the ABI corpus which to look the type up in.
+///
+/// @return the type definition if any was found, or a NULL pointer.
+static const class_decl_sptr
+lookup_class_type_through_translation_units(const string& qn,
+                                           const corpus& abi_corpus)
+{
+  class_decl_sptr result;
+
+  for (translation_units::const_iterator tu =
+        abi_corpus.get_translation_units().begin();
+       tu != abi_corpus.get_translation_units().end();
+       ++tu)
+    if ((result = lookup_class_type(qn, **tu)))
+      break;
+
+  return result;
+}
+
+/// Lookup a typedef type definition in all the translation units of a
+/// given ABI corpus.
+///
+/// @param @param qn the fully qualified name of the typedef type to lookup.
+///
+/// @param abi_corpus the ABI corpus which to look the type up in.
+///
+/// @return the type definition if any was found, or a NULL pointer.
+static typedef_decl_sptr
+lookup_typedef_type_through_translation_units(const interned_string& type_name,
+                                             const corpus & abi_corpus)
+{
+  typedef_decl_sptr result;
+
+  for (translation_units::const_iterator tu =
+        abi_corpus.get_translation_units().begin();
+       tu != abi_corpus.get_translation_units().end();
+       ++tu)
+    if ((result = lookup_typedef_type(type_name, **tu)))
+      break;
+
+  return result;
+}
+
+/// Lookup a qualified type definition in all the translation units of a
+/// given ABI corpus.
+///
+/// @param @param qn the fully qualified name of the qualified type to
+/// lookup.
+///
+/// @param abi_corpus the ABI corpus which to look the type up in.
+///
+/// @return the type definition if any was found, or a NULL pointer.
+static qualified_type_def_sptr
+lookup_qualified_type_through_translation_units(const interned_string& t_name,
+                                               const corpus & abi_corpus)
+{
+  qualified_type_def_sptr result;
+
+  for (translation_units::const_iterator tu =
+        abi_corpus.get_translation_units().begin();
+       tu != abi_corpus.get_translation_units().end();
+       ++tu)
+    if ((result = lookup_qualified_type(t_name, **tu)))
+      break;
+
+  return result;
+}
+
+/// Lookup a pointer type definition in all the translation units of a
+/// given ABI corpus.
+///
+/// @param @param qn the fully qualified name of the pointer type to
+/// lookup.
+///
+/// @param abi_corpus the ABI corpus which to look the type up in.
+///
+/// @return the type definition if any was found, or a NULL pointer.
+static pointer_type_def_sptr
+lookup_pointer_type_through_translation_units(const interned_string& type_name,
+                                             const corpus & abi_corpus)
+{
+  pointer_type_def_sptr result;
+
+  for (translation_units::const_iterator tu =
+        abi_corpus.get_translation_units().begin();
+       tu != abi_corpus.get_translation_units().end();
+       ++tu)
+    if ((result = lookup_pointer_type(type_name, **tu)))
+      break;
+
+  return result;
+}
+
+/// Lookup a reference type definition in all the translation units of a
+/// given ABI corpus.
+///
+/// @param @param qn the fully qualified name of the reference type to
+/// lookup.
+///
+/// @param abi_corpus the ABI corpus which to look the type up in.
+///
+/// @return the type definition if any was found, or a NULL pointer.
+static reference_type_def_sptr
+lookup_reference_type_through_translation_units(const interned_string& t_name,
+                                               const corpus & abi_corpus)
+{
+  reference_type_def_sptr result;
+
+  for (translation_units::const_iterator tu =
+        abi_corpus.get_translation_units().begin();
+       tu != abi_corpus.get_translation_units().end();
+       ++tu)
+    if ((result = lookup_reference_type(t_name, **tu)))
+      break;
+
+  return result;
+}
+
+/// Lookup a array type definition in all the translation units of a
+/// given ABI corpus.
+///
+/// @param @param qn the fully qualified name of the array type to
+/// lookup.
+///
+/// @param abi_corpus the ABI corpus which to look the type up in.
+///
+/// @return the type definition if any was found, or a NULL pointer.
+static array_type_def_sptr
+lookup_array_type_through_translation_units(const interned_string& type_name,
+                                           const corpus & abi_corpus)
+{
+  array_type_def_sptr result;
+
+  for (translation_units::const_iterator tu =
+        abi_corpus.get_translation_units().begin();
+       tu != abi_corpus.get_translation_units().end();
+       ++tu)
+    if ((result = lookup_array_type(type_name, **tu)))
+      break;
+
+  return result;
+}
+
+/// Lookup a function type definition in all the translation units of
+/// a given ABI corpus.
+///
+/// @param @param qn the fully qualified name of the function type to
+/// lookup.
+///
+/// @param abi_corpus the ABI corpus which to look the type up in.
+///
+/// @return the type definition if any was found, or a NULL pointer.
+static function_type_sptr
+lookup_function_type_through_translation_units(const interned_string& type_name,
+                                              const corpus & abi_corpus)
+{
+  function_type_sptr result;
+
+  for (translation_units::const_iterator tu =
+        abi_corpus.get_translation_units().begin();
+       tu != abi_corpus.get_translation_units().end();
+       ++tu)
+    if ((result = lookup_function_type(type_name, **tu)))
+      break;
+
+  return result;
+}
+
+/// Lookup a type definition in all the translation units of a given
+/// ABI corpus.
+///
+/// @param @param qn the fully qualified name of the type to lookup.
+///
+/// @param abi_corpus the ABI corpus which to look the type up in.
+///
+/// @return the type definition if any was found, or a NULL pointer.
+type_base_sptr
+lookup_type_through_translation_units(const string& qn,
+                                     const corpus& abi_corpus)
+{
+  type_base_sptr result;
+
+  for (translation_units::const_iterator tu =
+        abi_corpus.get_translation_units().begin();
+       tu != abi_corpus.get_translation_units().end();
+       ++tu)
+    if ((result = lookup_type(qn, **tu)))
+      break;
+
+  return result;
+}
+
+/// Look into an ABI corpus for a function type.
+///
+/// @param fn_type the function type to be looked for in the ABI
+/// corpus.
+///
+/// @param corpus the ABI corpus into which to look for the function
+/// type.
+///
+/// @return the function type found in the corpus.
+function_type_sptr
+lookup_or_synthesize_fn_type(const function_type_sptr& fn_t,
+                            const corpus& corpus)
+{
+  assert(fn_t);
+
+  function_type_sptr result;
+
+  if ((result = lookup_function_type(fn_t, corpus)))
+    return result;
+
+  for (translation_units::const_iterator i =
+        corpus.get_translation_units().begin();
+       i != corpus.get_translation_units().end();
+       ++i)
+    if ((result = synthesize_function_type_from_translation_unit(*fn_t,
+                                                                **i)))
+      return result;
+
+  return result;
+}
+
+/// Look into a given corpus to find a type which has the same
+/// qualified name as a giventype.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param t the type which has the same qualified name as the type we
+/// are looking for.
+///
+/// @param corp the ABI corpus to look into for the type.
+type_decl_sptr
+lookup_basic_type(const type_decl& t, const corpus& corp)
+{return lookup_basic_type(t.get_name(), corp);}
+
+/// Look into a given corpus to find a basic type which has a given
+/// qualified name.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param qualified_name the qualified name of the basic type to look
+/// for.
+///
+/// @param corp the corpus to look into.
+type_decl_sptr
+lookup_basic_type(const interned_string &qualified_name, const corpus& corp)
+{
+  const istring_type_base_wptr_map_type& m = corp.get_types().basic_types();
+  type_decl_sptr result;
+
+  if (!m.empty())
+    result = lookup_type_in_map<type_decl>(qualified_name, m);
+  else
+    result = lookup_basic_type_through_translation_units(qualified_name, corp);
+
+  return result;
+}
+
+/// Look into a given corpus to find a basic type which has a given
+/// qualified name.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param qualified_name the qualified name of the basic type to look
+/// for.
+///
+/// @param corp the corpus to look into.
+type_decl_sptr
+lookup_basic_type(const string& qualified_name, const corpus& corp)
+{
+  return lookup_basic_type(corp.get_environment()->intern(qualified_name),
+                          corp);
+}
+
+/// Look into a given corpus to find a class type which has the same
+/// qualified name as a given type.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param t the class decl type which has the same qualified name as
+/// the type we are looking for.
+///
+/// @param corp the corpus to look into.
+class_decl_sptr
+lookup_class_type(const class_decl& t, const corpus& corp)
+{
+  interned_string s = get_type_name(t);
+  return lookup_class_type(s, corp);
+}
+
+/// Look into a given corpus to find a class type which has a given
+/// qualified name.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param qualified_name the qualified name of the type to look for.
+///
+/// @param corp the corpus to look into.
+class_decl_sptr
+lookup_class_type(const string& qualified_name, const corpus& corp)
+{
+  interned_string s = corp.get_environment()->intern(qualified_name);
+  return lookup_class_type(s, corp);
+}
+
+/// Look into a given corpus to find a class type which has a given
+/// qualified name.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param qualified_name the qualified name of the type to look for.
+///
+/// @param corp the corpus to look into.
+class_decl_sptr
+lookup_class_type(const interned_string& qualified_name, const corpus& corp)
+{
+  const istring_type_base_wptr_map_type& m = corp.get_types().class_types();
+
+  class_decl_sptr result = lookup_type_in_map<class_decl>(qualified_name, m);
+  if (!result)
+    result = lookup_class_type_through_translation_units(qualified_name, corp);
+
+  return result;
+}
+
+/// Look into a given corpus to find a union type which has a given
+/// qualified name.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param qualified_name the qualified name of the type to look for.
+///
+/// @param corp the corpus to look into.
+union_decl_sptr
+lookup_union_type(const interned_string& type_name, const corpus& corp)
+{
+  const istring_type_base_wptr_map_type& m = corp.get_types().union_types();
+
+  union_decl_sptr result = lookup_type_in_map<union_decl>(type_name, m);
+  if (!result)
+    result = lookup_union_type_through_translation_units(type_name, corp);
+
+  return result;
+}
+
+/// Look into a given corpus to find a union type which has a given
+/// qualified name.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param qualified_name the qualified name of the type to look for.
+///
+/// @param corp the corpus to look into.
+union_decl_sptr
+lookup_union_type(const string& type_name, const corpus& corp)
+{
+  interned_string s = corp.get_environment()->intern(type_name);
+  return lookup_union_type(s, corp);
+}
+
+/// Look into a given corpus to find a enum type which has the same
+/// qualified name as a given enum type.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param t the enum type which has the same qualified name as the
+/// type we are looking for.
+///
+/// @param corp the corpus to look into.
+enum_type_decl_sptr
+lookup_enum_type(const enum_type_decl& t, const corpus& corp)
+{
+  interned_string s = get_type_name(t);
+  return lookup_enum_type(s, corp);
+}
+
+/// Look into a given corpus to find an enum type which has a given
+/// qualified name.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param qualified_name the qualified name of the enum type to look
+/// for.
+///
+/// @param corp the corpus to look into.
+enum_type_decl_sptr
+lookup_enum_type(const string& qualified_name, const corpus& corp)
+{
+  interned_string s = corp.get_environment()->intern(qualified_name);
+  return lookup_enum_type(s, corp);
+}
+
+/// Look into a given corpus to find an enum type which has a given
+/// qualified name.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param qualified_name the qualified name of the enum type to look
+/// for.
+///
+/// @param corp the corpus to look into.
+enum_type_decl_sptr
+lookup_enum_type(const interned_string& qualified_name, const corpus& corp)
+{
+  const istring_type_base_wptr_map_type& m = corp.get_types().enum_types();
+
+  enum_type_decl_sptr result =
+    lookup_type_in_map<enum_type_decl>(qualified_name, m);
+  if (!result)
+    result = lookup_enum_type_through_translation_units(qualified_name, corp);
+
+  return result;
+}
+
+/// Look into a given corpus to find a typedef type which has the
+/// same qualified name as a given typedef type.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param t the typedef type which has the same qualified name as the
+/// typedef type we are looking for.
+///
+/// @param corp the corpus to look into.
+typedef_decl_sptr
+lookup_typedef_type(const typedef_decl& t, const corpus& corp)
+{
+  interned_string s = get_type_name(t);
+  return lookup_typedef_type(s, corp);
+}
+
+/// Look into a given corpus to find a typedef type which has the
+/// same qualified name as a given typedef type.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param t the typedef type which has the same qualified name as the
+/// typedef type we are looking for.
+///
+/// @param corp the corpus to look into.
+typedef_decl_sptr
+lookup_typedef_type(const string& qualified_name, const corpus& corp)
+{
+  interned_string s = corp.get_environment()->intern(qualified_name);
+  return lookup_typedef_type(s, corp);
+}
+
+/// Look into a given corpus to find a typedef type which has a
+/// given qualified name.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param qualified_name the qualified name of the typedef type to
+/// look for.
+///
+/// @param corp the corpus to look into.
+typedef_decl_sptr
+lookup_typedef_type(const interned_string& qualified_name, const corpus& corp)
+{
+  const istring_type_base_wptr_map_type& m = corp.get_types().typedef_types();
+
+  typedef_decl_sptr result =
+    lookup_type_in_map<typedef_decl>(qualified_name, m);
+  if (!result)
+    result = lookup_typedef_type_through_translation_units(qualified_name,
+                                                          corp);
+
+  return result;
+}
+
+/// Look into a corpus to find a class or typedef type which has a
+/// given qualified name.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param qualified_name the name of the type to find.
+///
+/// @param corp the corpus to look into.
+///
+/// @return the typedef or class type found.
+type_base_sptr
+lookup_class_or_typedef_type(const string& qualified_name, const corpus& corp)
+{
+  type_base_sptr result = lookup_class_type(qualified_name, corp);
+  if (!result)
+    result = lookup_typedef_type(qualified_name, corp);
+  return result;
+}
+
+/// Look into a corpus to find a class, typedef or enum type which has
+/// a given qualified name.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param qualified_name the qualified name of the type to look for.
+///
+/// @param corp the corpus to look into.
+///
+/// @return the typedef, class or enum type found.
+type_base_sptr
+lookup_class_typedef_or_enum_type(const string& qualified_name,
+                                 const corpus& corp)
+{
+  type_base_sptr result = lookup_class_or_typedef_type(qualified_name, corp);
+  if (!result)
+    result = lookup_enum_type(qualified_name, corp);
+
+  return result;
+}
+
+/// Look into a given corpus to find a qualified type which has the
+/// same qualified name as a given type.
+///
+/// @param t the type which has the same qualified name as the
+/// qualified type we are looking for.
+///
+/// @param corp the corpus to look into.
+///
+/// @return the qualified type found.
+qualified_type_def_sptr
+lookup_qualified_type(const qualified_type_def& t, const corpus& corp)
+{
+  interned_string s = get_type_name(t);
+  return lookup_qualified_type(s, corp);
+}
+
+/// Look into a given corpus to find a qualified type which has a
+/// given qualified name.
+///
+/// @param qualified_name the qualified name of the type to look for.
+///
+/// @param corp the corpus to look into.
+///
+/// @return the type found.
+qualified_type_def_sptr
+lookup_qualified_type(const interned_string& qualified_name, const corpus& corp)
+{
+  const istring_type_base_wptr_map_type& m = corp.get_types().qualified_types();
+
+  qualified_type_def_sptr result =
+    lookup_type_in_map<qualified_type_def>(qualified_name, m);
+
+  if (!result)
+    result = lookup_qualified_type_through_translation_units(qualified_name,
+                                                            corp);
+
+  return result;
+}
+
+/// Look into a given corpus to find a pointer type which has the same
+/// qualified name as a given pointer type.
+///
+/// @param t the pointer type which has the same qualified name as the
+/// type we are looking for.
+///
+/// @param corp the corpus to look into.
+///
+/// @return the pointer type found.
+pointer_type_def_sptr
+lookup_pointer_type(const pointer_type_def& t, const corpus& corp)
+{
+  interned_string s = get_type_name(t);
+  return lookup_pointer_type(s, corp);
+}
+
+/// Look into a given corpus to find a pointer type which has a given
+/// qualified name.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param qualified_name the qualified name of the pointer type to
+/// look for.
+///
+/// @param corp the corpus to look into.
+///
+/// @return the pointer type found.
+pointer_type_def_sptr
+lookup_pointer_type(const interned_string& qualified_name, const corpus& corp)
+{
+  const istring_type_base_wptr_map_type& m = corp.get_types().pointer_types();
+
+  pointer_type_def_sptr result =
+    lookup_type_in_map<pointer_type_def>(qualified_name, m);
+  if (!result)
+    result = lookup_pointer_type_through_translation_units(qualified_name,
+                                                          corp);
+
+  return result;
+}
+
+/// Look into a given corpus to find a reference type which has the
+/// same qualified name as a given reference type.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param t the reference type which has the same qualified name as
+/// the reference type we are looking for.
+///
+/// @param corp the corpus to look into.
+///
+/// @return the reference type found.
+reference_type_def_sptr
+lookup_reference_type(const reference_type_def& t, const corpus& corp)
+{
+  interned_string s = get_type_name(t);
+  return lookup_reference_type(s, corp);
+}
+
+/// Look into a given corpus to find a reference type which has a
+/// given qualified name.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param qualified_name the qualified name of the reference type to
+/// look for.
+///
+/// @param corp the corpus to look into.
+///
+/// @return the reference type found.
+reference_type_def_sptr
+lookup_reference_type(const interned_string& qualified_name, const corpus& corp)
+{
+  const istring_type_base_wptr_map_type& m = corp.get_types().reference_types();
+
+  reference_type_def_sptr result =
+    lookup_type_in_map<reference_type_def>(qualified_name, m);
+  if (!result)
+    result = lookup_reference_type_through_translation_units(qualified_name,
+                                                            corp);
+
+  return result;
+}
+
+/// Look into a given corpus to find an array type which has a given
+/// qualified name.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param qualified_name the qualified name of the array type to look
+/// for.
+///
+/// @param corp the corpus to look into.
+///
+/// @return the array type found.
+array_type_def_sptr
+lookup_array_type(const array_type_def& t, const corpus& corp)
+{
+  interned_string s = get_type_name(t);
+  return lookup_array_type(s, corp);
+}
+
+/// Look into a given corpus to find an array type which has the same
+/// qualified name as a given array type.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param t the type which has the same qualified name as the type we
+/// are looking for.
+///
+/// @param corp the corpus to look into.
+///
+/// @return the type found.
+array_type_def_sptr
+lookup_array_type(const interned_string& qualified_name, const corpus& corp)
+{
+  const istring_type_base_wptr_map_type& m = corp.get_types().array_types();
+
+  array_type_def_sptr result =
+    lookup_type_in_map<array_type_def>(qualified_name, m);
+  if (!result)
+    result = lookup_array_type_through_translation_units(qualified_name, corp);
+
+  return result;
+}
+
+/// Look into a given corpus to find a function type which has the same
+/// qualified name as a given function type.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param t the function type which has the same qualified name as
+/// the function type we are looking for.
+///
+/// @param corp the corpus to look into.
+///
+/// @return the function type found.
+function_type_sptr
+lookup_function_type(const function_type&t, const corpus& corp)
+{
+  interned_string type_name = get_type_name(t);
+  return lookup_function_type(type_name, corp);
+}
+
+/// Look into a given corpus to find a function type which has the same
+/// qualified name as a given function type.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param t the function type which has the same qualified name as
+/// the function type we are looking for.
+///
+/// @param corp the corpus to look into.
+///
+/// @return the function type found.
+function_type_sptr
+lookup_function_type(const function_type_sptr& fn_t,
+                    const corpus& corpus)
+{
+  if (fn_t)
+    return lookup_function_type(*fn_t, corpus);
+  return function_type_sptr();
+}
+
+/// Look into a given corpus to find a function type which has a given
+/// qualified name.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param qualified_name the qualified name of the function type to
+/// look for.
+///
+/// @param corp the corpus to look into.
+///
+/// @return the function type found.
+function_type_sptr
+lookup_function_type(const interned_string& qualified_name, const corpus& corp)
+{
+  const istring_type_base_wptr_map_type& m = corp.get_types().function_types();
+
+  function_type_sptr result =
+    lookup_type_in_map<function_type>(qualified_name, m);
+  if (!result)
+    result = lookup_function_type_through_translation_units(qualified_name,
+                                                           corp);
+
+  return result;
+}
+
+/// Look into a given corpus to find a type which has a given
+/// qualified name.
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param qualified_name the qualified name of the function type to
+/// look for.
+///
+/// @param corp the corpus to look into.
+///
+/// @return the function type found.
+type_base_sptr
+lookup_type(const interned_string& n, const corpus& corp)
+{
+  type_base_sptr result;
+
+  ((result = lookup_basic_type(n, corp))
+   || (result = lookup_class_type(n, corp))
+   || (result = lookup_union_type(n, corp))
+   || (result = lookup_enum_type(n, corp))
+   || (result = lookup_typedef_type(n, corp))
+   || (result = lookup_qualified_type(n, corp))
+   || (result = lookup_pointer_type(n, corp))
+   || (result = lookup_reference_type(n, corp))
+   || (result = lookup_array_type(n, corp))
+   || (result= lookup_function_type(n, corp)));
+
+  return result;
+}
+
+/// Look into a given corpus to find a type
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param qualified_name the qualified name of the function type to
+/// look for.
+///
+/// @param corp the corpus to look into.
+///
+/// @return the function type found.
+type_base_sptr
+lookup_type(const type_base&t, const corpus& corp)
+{
+  interned_string n = get_type_name(t);
+  return lookup_type(n, corp);
+}
+
+/// Look into a given corpus to find a type
+///
+/// If the per-corpus type map is non-empty (because the corpus allows
+/// the One Definition Rule) then the type islooked up in that
+/// per-corpus type map.  Otherwise, the type is looked-up in each
+/// translation unit.
+///
+/// @param qualified_name the qualified name of the function type to
+/// look for.
+///
+/// @param corp the corpus to look into.
+///
+/// @return the function type found.
+type_base_sptr
+lookup_type(const type_base_sptr&t, const corpus& corp)
+{
+  if (t)
+    return lookup_type(*t, corp);
+  return type_base_sptr();
+}
+
+/// Update the map that associates a fully qualified name of a given
+/// type to that type.
+///
+///
+/// @param type the type we are considering.
+///
+/// @param types_map the map to update.  It's a map that assciates a
+/// fully qualified name of a type to the type itself.
+///
+/// @param erase_if_exists_already if true and if a type with a given
+/// name already exists in the map @p types_map, then erase the type
+/// that exists already.  Otherwise, if this parameter is false, if a
+/// type with the same name already exists in the map, then, do
+/// nothing; do not even update the map in that case.
+///
+/// @return true iff the type was added to the map.
+template<typename TypeKind>
+bool
+maybe_update_types_lookup_map(const shared_ptr<TypeKind>& type,
+                             istring_type_base_wptr_map_type& types_map,
+                             bool erase_if_exists_already = false)
+{
+  interned_string s = get_type_name(type);
+  istring_type_base_wptr_map_type::iterator i = types_map.find(s);
+  bool result = false;
+
+  if (types_map.find(s) == types_map.end())
+    {
+      types_map[s]= type;
+      result = true;
+    }
+  else if (erase_if_exists_already)
+    types_map.erase(i);
+
+  return result;
+}
+
+/// This is the specialization for type @ref class_decl of the
+/// function template:
+///
+///    maybe_update_types_lookup_map<T>(scope_decl*,
+///                                    const shared_ptr<T>&,
+///                                    istring_type_base_wptr_map_type&)
+///
+/// @param class_type the type to consider.
+///
+/// @param types_map the type map to update.
+///
+/// @param erase_if_exists_already if true and if a type with a given
+/// name already exists in the map @p types_map, then erase the type
+/// that exists already.  Otherwise, if this parameter is false, if a
+/// type with the same name already exists in the map, then, do
+/// nothing; do not even update the map in that case.
+///
+/// @return true iff the type was added to the map.
+template<>
+bool
+maybe_update_types_lookup_map<class_decl>(const class_decl_sptr& class_type,
+                                         istring_type_base_wptr_map_type& map,
+                                         bool erase_if_exists_already)
+{
+  class_decl_sptr type = class_type;
+
+  bool update_qname_map = true;
+  if (type->get_is_declaration_only())
+    {
+      if (class_decl_sptr def = class_type->get_definition_of_declaration())
+       type = def;
+      else
+       update_qname_map = false;
+    }
+
+  if (!update_qname_map)
+    return false;
+
+  string qname = type->get_qualified_name();
+  interned_string s = type->get_environment()->intern(qname);
+  bool result = false;
+  istring_type_base_wptr_map_type::iterator i = map.find(s);
+  if (i == map.end())
+    {
+      map[s]= type;
+      result = true;
+    }
+  else if (erase_if_exists_already)
+    map.erase(i);
+
+  return result;
+}
+
+/// This is the specialization for type @ref function_type of the
+/// function template:
+///
+///    maybe_update_types_lookup_map<T>(scope_decl*,
+///                                    const shared_ptr<T>&,
+///                                    istring_type_base_wptr_map_type&)
+///
+/// @param scope the scope of the type to consider.
+///
+/// @param class_type the type to consider.
+///
+/// @param types_map the type map to update.
+///
+/// @param erase_if_exists_already if true and if a type with a given
+/// name already exists in the map @p types_map, then erase the type
+/// that exists already.  Otherwise, if this parameter is false, if a
+/// type with the same name already exists in the map, then, do
+/// nothing; do not even update the map in that case.
+///
+/// @return true iff the type was added to the map.
+template<>
+bool
+maybe_update_types_lookup_map<function_type>
+(const function_type_sptr& type,
+ istring_type_base_wptr_map_type& types_map,
+ bool erase_if_exists_already)
+{
+  bool result = false;
+  interned_string s = get_type_name(type);
+  istring_type_base_wptr_map_type::iterator i = types_map.find(s);
+  if (i == types_map.end())
+    {
+      types_map[s]= type;
+      result = true;
+    }
+  else if (erase_if_exists_already)
+    types_map.erase(i);
+
+  return result;
+}
+
+/// Update the map that associates the fully qualified name of a basic
+/// type with the type itself.
+///
+/// The per-translation unit type map is updated if no type with this
+/// name was already existing in that map.
+///
+/// If no type with this name did already exist in the per-corpus type
+/// map, then that per-corpus type map is updated. Otherwise, that
+/// type is erased from that per-corpus map.
+///
+/// @param basic_type the basic type to consider.
+void
+maybe_update_types_lookup_map(const type_decl_sptr& basic_type)
+{
+  if (translation_unit *tu = basic_type->get_translation_unit())
+    maybe_update_types_lookup_map<type_decl>
+      (basic_type, tu->get_types().basic_types());
+
+  if (corpus *type_corpus = basic_type->get_corpus())
+    maybe_update_types_lookup_map<type_decl>
+      (basic_type,
+       type_corpus->priv_->get_types().basic_types(),
+       /*erase_if_exists_already=*/true);
+}
+
+/// Update the map that associates the fully qualified name of a class
+/// type with the type itself.
+///
+/// The per-translation unit type map is updated if no type with this
+/// name was already existing in that map.
+///
+/// If no type with this name did already exist in the per-corpus type
+/// map, then that per-corpus type map is updated. Otherwise, that
+/// type is erased from that per-corpus map.
+///
+/// @param class_type the class type to consider.
+void
+maybe_update_types_lookup_map(const class_decl_sptr& class_type)
+{
+  if (translation_unit *tu = class_type->get_translation_unit())
+    maybe_update_types_lookup_map<class_decl>
+      (class_type, tu->get_types().class_types());
+
+  if (corpus *type_corpus = class_type->get_corpus())
+    maybe_update_types_lookup_map<class_decl>
+      (class_type,
+       type_corpus->priv_->get_types().class_types(),
+       /*erase_if_exists_already=*/true);
+}
+
+/// Update the map that associates the fully qualified name of a union
+/// type with the type itself.
+///
+/// The per-translation unit type map is updated if no type with this
+/// name was already existing in that map.
+///
+/// If no type with this name did already exist in the per-corpus type
+/// map, then that per-corpus type map is updated. Otherwise, that
+/// type is erased from that per-corpus map.
+///
+/// @param union_type the union type to consider.
+void
+maybe_update_types_lookup_map(const union_decl_sptr& union_type)
+{
+  if (translation_unit *tu = union_type->get_translation_unit())
+    maybe_update_types_lookup_map<union_decl>
+      (union_type, tu->get_types().union_types());
+
+  if (corpus *type_corpus = union_type->get_corpus())
+    maybe_update_types_lookup_map<union_decl>
+      (union_type,
+       type_corpus->priv_->get_types().union_types(),
+       /*erase_if_exists_already=*/true);
+}
+
+/// Update the map that associates the fully qualified name of an enum
+/// type with the type itself.
+///
+/// The per-translation unit type map is updated if no type with this
+/// name was already existing in that map.
+///
+/// If no type with this name did already exist in the per-corpus type
+/// map, then that per-corpus type map is updated. Otherwise, that
+/// type is erased from that per-corpus map.
+///
+/// @param enum_type the type to consider.
+void
+maybe_update_types_lookup_map(const enum_type_decl_sptr& enum_type)
+
+{
+  if (translation_unit *tu = enum_type->get_translation_unit())
+    maybe_update_types_lookup_map<enum_type_decl>
+      (enum_type, tu->get_types().enum_types());
+
+  if (corpus *type_corpus = enum_type->get_corpus())
+    maybe_update_types_lookup_map<enum_type_decl>
+      (enum_type,
+       type_corpus->priv_->get_types().enum_types(),
+       /*erase_if_exists_already=*/true);
+}
+
+/// Update the map that associates the fully qualified name of a
+/// typedef type with the type itself.
+///
+/// The per-translation unit type map is updated if no type with this
+/// name was already existing in that map.
+///
+/// If no type with this name did already exist in the per-corpus type
+/// map, then that per-corpus type map is updated. Otherwise, that
+/// type is erased from that per-corpus map.
+///
+/// @param typedef_type the type to consider.
+void
+maybe_update_types_lookup_map(const typedef_decl_sptr& typedef_type)
+{
+  if (translation_unit *tu = typedef_type->get_translation_unit())
+    maybe_update_types_lookup_map<typedef_decl>
+      (typedef_type, tu->get_types().typedef_types());
+
+  if (corpus *type_corpus = typedef_type->get_corpus())
+    maybe_update_types_lookup_map<typedef_decl>
+      (typedef_type,
+       type_corpus->priv_->get_types().typedef_types(),
+       /*erase_if_exists_already=*/true);
+}
+
+/// Update the map that associates the fully qualified name of a
+/// qualified type with the type itself.
+///
+/// The per-translation unit type map is updated if no type with this
+/// name was already existing in that map.
+///
+/// If no type with this name did already exist in the per-corpus type
+/// map, then that per-corpus type map is updated. Otherwise, that
+/// type is erased from that per-corpus map.
+///
+/// @param qualified_type the type to consider.
+void
+maybe_update_types_lookup_map(const qualified_type_def_sptr& qualified_type)
+{
+  if (translation_unit *tu = qualified_type->get_translation_unit())
+    maybe_update_types_lookup_map<qualified_type_def>
+      (qualified_type, tu->get_types().qualified_types());
+
+  if (corpus *type_corpus = qualified_type->get_corpus())
+    maybe_update_types_lookup_map<qualified_type_def>
+      (qualified_type,
+       type_corpus->priv_->get_types().qualified_types(),
+       /*erase_if_exists_already=*/true);
+}
+
+/// Update the map that associates the fully qualified name of a
+/// pointer type with the type itself.
+///
+/// The per-translation unit type map is updated if no type with this
+/// name was already existing in that map.
+///
+/// If no type with this name did already exist in the per-corpus type
+/// map, then that per-corpus type map is updated. Otherwise, that
+/// type is erased from that per-corpus map.
+///
+/// @param pointer_type the type to consider.
+void
+maybe_update_types_lookup_map(const pointer_type_def_sptr& pointer_type)
+{
+  if (translation_unit *tu = pointer_type->get_translation_unit())
+    maybe_update_types_lookup_map<pointer_type_def>
+      (pointer_type, tu->get_types().pointer_types());
+
+  if (corpus *type_corpus = pointer_type->get_corpus())
+    maybe_update_types_lookup_map<pointer_type_def>
+      (pointer_type,
+       type_corpus->priv_->get_types().pointer_types(),
+       /*erase_if_exists_already=*/true);
+}
+
+/// Update the map that associates the fully qualified name of a
+/// reference type with the type itself.
+///
+/// The per-translation unit type map is updated if no type with this
+/// name was already existing in that map.
+///
+/// If no type with this name did already exist in the per-corpus type
+/// map, then that per-corpus type map is updated. Otherwise, that
+/// type is erased from that per-corpus map.
+///
+/// @param reference_type the type to consider.
+void
+maybe_update_types_lookup_map(const reference_type_def_sptr& reference_type)
+{
+  if (translation_unit *tu = reference_type->get_translation_unit())
+    maybe_update_types_lookup_map<reference_type_def>
+      (reference_type, tu->get_types().reference_types());
+
+  if (corpus *type_corpus = reference_type->get_corpus())
+    maybe_update_types_lookup_map<reference_type_def>
+      (reference_type,
+       type_corpus->priv_->get_types().reference_types(),
+       /*erase_if_exists_already=*/true);
+}
+
+/// Update the map that associates the fully qualified name of a type
+/// with the type itself.
+///
+/// The per-translation unit type map is updated if no type with this
+/// name was already existing in that map.
+///
+/// If no type with this name did already exist in the per-corpus type
+/// map, then that per-corpus type map is updated. Otherwise, that
+/// type is erased from that per-corpus map.
+///
+/// @param array_type the type to consider.
+void
+maybe_update_types_lookup_map(const array_type_def_sptr& array_type)
+{
+  if (translation_unit *tu = array_type->get_translation_unit())
+    maybe_update_types_lookup_map<array_type_def>
+      (array_type, tu->get_types().array_types());
+
+  if (corpus *type_corpus = array_type->get_corpus())
+    maybe_update_types_lookup_map<array_type_def>
+      (array_type,
+       type_corpus->priv_->get_types().array_types(),
+       /*erase_if_exists_already=*/true);
+}
+
+/// Update the map that associates the fully qualified name of a
+/// function type with the type itself.
+///
+/// The per-translation unit type map is updated if no type with this
+/// name was already existing in that map.
+///
+/// If no type with this name did already exist in the per-corpus type
+/// map, then that per-corpus type map is updated. Otherwise, that
+/// type is erased from that per-corpus map.
+///
+/// @param scope the scope of the function type.
+/// @param fn_type the type to consider.
+void
+maybe_update_types_lookup_map(const function_type_sptr& fn_type)
+{
+  if (translation_unit *tu = fn_type->get_translation_unit())
+    maybe_update_types_lookup_map<function_type>
+      (fn_type, tu->get_types().function_types());
+
+  if (corpus *type_corpus = fn_type->get_corpus())
+    maybe_update_types_lookup_map<function_type>
+      (fn_type,
+       type_corpus->priv_->get_types().function_types(),
+       /*erase_if_exists_already=*/true);
+}
+
+/// Update the map that associates the fully qualified name of a type
+/// declaration with the type itself.
+///
+/// The per-translation unit type map is updated if no type with this
+/// name was already existing in that map.
+///
+/// If no type with this name did already exist in the per-corpus type
+/// map, then that per-corpus type map is updated. Otherwise, that
+/// type is erased from that per-corpus map.
+///
+/// @param decl the declaration of the type to consider.
+void
+maybe_update_types_lookup_map(const decl_base_sptr& decl)
+{
+  if (!is_type(decl))
+    return;
+
+  if (type_decl_sptr basic_type = is_type_decl(decl))
+    maybe_update_types_lookup_map(basic_type);
+  else if (class_decl_sptr class_type = is_class_type(decl))
+    maybe_update_types_lookup_map(class_type);
+  else if (union_decl_sptr union_type = is_union_type(decl))
+    maybe_update_types_lookup_map(union_type);
+  else if (enum_type_decl_sptr enum_type = is_enum_type(decl))
+    maybe_update_types_lookup_map(enum_type);
+  else if (typedef_decl_sptr typedef_type = is_typedef(decl))
+    maybe_update_types_lookup_map(typedef_type);
+  else if (qualified_type_def_sptr qualified_type = is_qualified_type(decl))
+    maybe_update_types_lookup_map(qualified_type);
+  else if (pointer_type_def_sptr pointer_type = is_pointer_type(decl))
+    maybe_update_types_lookup_map(pointer_type);
+  else if (reference_type_def_sptr reference_type = is_reference_type(decl))
+    maybe_update_types_lookup_map(reference_type);
+  else if (array_type_def_sptr array_type = is_array_type(decl))
+    maybe_update_types_lookup_map(array_type);
+  else
+    ABG_ASSERT_NOT_REACHED;
+}
+
+/// Update the map that associates the fully qualified name of a type
+/// with the type itself.
+///
+/// The per-translation unit type map is updated if no type with this
+/// name was already existing in that map.
+///
+/// If no type with this name did already exist in the per-corpus type
+/// map, then that per-corpus type map is updated. Otherwise, that
+/// type is erased from that per-corpus map.
+///
+/// @param type the type to consider.
+void
+maybe_update_types_lookup_map(const type_base_sptr& type)
+{
+  if (decl_base_sptr decl = get_type_declaration(type))
+    maybe_update_types_lookup_map(decl);
+  else
+    ABG_ASSERT_NOT_REACHED;
+}
+
+//--------------------------------
+// </type and decls lookup stuff>
+// ------------------------------
+
+/// In a translation unit, lookup a given type or synthesize it if
+/// it's a qualified type.
+///
+/// So this function first looks the type up in the translation unit.
+/// If it's found, then OK, it's returned.  Otherwise, if it's a
+/// qualified, reference or pointer or function type (a composite
+/// type), lookup the underlying type, synthesize the type we want
+/// from it and return it.
+///
+/// If the underlying types is not not found, then give up and return
+/// nil.
+///
+/// @return the type that was found or the synthesized type.
+type_base_sptr
+synthesize_type_from_translation_unit(const type_base_sptr& type,
+                                     translation_unit& tu)
+{
+  type_base_sptr result;
+
+   result = lookup_type(type, tu);
+
+  if (!result)
+    {
+      if (qualified_type_def_sptr qual = is_qualified_type(type))
+       {
+         type_base_sptr underlying_type =
+           synthesize_type_from_translation_unit(qual->get_underlying_type(),
+                                                 tu);
+         if (underlying_type)
+           {
+             result.reset(new qualified_type_def(underlying_type,
+                                                 qual->get_cv_quals(),
+                                                 qual->get_location()));
+           }
+       }
+      else if (pointer_type_def_sptr p = is_pointer_type(type))
+       {
+         type_base_sptr pointed_to_type =
+           synthesize_type_from_translation_unit(p->get_pointed_to_type(),
+                                                 tu);
+         if (pointed_to_type)
+           {
+             result.reset(new pointer_type_def(pointed_to_type,
+                                               p->get_size_in_bits(),
+                                               p->get_alignment_in_bits(),
+                                               p->get_location()));
+             result->set_environment(pointed_to_type->get_environment());
+           }
+       }
+      else if (reference_type_def_sptr r = is_reference_type(type))
+       {
+         type_base_sptr pointed_to_type =
+           synthesize_type_from_translation_unit(r->get_pointed_to_type(), tu);
+         if (pointed_to_type)
+           {
+             result.reset(new reference_type_def(pointed_to_type,
+                                                 r->is_lvalue(),
+                                                 r->get_size_in_bits(),
+                                                 r->get_alignment_in_bits(),
+                                                 r->get_location()));
+             result->set_environment(pointed_to_type->get_environment());
+           }
+       }
+      else if (function_type_sptr f = is_function_type(type))
+       result = synthesize_function_type_from_translation_unit(*f, tu);
+    }
+
+  if (result)
+    tu.priv_->synthesized_types_.push_back(result);
+
+  return result;
+}
+
+/// In a translation unit, lookup the sub-types that make up a given
+/// function type and if the sub-types are all found, synthesize and
+/// return a function_type with them.
+///
+/// This function is like lookup_function_type_in_translation_unit()
+/// execept that it constructs the function type from the sub-types
+/// found in the translation, rather than just looking for the
+/// function types held by the translation unit.  This can be useful
+/// if the translation unit doesnt hold the function type we are
+/// looking for (i.e, lookup_function_type_in_translation_unit()
+/// returned NULL) but we still want to see if the sub-types of the
+/// function types are present in the translation unit.
+///
+/// @param fn_type the function type to consider.
+///
+/// @param tu the translation unit to look into.
+///
+/// @return the resulting synthesized function type if all its
+/// sub-types have been found, NULL otherwise.
+function_type_sptr
+synthesize_function_type_from_translation_unit(const function_type& fn_type,
+                                              translation_unit& tu)
+{
+  function_type_sptr nil = function_type_sptr();
+
+  environment* env = tu.get_environment();
+  assert(env);
+
+  type_base_sptr return_type = fn_type.get_return_type();
+  type_base_sptr result_return_type;
+  if (!return_type || env->is_void_type(return_type))
+    result_return_type = env->get_void_type();
+  else
+    result_return_type = synthesize_type_from_translation_unit(return_type, tu);
+  if (!result_return_type)
+    return nil;
+
+  function_type::parameters parms;
+  type_base_sptr parm_type;
+  function_decl::parameter_sptr parm;
+  for (function_type::parameters::const_iterator i =
+        fn_type.get_parameters().begin();
+       i != fn_type.get_parameters().end();
+       ++i)
+    {
+      type_base_sptr t = (*i)->get_type();
+      parm_type = synthesize_type_from_translation_unit(t, tu);
+      if (!parm_type)
+       return nil;
+      parm.reset(new function_decl::parameter(parm_type,
+                                             (*i)->get_index(),
+                                             (*i)->get_name(),
+                                             (*i)->get_location(),
+                                             (*i)->get_variadic_marker(),
+                                             (*i)->get_artificial()));
+      parms.push_back(parm);
+    }
+
+  class_or_union_sptr class_type;
+  const method_type* method = is_method_type(&fn_type);
+  if (method)
+    {
+      class_type = is_class_or_union_type
+       (synthesize_type_from_translation_unit(method->get_class_type(), tu));
+      assert(class_type);
+    }
+
+  function_type_sptr result_fn_type;
+
+  if (class_type)
+    result_fn_type.reset(new method_type(result_return_type,
+                                        class_type,
+                                        parms,
+                                        method->get_is_const(),
+                                        fn_type.get_size_in_bits(),
+                                        fn_type.get_alignment_in_bits()));
+  else
+    result_fn_type.reset(new function_type(result_return_type,
+                                          parms,
+                                          fn_type.get_size_in_bits(),
+                                          fn_type.get_alignment_in_bits()));
+
+  tu.priv_->synthesized_types_.push_back(result_fn_type);
+  // The new synthesized type must be in the same environment as its
+  // translation unit.
+  result_fn_type->set_environment(tu.get_environment());
+
+  return result_fn_type;
 }
 
 /// Demangle a C++ mangled name and return the resulting string
index cea5fa70044fbf705cc5018b2b3d0e750ea3b4d5..c715b114fb99045e39686dd1a491c621b04619e9 100644 (file)
@@ -403,8 +403,7 @@ public:
     if (d)
       return (ir::get_translation_unit(d) == get_translation_unit());
     else if (function_type_sptr fn_type = is_function_type(type))
-      return lookup_function_type_in_translation_unit(fn_type,
-                                                     *get_translation_unit());
+      return lookup_function_type(fn_type, *get_translation_unit());
     else
       return false;
   }
index 192a89d07cb2aaea9b6d10c62af8d929ec8b9166..50fcb0258a2de94ca3b6c093b75cd35e5f02a690 100644 (file)
@@ -365,6 +365,24 @@ public:
 
       return r1 < r2;
     }
+
+    /// The comparison operator of the functor.
+    ///
+    /// @param l the first type to consider.
+    ///
+    /// @param r the second type to consider.
+    ///
+    /// @return true if the string representation of type @p l is
+    /// considered to be "less than" the string representation of the
+    /// type @p r.
+    ///
+    /// But when the two string representations are equal (for
+    /// instance, for typedefs that have the same string
+    /// representation), this function compares the type-ids of the
+    /// types.  This allows for a stable result.
+    bool
+    operator()(const type_base_sptr& l, const type_base_sptr& r) const
+    {return operator()(l.get(), r.get());}
   }; // end struct type_ptr_cmp
 
   /// Sort the content of a map of type pointers into a vector.
@@ -389,6 +407,49 @@ public:
     sort(sorted.begin(), sorted.end(), comp);
   }
 
+  /// Sort the content of a map of type pointers into a vector.
+  ///
+  /// The pointers are sorted by using their string representation as
+  /// the key to sort, lexicographically.
+  ///
+  /// @param types the map to sort.
+  ///
+  /// @param sorted the resulted sorted vector.  It's set by this
+  /// function with the result of the sorting.
+  void
+  sort_types(const istring_type_base_wptr_map_type& types,
+            vector<type_base_sptr> &sorted)
+  {
+    for (istring_type_base_wptr_map_type::const_iterator i = types.begin();
+        i != types.end();
+        ++i)
+      sorted.push_back(type_base_sptr(i->second));
+    type_ptr_cmp comp(&m_type_id_map);
+    sort(sorted.begin(), sorted.end(), comp);
+  }
+
+  /// Sort the content of a vector of function types into a vector of
+  /// types.
+  ///
+  /// The pointers are sorted by using their string representation as
+  /// the key to sort, lexicographically.
+  ///
+  /// @param types the vector of function types to store.
+  ///
+  /// @param sorted the resulted sorted vector.  It's set by this
+  /// function with the result of the sorting.
+  void
+  sort_types(const vector<function_type_sptr>& types,
+            vector<type_base_sptr> &sorted)
+  {
+    for (vector<function_type_sptr>::const_iterator i = types.begin();
+        i != types.end();
+        ++i)
+      sorted.push_back(*i);
+    type_ptr_cmp comp(&m_type_id_map);
+    sort(sorted.begin(), sorted.end(), comp);
+  }
+
   /// Flag a type as having been written out to the XML output.
   ///
   /// @param t the type to flag.
@@ -1404,18 +1465,24 @@ write_translation_unit(const translation_unit&  tu,
        }
     }
 
-  typedef scope_decl::function_types function_types;
-  typedef function_types::const_iterator const_fn_iterator;
-  const function_types& t = tu.get_function_types();
+  // Now handle all function types that were not only referenced by
+  // emitted types.
+  const vector<function_type_sptr>& t = tu.get_live_fn_types();
+  vector<type_base_sptr> sorted_types;
+  ctxt.sort_types(t, sorted_types);
 
-  for (const_fn_iterator i = t.begin(); i != t.end(); ++i)
+  for (vector<type_base_sptr>::const_iterator i = sorted_types.begin();
+       i != sorted_types.end();
+       ++i)
     {
-      if (!ctxt.type_is_referenced(*i) || ctxt.type_is_emitted(*i))
+      function_type_sptr fn_type = is_function_type(*i);
+
+      if (!ctxt.type_is_referenced(fn_type) || ctxt.type_is_emitted(fn_type))
        // This function type is either not referenced by any emitted
        // pointer or reference type, or has already been emitted, so skip it.
        continue;
       o << "\n";
-      write_function_type(*i, ctxt, indent + c.get_xml_element_indent());
+      write_function_type(fn_type, ctxt, indent + c.get_xml_element_indent());
     }
 
   o << "\n";
index 3bbf62dee43871758215cf578aa0bcf120e2b4bf..4cca7fe3136128adc7fa1cff87c089de6f5601c6 100644 (file)
@@ -500,7 +500,13 @@ perform_compat_check_in_weak_mode(options& opts,
       {
        lib_fn_type = (*i)->get_type();
        assert(lib_fn_type);
-       app_fn_type = lookup_function_type_in_corpus(lib_fn_type, *app_corpus);
+
+       // app_fn_type contains the the "version" of lib_fn_type that
+       // is expected by app_corpus.
+       app_fn_type = lookup_or_synthesize_fn_type(lib_fn_type, *app_corpus);
+
+       // Now lets compare the type expected by app_corpus against
+       // the type actually provided by lib_fn_type.
        function_type_diff_sptr fn_type_diff;
        if (app_fn_type)
          fn_type_diff = compute_diff(app_fn_type, lib_fn_type, ctxt);
@@ -546,7 +552,7 @@ perform_compat_check_in_weak_mode(options& opts,
       {
        lib_var_type = (*i)->get_type();
        assert(lib_var_type);
-       app_var_type = lookup_type_in_corpus(lib_var_type, *app_corpus);
+       app_var_type = lookup_type(lib_var_type, *app_corpus);
        diff_sptr type_diff;
        if (app_var_type)
          type_diff = compute_diff(app_var_type, lib_var_type, ctxt);