// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// -*- mode: C++ -*-
//
// Copyright (C) 2013-2020 Red Hat, Inc.

/// @file

#include "config.h"

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <stdexcept>
#include <unordered_map>

#include "abg-internal.h"

// <headers defining libabigail's API go under here>
ABG_BEGIN_EXPORT_DECLARATIONS

#include "abg-corpus.h"
#include "abg-ir.h"
#include "abg-reader.h"
#include "abg-sptr-utils.h"
#include "abg-symtab-reader.h"
#include "abg-tools-utils.h"
#include "abg-writer.h"

#if WITH_ZIP_ARCHIVE
#include "abg-libzip-utils.h"
#endif

ABG_END_EXPORT_DECLARATIONS
// </headers defining libabigail's API>

#include "abg-corpus-priv.h"
#include "abg-ir-priv.h"

namespace abigail
{

namespace ir
{

using std::ostringstream;
using std::unordered_map;
using std::list;
using std::vector;

#if WITH_ZIP_ARCHIVE
using zip_utils::zip_sptr;
using zip_utils::zip_file_sptr;
using zip_utils::open_archive;
using zip_utils::open_file_in_archive;
#endif // WITH_ZIP_ARCHIVE

using regex::regex_t_sptr;

/// Constructor of @ref corpus::exported_decls_builder.
///
/// @param fns a reference to the vector of exported functions.
///
/// @param vars a reference to the vector of exported variables.
///
/// @param fns_suppress_regexps the regular expressions that designate
/// the functions to suppress from the exported functions set.
///
/// @param vars_suppress_regexps the regular expressions that designate
/// the variables to suppress from the exported variables set.
///
/// @param fns_keep_regexps the regular expressions that designate the
/// functions to keep in the exported functions set.
///
/// @param fns_keep_regexps the regular expressions that designate the
/// functions to keep in the exported functions set.
///
/// @param vars_keep_regexps the regular expressions that designate
/// the variables to keep in the exported variables set.
///
/// @param sym_id_of_fns_to_keep the IDs of the functions to keep in
/// the exported functions set.
///
/// @param sym_id_of_vars_to_keep the IDs of the variables to keep in
/// the exported variables set.
corpus::exported_decls_builder
::exported_decls_builder(functions&	fns,
			 variables&	vars,
			 strings_type&	fns_suppress_regexps,
			 strings_type&	vars_suppress_regexps,
			 strings_type&	fns_keep_regexps,
			 strings_type&	vars_keep_regexps,
			 strings_type&	sym_id_of_fns_to_keep,
			 strings_type&	sym_id_of_vars_to_keep)
  : priv_(new priv(fns, vars,
		   fns_suppress_regexps,
		   vars_suppress_regexps,
		   fns_keep_regexps,
		   vars_keep_regexps,
		   sym_id_of_fns_to_keep,
		   sym_id_of_vars_to_keep))
{
}

/// Getter for the reference to the vector of exported functions.
/// This vector is shared with with the @ref corpus.  It's where the
/// set of exported function is ultimately stored.
///
/// @return a reference to the vector of exported functions.
const corpus::functions&
corpus::exported_decls_builder::exported_functions() const
{return priv_->fns_;}

/// Getter for the reference to the vector of exported functions.
/// This vector is shared with with the @ref corpus.  It's where the
/// set of exported function is ultimately stored.
///
/// @return a reference to the vector of exported functions.
corpus::functions&
corpus::exported_decls_builder::exported_functions()
{return priv_->fns_;}

/// Getter for the reference to the vector of exported variables.
/// This vector is shared with with the @ref corpus.  It's where the
/// set of exported variable is ultimately stored.
///
/// @return a reference to the vector of exported variables.
const corpus::variables&
corpus::exported_decls_builder::exported_variables() const
{return priv_->vars_;}

/// Getter for the reference to the vector of exported variables.
/// This vector is shared with with the @ref corpus.  It's where the
/// set of exported variable is ultimately stored.
///
/// @return a reference to the vector of exported variables.
corpus::variables&
corpus::exported_decls_builder::exported_variables()
{return priv_->vars_;}

/// Consider at all the tunables that control wether a function should
/// be added to the set of exported function and if it fits in, add
/// the function to that set.
///
/// @param fn the function to add the set of exported functions.
void
corpus::exported_decls_builder::maybe_add_fn_to_exported_fns(function_decl* fn)
{
  if (!fn->get_is_in_public_symbol_table())
    return;

  const string& fn_id = priv_->get_id(*fn);
  ABG_ASSERT(!fn_id.empty());

  if (priv_->fn_is_in_id_fns_map(fn))
    return;

  if (priv_->keep_wrt_id_of_fns_to_keep(fn)
      && priv_->keep_wrt_regex_of_fns_to_suppress(fn)
      && priv_->keep_wrt_regex_of_fns_to_keep(fn))
    priv_->add_fn_to_exported(fn);
}

/// Consider at all the tunables that control wether a variable should
/// be added to the set of exported variable and if it fits in, add
/// the variable to that set.
///
/// @param fn the variable to add the set of exported variables.
void
corpus::exported_decls_builder::maybe_add_var_to_exported_vars(var_decl* var)
{
  if (!var->get_is_in_public_symbol_table())
    return;

  const string& var_id = priv_->get_id(*var);
  ABG_ASSERT(!var_id.empty());

  if (priv_->var_id_is_in_id_var_map(var_id))
    return;

  if (priv_->keep_wrt_id_of_vars_to_keep(var)
      && priv_->keep_wrt_regex_of_vars_to_suppress(var)
      && priv_->keep_wrt_regex_of_vars_to_keep(var))
    priv_->add_var_to_exported(var);
}

// </corpus::exported_decls_builder>

/// Convenience typedef for a hash map of pointer to function_decl and
/// boolean.
typedef unordered_map<const function_decl*,
		      bool,
		      function_decl::hash,
		      function_decl::ptr_equal> fn_ptr_map_type;

/// Convenience typedef for a hash map of string and pointer to
/// function_decl.
typedef unordered_map<string, const function_decl*> str_fn_ptr_map_type;

/// Convenience typedef for a hash map of pointer to var_decl and boolean.
typedef unordered_map<const var_decl*,
		      bool,
		      var_decl::hash,
		      var_decl::ptr_equal> var_ptr_map_type;

/// This is a comparison functor for comparing pointers to @ref
/// function_decl.
struct func_comp
{
  /// The comparisong operator for pointers to @ref function_decl.  It
  /// performs a string comparison of the mangled names of the
  /// functions.  If the functions don't have mangled names, it
  /// compares their names instead.
  ///
  /// @param first the first function to consider in the comparison.
  ///
  /// @param second the second function to consider in the comparison.
  ///
  /// @return true if the (mangled) name of the first function is less
  /// than the (mangled)name of the second one, false otherwise.
  bool
  operator()(const function_decl* first,
	     const function_decl* second) const
  {
    ABG_ASSERT(first != 0 && second != 0);

    string first_name, second_name;
    first_name = first->get_linkage_name();
    if (first_name.empty())
      first_name = first->get_name();
    ABG_ASSERT(!first_name.empty());

    second_name = second->get_linkage_name();
    if (second_name.empty())
      second_name = second->get_name();
    ABG_ASSERT(!second_name.empty());

    return first_name < second_name;
  }
};

/// This is a comparison functor for comparing pointers to @ref
/// var_decl.
struct var_comp
{
  /// The comparison operator for pointers to @ref var_decl.
  ///
  /// It perform a string comparison on the names of the variables.
  ///
  /// @param first the first variable to consider for the comparison.
  ///
  /// @param second the second variable to consider for the comparison.
  ///
  /// @return true if first is less than second, false otherwise.
  bool
  operator()(const var_decl* first,
	     const var_decl* second) const
  {
    ABG_ASSERT(first != 0 && second != 0);

    string first_name, second_name;
    first_name = first->get_linkage_name();
    if (first_name.empty())
      {
	first_name = first->get_pretty_representation();
	second_name = second->get_pretty_representation();
	ABG_ASSERT(!second_name.empty());
      }
    ABG_ASSERT(!first_name.empty());

    if (second_name.empty())
      second_name = second->get_linkage_name();

    if (second_name.empty())
      {
	second_name = second->get_pretty_representation();
	first_name = first->get_pretty_representation();
	ABG_ASSERT(!first_name.empty());
      }
    ABG_ASSERT(!second_name.empty());

    return first_name < second_name;
  }
};


/// A comparison functor to compare elf_symbols for the purpose of
/// sorting.
struct comp_elf_symbols_functor
{
  bool
  operator()(const elf_symbol& l,
	     const elf_symbol& r) const
  {return l.get_id_string() < r.get_id_string();}

  bool
  operator()(const elf_symbol_sptr l,
	     const elf_symbol_sptr r) const
  {return operator()(*l, *r);}
}; // end struct comp_elf_symbols_functor


// <corpus stuff>


/// Build the tables of symbols that are not referenced by any
/// function or variables of corpus::get_functions() or
/// corpus::get_variables().
///
/// Note that this function considers the list of function and
/// variable symbols to keep, that is provided by
/// corpus::get_sym_ids_of_fns_to_keep() and
/// corpus::get_sym_ids_of_vars_to_keep().  If a given unreferenced
/// function or variable symbol is not in the list of variable and
/// function symbols to keep, then that symbol is dropped and will not
/// be part of the resulting table of unreferenced symbol that is
/// built.
///
/// The built tables are accessible from
/// corpus::get_unreferenced_function_symbols() and
/// corpus::get_unreferenced_variable_symbols().
void
corpus::priv::build_unreferenced_symbols_tables()
{
  unordered_map<string, bool> refed_funs, refed_vars;
  elf_symbol_sptr sym;

  for (vector<function_decl*>::const_iterator f = fns.begin();
       f != fns.end();
       ++f)
    if ((sym = (*f)->get_symbol()))
      {
	refed_funs[sym->get_id_string()] = true;
	for (elf_symbol_sptr a = sym->get_next_alias();
	     a && !a->is_main_symbol();
	     a = a->get_next_alias())
	  refed_funs[a->get_id_string()] = true;
      }

  for (vector<var_decl*>::const_iterator v = vars.begin();
       v != vars.end();
       ++v)
    if ((sym = (*v)->get_symbol()))
      {
	refed_vars[sym->get_id_string()] = true;
	for (elf_symbol_sptr a = sym->get_next_alias();
	     a && !a->is_main_symbol();
	     a = a->get_next_alias())
	  refed_vars[a->get_id_string()] = true;
      }

  if (fun_symbol_map)
    {
      // Let's assume that the size of the unreferenced symbols vector
      // is roughly smaller than the size of the symbol table.
      unrefed_fun_symbols.reserve(fun_symbol_map->size());
      for (string_elf_symbols_map_type::const_iterator i
	     = fun_symbol_map->begin();
	   i != fun_symbol_map->end();
	   ++i)
	for (elf_symbols::const_iterator s = i->second.begin();
	     s != i->second.end();
	     ++s)
	  {
	    string sym_id = (*s)->get_id_string();
	    if (refed_funs.find(sym_id) == refed_funs.end())
	      {
		bool keep = sym_id_fns_to_keep.empty();
		for (vector<string>::const_iterator i =
		       sym_id_fns_to_keep.begin();
		     i != sym_id_fns_to_keep.end();
		     ++i)
		  {
		    if (*i == sym_id)
		      {
			keep = true;
			break;
		      }
		  }
		if (keep)
		  unrefed_fun_symbols.push_back(*s);
	      }
	  }

      comp_elf_symbols_functor comp;
      std::sort(unrefed_fun_symbols.begin(),
		unrefed_fun_symbols.end(),
		comp);
    }

  if (var_symbol_map)
    {
      // Let's assume that the size of the unreferenced symbols vector
      // is roughly smaller than the size of the symbol table.
      unrefed_var_symbols.reserve(var_symbol_map->size());
      for (string_elf_symbols_map_type::const_iterator i
	     = var_symbol_map->begin();
	   i != var_symbol_map->end();
	   ++i)
	for (elf_symbols::const_iterator s = i->second.begin();
	     s != i->second.end();
	     ++s)
	  {
	    string sym_id = (*s)->get_id_string();
	    if (refed_vars.find(sym_id) == refed_vars.end())
	      {
		bool keep = sym_id_vars_to_keep.empty();
		for (vector<string>::const_iterator i =
		       sym_id_vars_to_keep.begin();
		     i != sym_id_vars_to_keep.end();
		     ++i)
		  {
		    if (*i == sym_id)
		      {
			keep = true;
			break;
		      }
		  }
		if (keep)
		  unrefed_var_symbols.push_back(*s);
	      }
	  }

      comp_elf_symbols_functor comp;
      std::sort(unrefed_var_symbols.begin(),
		unrefed_var_symbols.end(),
		comp);
    }
}

/// 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_;}

/// Return a sorted vector of function symbols for this corpus.
///
/// Note that the first time this function is called, the symbols are
/// sorted and cached.  Subsequent invocations of this function return
/// the cached vector that was built previously.
///
/// @return the sorted list of function symbols.
const elf_symbols&
corpus::priv::get_sorted_fun_symbols() const
{
  if (!sorted_fun_symbols)
    {
      const symtab_reader::symtab_filter filter =
	  symtab_->make_filter().functions();

      sorted_fun_symbols = elf_symbols(symtab_->begin(filter), symtab_->end());
    }
  return *sorted_fun_symbols;
}

/// Getter for a sorted vector of the function symbols undefined in
/// this corpus.
///
/// @return a vector of the function symbols undefined in this corpus,
/// sorted by name and then version.
const elf_symbols&
corpus::priv::get_sorted_undefined_fun_symbols() const
{
  if (!sorted_undefined_fun_symbols)
    {
      const symtab_reader::symtab_filter filter = symtab_->make_filter()
						      .functions()
						      .undefined_symbols()
						      .public_symbols(false);

      sorted_undefined_fun_symbols =
	  elf_symbols(symtab_->begin(filter), symtab_->end());
    }
  return *sorted_undefined_fun_symbols;
}

/// Getter for the sorted vector of variable symbols for this corpus.
///
/// Note that the first time this function is called, it computes the
/// sorted vector, caches the result and returns it.  Subsequent
/// invocations of this function just return the cached vector.
///
/// @return the sorted vector of variable symbols for this corpus.
const elf_symbols&
corpus::priv::get_sorted_var_symbols() const
{
  if (!sorted_var_symbols)
    {
      const symtab_reader::symtab_filter filter =
	  symtab_->make_filter().variables();

      sorted_var_symbols = elf_symbols(symtab_->begin(filter), symtab_->end());
    }
  return *sorted_var_symbols;
}

/// Getter for a sorted vector of the variable symbols undefined in
/// this corpus.
///
/// @return a vector of the variable symbols undefined in this corpus,
/// sorted by name and then version.
const elf_symbols&
corpus::priv::get_sorted_undefined_var_symbols() const
{
  if (!sorted_undefined_var_symbols)
    {
      const symtab_reader::symtab_filter filter = symtab_->make_filter()
						      .variables()
						      .undefined_symbols()
						      .public_symbols(false);

      sorted_undefined_var_symbols =
	  elf_symbols(symtab_->begin(filter), symtab_->end());
    }
  return *sorted_undefined_var_symbols;
}

/// Getter of the set of pretty representation of types that are
/// reachable from public interfaces (global functions and variables).
///
/// @return the set of pretty representation of types that are
/// reachable from public interfaces (global functions and variables).
unordered_set<interned_string, hash_interned_string>*
corpus::priv::get_public_types_pretty_representations()
{
  if (group)
    return group->get_public_types_pretty_representations();

  if (pub_type_pretty_reprs_ == 0)
    pub_type_pretty_reprs_ =
	new unordered_set<interned_string, hash_interned_string>;
  return pub_type_pretty_reprs_;
}

/// Destructor of the @ref corpus::priv type.
corpus::priv::~priv()
{
  delete pub_type_pretty_reprs_;
}

/// Constructor of the @ref corpus type.
///
/// @param env the environment of the corpus.
///
/// @param path the path to the file containing the ABI corpus.
corpus::corpus(ir::environment* env, const string& path)
{priv_.reset(new priv(path, env));}

/// Getter of the enviroment of the corpus.
///
/// @return the environment of this corpus.
const environment*
corpus::get_environment() const
{return priv_->env;}

/// Getter of the enviroment of the corpus.
///
/// @return the environment of this corpus.
environment*
corpus::get_environment()
{return priv_->env;}

/// Setter of the environment of this corpus.
///
/// @param e the new environment.
void
corpus::set_environment(environment* e) const
{priv_->env = e;}

/// Add a translation unit to the current ABI Corpus. Next time
/// corpus::save is called, all the translation unit that got added to
/// the corpus are going to be serialized on disk in the file
/// associated to the current corpus.
///
/// Note that two translation units with the same path (as returned by
/// translation_unit::get_path) cannot be added to the same @ref
/// corpus.  If that happens, the library aborts.
///
/// @param tu the new translation unit to add.
void
corpus::add(const translation_unit_sptr tu)
{
  if (!tu->get_environment())
    tu->set_environment(get_environment());

  ABG_ASSERT(tu->get_environment() == get_environment());

  ABG_ASSERT(priv_->members.insert(tu).second);

  if (!tu->get_absolute_path().empty())
    {
      // Update the path -> translation_unit map.
      string_tu_map_type::const_iterator i =
	priv_->path_tu_map.find(tu->get_absolute_path());
      ABG_ASSERT(i == priv_->path_tu_map.end());
      priv_->path_tu_map[tu->get_absolute_path()] = tu;
    }

  tu->set_corpus(this);
}

/// Return the list of translation units of the current corpus.
///
/// @return the list of translation units of the current corpus.
const translation_units&
corpus::get_translation_units() const
{return priv_->members;}

/// Find the translation unit that has a given path.
///
/// @param path the path of the translation unit to look for.
///
/// @return the translation unit found, if any.  Otherwise, return
/// nil.
const translation_unit_sptr
corpus::find_translation_unit(const string &path) const
{
  string_tu_map_type::const_iterator i =
    priv_->path_tu_map.find(path);

  if (i == priv_->path_tu_map.end())
    return translation_unit_sptr();
  return i->second;
}

/// Erase the translation units contained in this in-memory object.
///
/// Note that the on-disk archive file that contains the serialized
/// representation of this object is not modified.
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_;}

/// Get the maps that associate a location string to a certain kind of
/// type.
///
/// The location string is the result of the invocation to the
/// function abigail::ir::location::expand().  It has the form
/// "file.c:4:1", with 'file.c' being the file name, '4' being the
/// line number and '1' being the column number.
///
/// @return the maps.
const type_maps&
corpus::get_type_per_loc_map() const
{return priv_->type_per_loc_map_;}

/// Test if the recording of reachable types (and thus, indirectly,
/// the recording of non-reachable types) is activated for the
/// current @ref corpus.
///
/// @return true iff the recording of reachable types is activated for
/// the current @ref corpus.
bool
corpus::recording_types_reachable_from_public_interface_supported()
{
  return (priv_->get_public_types_pretty_representations()
	  && !priv_->get_public_types_pretty_representations()->empty());
}

/// Record a type as being reachable from public interfaces (global
/// functions and variables).
///
/// @param t the type to record as reachable.
void
corpus::record_type_as_reachable_from_public_interfaces(const type_base& t)
{
  string repr = get_pretty_representation(&t, /*internal=*/true);
  interned_string s = t.get_environment()->intern(repr);
  priv_->get_public_types_pretty_representations()->insert(s);
}

/// Test if a type is reachable from public interfaces (global
/// functions and variables).
///
/// For a type to be considered reachable from public interfaces, it
/// must have been previously marked as such by calling
/// corpus::record_type_as_reachable_from_public_interfaces.
///
/// @param t the type to test for.
///
/// @return true iff @p t is reachable from public interfaces.
bool
corpus::type_is_reachable_from_public_interfaces(const type_base& t) const
{
  string repr = get_pretty_representation(&t, /*internal=*/true);
  interned_string s = t.get_environment()->intern(repr);

  return (priv_->get_public_types_pretty_representations()->find(s)
	  !=  priv_->get_public_types_pretty_representations()->end());
}

/// Getter of a sorted vector of the types that are *NOT* reachable
/// from public interfaces.
///
/// Note that for this to be non-empty, the libabigail reader that
/// analyzed the input (be it a binary or an abixml file) must have be
/// configured to load types that are not reachable from public
/// interfaces.
///
/// @return a reference to a vector of sorted types NON reachable from
/// public interfaces.
const vector<type_base_wptr>&
corpus::get_types_not_reachable_from_public_interfaces() const
{
  if (priv_->types_not_reachable_from_pub_ifaces_.empty())
    {
      const type_maps& types = get_types();
      for (vector<type_base_wptr>::const_iterator it =
	     types.get_types_sorted_by_name().begin();
	   it != types.get_types_sorted_by_name().end();
	   ++it)
	{
	  type_base_sptr t(*it);
	  if (!type_is_reachable_from_public_interfaces(*t))
	    priv_->types_not_reachable_from_pub_ifaces_.push_back(t);
	}
    }

  return priv_->types_not_reachable_from_pub_ifaces_;
}

/// Get the maps that associate a location string to a certain kind of
/// type.
///
/// The location string is the result of the invocation to the
/// function abigail::ir::location::expand().  It has the form
/// "file.c:4:1", with 'file.c' being the file name, '4' being the
/// line number and '1' being the column number.
///
/// @return the maps.
type_maps&
corpus::get_type_per_loc_map()
{return priv_->type_per_loc_map_;}

/// Getter of the group this corpus is a member of.
///
/// @return the group this corpus is a member of, or nil if it's not
/// part of any @ref corpus_group.
const corpus_group*
corpus::get_group() const
{return priv_->group;}

/// Getter of the group this corpus belongs to.
///
/// @return the group this corpus belong to, or nil if it's not part
/// of any @ref corpus_group.
corpus_group*
corpus::get_group()
{return priv_->group;}

/// Setter of the group this corpus belongs to.
///
/// @param g the new group.
void
corpus::set_group(corpus_group* g)
{priv_->group = g;}

/// Getter for the origin of the corpus.
///
/// @return the origin of the corpus.
corpus::origin
corpus::get_origin() const
{return priv_->origin_;}

/// Setter for the origin of the corpus.
///
/// @param o the new origin for the corpus.
void
corpus::set_origin(origin o)
{priv_->origin_ = o;}

/// Get the file path associated to the corpus file.
///
/// A subsequent call to corpus::read will deserialize the content of
/// the abi file expected at this path; likewise, a call to
/// corpus::write will serialize the translation units contained in
/// the corpus object into the on-disk file at this path.
///
/// @return the file path associated to the current corpus.
string&
corpus::get_path() const
{return priv_->path;}

/// Set the file path associated to the corpus file.
///
/// A subsequent call to corpus::read will deserialize the content of
/// the abi file expected at this path; likewise, a call to
/// corpus::write will serialize the translation units contained in
/// the corpus object into the on-disk file at this path.
///
/// @param path the new file path to assciate to the current corpus.
void
corpus::set_path(const string& path)
{priv_->path = path;}

/// Getter of the needed property of the corpus.
///
/// This property is meaningful for, e.g, corpora built from ELF
/// shared library files.  In that case, this is a vector of names of
/// dependencies of the ELF shared library file.
///
/// @return the vector of dependencies needed by this corpus.
const vector<string>&
corpus::get_needed() const
{return priv_->needed;}

/// Setter of the needed property of the corpus.
///
/// This property is meaningful for, e.g, corpora built from ELF
/// shared library files.  In that case, this is a vector of names of
/// dependencies of the ELF shared library file.
///
/// @param needed the new vector of dependencies needed by this
/// corpus.
void
corpus::set_needed(const vector<string>& needed)
{priv_->needed = needed;}

/// Getter for the soname property of the corpus.
///
/// This property is meaningful for, e.g, corpora built from ELF
/// shared library files.  In that case, this is the shared object
/// name exported by the shared library.
///
/// @return the soname property of the corpus.
const string&
corpus::get_soname()
{return priv_->soname;}

/// Setter for the soname property of the corpus.
///
/// This property is meaningful for, e.g, corpora built from ELF
/// shared library files.  In that case, this is the shared object
/// name exported by the shared library.
///
/// @param soname the new soname property of the corpus.
void
corpus::set_soname(const string& soname)
{priv_->soname = soname;}

/// Getter for the architecture name of the corpus.
///
/// This property is meaningful for e.g, corpora built from ELF shared
/// library files.  In that case, this is a string representation of
/// the Elf{32,64}_Ehdr::e_machine field.
///
/// @return the architecture name string.
const string&
corpus::get_architecture_name() const
{return priv_->architecture_name;}

/// Setter for the architecture name of the corpus.
///
/// This property is meaningful for e.g, corpora built from ELF shared
/// library files.  In that case, this is a string representation of
/// the Elf{32,64}_Ehdr::e_machine field.
///
/// @param arch the architecture name string.
void
corpus::set_architecture_name(const string& arch)
{priv_->architecture_name = arch;}

/// Tests if the corpus is empty from an ABI surface perspective. I.e. if all
/// of these criteria are true:
///  - all translation units (members) are empty
///  - the maps function and variable symbols are not having entries
///  - for shared libraries:
///    - the soname is empty
///    - there are no DT_NEEDED entries
///
/// @return true if the corpus contains no translation unit.
bool
corpus::is_empty() const
{
  bool members_empty = true;
  for (translation_units::const_iterator i = priv_->members.begin(),
					 e = priv_->members.end();
       i != e; ++i)
    {
      if (!(*i)->is_empty())
	{
	  members_empty = false;
	  break;
	}
    }
  return (members_empty
	  && priv_->fun_symbol_map
	  && priv_->fun_symbol_map->empty()
	  && priv_->var_symbol_map
	  && priv_->var_symbol_map->empty()
	  && priv_->soname.empty()
	  && priv_->needed.empty());
}

/// Compare the current @ref corpus against another one.
///
/// @param other the other corpus to compare against.
///
/// @return true if the two corpus are equal, false otherwise.
bool
corpus::operator==(const corpus& other) const
{
  translation_units::const_iterator i, j;
  for (i = get_translation_units().begin(),
	 j = other.get_translation_units().begin();
       (i != get_translation_units().end()
	&& j != other.get_translation_units().end());
       ++i, ++j)
    if ((**i) != (**j))
      return false;

  return (i == get_translation_units().end()
	  && j == other.get_translation_units().end());
}

void
corpus::set_symtab(symtab_reader::symtab_sptr symtab)
{priv_->symtab_ = symtab;}

const symtab_reader::symtab_sptr&
corpus::get_symtab() const
{ return priv_->symtab_; }

/// Setter of the function symbols map.
///
/// @param map a shared pointer to the new function symbols map.
void
corpus::set_fun_symbol_map(string_elf_symbols_map_sptr map)
{priv_->fun_symbol_map = map;}

/// Setter for the map of function symbols that are undefined in this
/// corpus.
///
/// @param map a new map for function symbols not defined in this
/// corpus.  The key of the map is the name of the function symbol.
/// The value is a vector of all the function symbols that have the
/// same name.
void
corpus::set_undefined_fun_symbol_map(string_elf_symbols_map_sptr map)
{priv_->undefined_fun_symbol_map = map;}

/// Setter of the variable symbols map.
///
/// @param map a shared pointer to the new variable symbols map.
void
corpus::set_var_symbol_map(string_elf_symbols_map_sptr map)
{priv_->var_symbol_map = map;}

/// Setter for the map of variable symbols that are undefined in this
/// corpus.
///
/// @param map a new map for variable symbols not defined in this
/// corpus.  The key of the map is the name of the variable symbol.
/// The value is a vector of all the variable symbols that have the
/// same name.
void
corpus::set_undefined_var_symbol_map(string_elf_symbols_map_sptr map)
{priv_->undefined_var_symbol_map = map;}

/// Getter for the function symbols map.
///
/// @return a shared pointer to the function symbols map.
const string_elf_symbols_map_sptr
corpus::get_fun_symbol_map_sptr() const
{
  if (!priv_->fun_symbol_map)
    priv_->fun_symbol_map.reset(new string_elf_symbols_map_type);
  return priv_->fun_symbol_map;
}

/// Getter for the function symbols map.
///
/// @return a reference to the function symbols map.
const string_elf_symbols_map_type&
corpus::get_fun_symbol_map() const
{return *get_fun_symbol_map_sptr();}

/// Getter for the map of function symbols that are undefined in this
/// corpus.
///
/// @return the map of function symbols not defined in this corpus.
/// The key of the map is the name of the function symbol.  The value
/// is a vector of all the function symbols that have the same name.
const string_elf_symbols_map_sptr
corpus::get_undefined_fun_symbol_map_sptr() const
{return priv_->undefined_fun_symbol_map;}

/// Getter for the map of function symbols that are undefined in this
/// corpus.
///
/// @return the map of function symbols not defined in this corpus.
/// The key of the map is the name of the function symbol.  The value
/// is a vector of all the function symbols that have the same name.
const string_elf_symbols_map_type&
corpus::get_undefined_fun_symbol_map() const
{return *get_undefined_fun_symbol_map_sptr();}

const elf_symbols&
corpus::get_sorted_fun_symbols() const
{ return priv_->get_sorted_fun_symbols(); }

const elf_symbols&
corpus::get_sorted_undefined_fun_symbols() const
{ return priv_->get_sorted_undefined_fun_symbols(); }

const elf_symbols&
corpus::get_sorted_var_symbols() const
{ return priv_->get_sorted_var_symbols(); }

const elf_symbols&
corpus::get_sorted_undefined_var_symbols() const
{ return priv_->get_sorted_undefined_var_symbols(); }

/// Getter for the variable symbols map.
///
/// @return a shared pointer to the variable symbols map.
const string_elf_symbols_map_sptr
corpus::get_var_symbol_map_sptr() const
{
  if (!priv_->var_symbol_map)
    priv_->var_symbol_map.reset(new string_elf_symbols_map_type);
  return priv_->var_symbol_map;
}

/// Getter for the variable symbols map.
///
/// @return a reference to the variabl symbols map.
const string_elf_symbols_map_type&
corpus::get_var_symbol_map() const
{return *get_var_symbol_map_sptr();}

/// Getter for the map of variable symbols that are undefined in this
/// corpus.
///
/// @return the map of variable symbols not defined in this corpus.
/// The key of the map is the name of the variable symbol.  The value
/// is a vector of all the variable symbols that have the same name.
const string_elf_symbols_map_sptr
corpus::get_undefined_var_symbol_map_sptr() const
{return priv_->undefined_var_symbol_map;}

/// Getter for the map of variable symbols that are undefined in this
/// corpus.
///
/// @return the map of variable symbols not defined in this corpus.
/// The key of the map is the name of the variable symbol.  The value
/// is a vector of all the variable symbols that have the same name.
const string_elf_symbols_map_type&
corpus::get_undefined_var_symbol_map() const
{return *get_undefined_var_symbol_map_sptr();}

/// Look in the function symbols map for a symbol with a given name.
///
/// @param n the name of the symbol to look for.
///
/// return the first symbol with the name @p n.
const elf_symbol_sptr
corpus::lookup_function_symbol(const string& n) const
{
  if (get_fun_symbol_map().empty())
    return elf_symbol_sptr();

  string_elf_symbols_map_type::const_iterator it =
    get_fun_symbol_map().find(n);
  if ( it == get_fun_symbol_map().end())
    return elf_symbol_sptr();
  return it->second[0];
}

/// Look into a set of symbols and look for a symbol that has a given
/// version.
///
/// This is a sub-routine for corpus::lookup_function_symbol() and
/// corpus::lookup_variable_symbol().
///
/// @param version the version of the symbol to look for.
///
/// @param symbols the set of symbols to consider.
///
/// @return the symbol found, or nil if none was found.
static const elf_symbol_sptr
find_symbol_by_version(const elf_symbol::version& version,
		       const vector<elf_symbol_sptr>& symbols)
{
  if (version.is_empty())
    {
      // We are looing for a symbol with no version.

      // So first look for possible aliases with no version
      for (elf_symbols::const_iterator s = symbols.begin();
	   s != symbols.end();
	   ++s)
	if ((*s)->get_version().is_empty())
	  return *s;

      // Or, look for a version that is a default one!
      for (elf_symbols::const_iterator s = symbols.begin();
	   s != symbols.end();
	   ++s)
	if ((*s)->get_version().is_default())
	  return *s;
    }
  else
    // We are looking for a symbol with a particular defined version.
    for (elf_symbols::const_iterator s = symbols.begin();
	 s != symbols.end();
	 ++s)
      if ((*s)->get_version().str() == version.str())
	return *s;

  return elf_symbol_sptr();
}

/// Look in the function symbols map for a symbol with a given name.
///
/// @param symbol_name the name of the symbol to look for.
///
/// @param version the version of the symbol to look for.
///
/// return the symbol with name @p symbol_name and with version @p
/// version, or nil if no symbol has been found with that name and
/// version.
const elf_symbol_sptr
corpus::lookup_function_symbol(const string& symbol_name,
			       const elf_symbol::version& version) const
{
  if (get_fun_symbol_map().empty())
    return elf_symbol_sptr();

  string_elf_symbols_map_type::const_iterator it =
    get_fun_symbol_map().find(symbol_name);
  if ( it == get_fun_symbol_map().end())
    return elf_symbol_sptr();

  return find_symbol_by_version(version, it->second);
}

/// Look in the function symbols map for a symbol with the same name
/// and version as a given symbol.
///
/// @param symbol the symbol to look for.
///
/// return the symbol with the same name and version as @p symbol.
const elf_symbol_sptr
corpus::lookup_function_symbol(const elf_symbol& symbol) const
{return lookup_function_symbol(symbol.get_name(), symbol.get_version());}

/// Look in the variable symbols map for a symbol with a given name.
///
/// @param n the name of the symbol to look for.
///
/// return the first symbol with the name @p n.
const elf_symbol_sptr
corpus::lookup_variable_symbol(const string& n) const
{
  if (get_var_symbol_map().empty())
    return elf_symbol_sptr();

  string_elf_symbols_map_type::const_iterator it =
    get_var_symbol_map().find(n);
  if ( it == get_var_symbol_map().end())
    return elf_symbol_sptr();
  return it->second[0];
}

/// Look in the variable symbols map for a symbol with a given name.
///
/// @param symbol_name the name of the symbol to look for.
///
/// @param symbol_version the version of the symbol to look for.
///
/// return the first symbol with the name @p symbol_name and with
/// version @p version.
const elf_symbol_sptr
corpus::lookup_variable_symbol(const string& symbol_name,
			       const elf_symbol::version& version) const
{
  if (get_var_symbol_map().empty())
    return elf_symbol_sptr();

  string_elf_symbols_map_type::const_iterator it =
    get_var_symbol_map().find(symbol_name);
  if ( it == get_var_symbol_map().end())
    return elf_symbol_sptr();

  return find_symbol_by_version(version, it->second);
}

/// Look in the variable symbols map for a symbol with the same name
/// and version as a given symbol.
///
/// @param symbol the symbol to look for.
///
/// return the symbol with the same name and version as @p symbol.
const elf_symbol_sptr
corpus::lookup_variable_symbol(const elf_symbol& symbol) const
{return lookup_variable_symbol(symbol.get_name(), symbol.get_version());}

/// Return the functions public decl table of the current corpus.
///
/// The function public decl tables is a vector of all the functions
/// and member functions found in the current corpus.
///
/// Note that the caller can suppress some functions from the vector
/// supplying regular expressions describing the set of functions she
/// want to see removed from the public decl table by populating the
/// vector of regular expressions returned by
/// corpus::get_regex_patterns_of_fns_to_suppress().
///
/// @return the vector of functions of the public decl table.  The
/// functions are sorted using their mangled name or name if they
/// don't have mangle names.
const corpus::functions&
corpus::get_functions() const
{return priv_->fns;}

/// Lookup the function which has a given function ID.
///
/// Note that there can have been several functions with the same ID.
/// This is because debug info can declare the same function in
/// several different translation units.  Normally, all these function
/// should be equal.  But still, this function returns all these
/// functions.
///
/// @param id the ID of the function to lookup.  This ID must be
/// either the result of invoking function::get_id() of
/// elf_symbol::get_id_string().
///
/// @return the vector functions which ID is @p id, or nil if no
/// function with that ID was found.
const vector<function_decl*>*
corpus::lookup_functions(const string& id) const
{
  exported_decls_builder_sptr b = get_exported_decls_builder();
  str_fn_ptrs_map_type::const_iterator i =
    b->priv_->id_fns_map_.find(id);
  if (i == b->priv_->id_fns_map_.end())
    return 0;
  return &i->second;
}

/// Sort the set of functions exported by this corpus.
///
/// Normally, you shouldn't be calling this as the code that creates
/// the corpus for you should do it for you too.
void
corpus::sort_functions()
{
  func_comp fc;
  std::sort(priv_->fns.begin(), priv_->fns.end(), fc);
}

/// Return the public decl table of the global variables of the
/// current corpus.
///
/// The variable public decls table is a vector of all the public
/// global variables and static member variables found in the current
/// corpus.
///
/// Note that the caller can suppress some variables from the vector
/// supplying regular expressions describing the set of variables she
/// wants to see removed from the public decl table by populating the
/// vector of regular expressions returned by
/// corpus::get_regex_patterns_of_fns_to_suppress().
///
/// @return the vector of variables of the public decl table.  The
/// variables are sorted using their name.
const corpus::variables&
corpus::get_variables() const
{return priv_->vars;}

/// Sort the set of variables exported by this corpus.
///
/// Normally, you shouldn't be calling this as the code that creates
/// the corpus for you should do it for you too.
void
corpus::sort_variables()
{
  var_comp vc;
  std::sort(priv_->vars.begin(), priv_->vars.end(), vc);
}

/// Getter of the set of function symbols that are not referenced by
/// any function exported by the current corpus.
///
/// When the corpus has been created from an ELF library or program,
/// this function returns the set of function symbols not referenced
/// by any debug information.
///
/// @return the vector of function symbols not referenced by any
/// function exported by the current corpus.
const elf_symbols&
corpus::get_unreferenced_function_symbols() const
{
  if (priv_->unrefed_fun_symbols.empty()
      && priv_->unrefed_var_symbols.empty())
    priv_->build_unreferenced_symbols_tables();
  return priv_->unrefed_fun_symbols;
}

/// Getter of the set of variable symbols that are not referenced by
/// any variable exported by the current corpus.
///
/// When the corpus has been created from an ELF library or program,
/// this function returns the set of variable symbols not referenced
/// by any debug information.
///
/// @return the vector of variable symbols not referenced by any
/// variable exported by the current corpus.
const elf_symbols&
corpus::get_unreferenced_variable_symbols() const
{
    if (priv_->unrefed_fun_symbols.empty()
      && priv_->unrefed_var_symbols.empty())
    priv_->build_unreferenced_symbols_tables();
  return priv_->unrefed_var_symbols;
}

/// Accessor for the regex patterns describing the functions to drop
/// from the public decl table.
///
/// @return the regex patterns describing the functions to drop from
/// the public decl table.
vector<string>&
corpus::get_regex_patterns_of_fns_to_suppress()
{return priv_->regex_patterns_fns_to_suppress;}

/// Accessor for the regex patterns describing the functions to drop
/// from the public decl table.
///
/// @return the regex patterns describing the functions to drop from
/// the public decl table.
const vector<string>&
corpus::get_regex_patterns_of_fns_to_suppress() const
{return priv_->regex_patterns_fns_to_suppress;}

/// Accessor for the regex patterns describing the variables to drop
/// from the public decl table.
///
/// @return the regex patterns describing the variables to drop from
/// the public decl table.
vector<string>&
corpus::get_regex_patterns_of_vars_to_suppress()
{return priv_->regex_patterns_vars_to_suppress;}

/// Accessor for the regex patterns describing the variables to drop
/// from the public decl table.
///
/// @return the regex patterns describing the variables to drop from
/// the public decl table.
const vector<string>&
corpus::get_regex_patterns_of_vars_to_suppress() const
{return priv_->regex_patterns_vars_to_suppress;}

/// Accessor for the regex patterns describing the functions to keep
/// into the public decl table.  The other functions not matches by these
/// regexes are dropped from the public decl table.
///
/// @return the regex patterns describing the functions to keep into
/// the public decl table.
vector<string>&
corpus::get_regex_patterns_of_fns_to_keep()
{return priv_->regex_patterns_fns_to_keep;}

/// Accessor for the regex patterns describing the functions to keep
/// into the public decl table.  The other functions not matches by these
/// regexes are dropped from the public decl table.
///
/// @return the regex patterns describing the functions to keep into
/// the public decl table.
const vector<string>&
corpus::get_regex_patterns_of_fns_to_keep() const
{return priv_->regex_patterns_fns_to_keep;}

/// Getter for the vector of function symbol IDs to keep.
///
/// A symbol ID is a string made of the name of the symbol and its
/// version, separated by one or two '@'.
///
/// @return a vector of IDs of function symbols to keep.
vector<string>&
corpus::get_sym_ids_of_fns_to_keep()
{return priv_->sym_id_fns_to_keep;}

/// Getter for the vector of function symbol IDs to keep.
///
/// A symbol ID is a string made of the name of the symbol and its
/// version, separated by one or two '@'.
///
/// @return a vector of IDs of function symbols to keep.
const vector<string>&
corpus::get_sym_ids_of_fns_to_keep() const
{return priv_->sym_id_fns_to_keep;}

/// Accessor for the regex patterns describing the variables to keep
/// into the public decl table.  The other variables not matches by these
/// regexes are dropped from the public decl table.
///
/// @return the regex patterns describing the variables to keep into
/// the public decl table.
vector<string>&
corpus::get_regex_patterns_of_vars_to_keep()
{return priv_->regex_patterns_vars_to_keep;}

/// Accessor for the regex patterns describing the variables to keep
/// into the public decl table.  The other variables not matches by these
/// regexes are dropped from the public decl table.
///
/// @return the regex patterns describing the variables to keep into
/// the public decl table.
const vector<string>&
corpus::get_regex_patterns_of_vars_to_keep() const
{return priv_->regex_patterns_vars_to_keep;}

/// Getter for the vector of variable symbol IDs to keep.
///
/// A symbol ID is a string made of the name of the symbol and its
/// version, separated by one or two '@'.
///
/// @return a vector of IDs of variable symbols to keep.
vector<string>&
corpus::get_sym_ids_of_vars_to_keep()
{return priv_->sym_id_vars_to_keep;}

/// Getter for the vector of variable symbol IDs to keep.
///
/// A symbol ID is a string made of the name of the symbol and its
/// version, separated by one or two '@'.
///
/// @return a vector of IDs of variable symbols to keep.
const vector<string>&
corpus::get_sym_ids_of_vars_to_keep() const
{return priv_->sym_id_vars_to_keep;}

/// After the set of exported functions and variables have been built,
/// consider all the tunables that control that set and see if some
/// functions need to be removed from that set; if so, remove them.
void
corpus::maybe_drop_some_exported_decls()
{
  string sym_name, sym_version;

  vector<function_decl*> fns_to_keep;
  exported_decls_builder* b = get_exported_decls_builder().get();
  for (vector<function_decl*>::iterator f = priv_->fns.begin();
       f != priv_->fns.end();
       ++f)
    {
      if (b->priv_->keep_wrt_id_of_fns_to_keep(*f)
	  && b->priv_->keep_wrt_regex_of_fns_to_suppress(*f)
	  && b->priv_->keep_wrt_regex_of_fns_to_keep(*f))
	fns_to_keep.push_back(*f);
    }
  priv_->fns = fns_to_keep;

  vector<var_decl*> vars_to_keep;
  for (vector<var_decl*>::iterator v = priv_->vars.begin();
       v != priv_->vars.end();
       ++v)
    {
      if (b->priv_->keep_wrt_id_of_vars_to_keep(*v)
	  && b->priv_->keep_wrt_regex_of_vars_to_suppress(*v)
	  && b->priv_->keep_wrt_regex_of_vars_to_keep(*v))
	vars_to_keep.push_back(*v);
    }
  priv_->vars = vars_to_keep;
}

///  Getter for the object that is responsible for determining what
///  decls ought to be in the set of exported decls.
///
///  The object does have methods to add the decls to the set of
///  exported decls, right at the place where the corpus expects it,
///  so that there is no unnecessary copying involved.
///
///  @return a (smart) pointer to the instance of @ref
///  corpus::exported_decls_builder that is responsible for determine
///  what decls ought to be in the set of exported decls.
corpus::exported_decls_builder_sptr
corpus::get_exported_decls_builder() const
{
  if (!priv_->exported_decls_builder)
    {
      priv_->exported_decls_builder.reset
	(new exported_decls_builder(priv_->fns,
				    priv_->vars,
				    priv_->regex_patterns_fns_to_suppress,
				    priv_->regex_patterns_vars_to_suppress,
				    priv_->regex_patterns_fns_to_keep,
				    priv_->regex_patterns_vars_to_keep,
				    priv_->sym_id_fns_to_keep,
				    priv_->sym_id_vars_to_keep));
    }
  return priv_->exported_decls_builder;
}

// </corpus stuff>

// <corpus_group stuff>

/// Type of the private data of @ref corpus_group
struct corpus_group::priv
{
  corpora_type			corpora;
  istring_function_decl_ptr_map_type fns_map;
  vector<function_decl*>	fns;
  istring_var_decl_ptr_map_type vars_map;
  vector<var_decl*>		vars;
  string_elf_symbols_map_type	var_symbol_map;
  string_elf_symbols_map_type	fun_symbol_map;
  elf_symbols			sorted_var_symbols;
  elf_symbols			sorted_fun_symbols;
  unordered_map<string, elf_symbol_sptr> unrefed_fun_symbol_map;
  elf_symbols			unrefed_fun_symbols;
  bool				unrefed_fun_symbols_built;
  unordered_map<string, elf_symbol_sptr> unrefed_var_symbol_map;
  elf_symbols			unrefed_var_symbols;
  bool				unrefed_var_symbols_built;
  unordered_set<interned_string, hash_interned_string> pub_type_pretty_reprs_;

  priv()
    : unrefed_fun_symbols_built(),
      unrefed_var_symbols_built()
  {}

  /// Add symbols to the set of corpus group function symbols that are
  /// *NOT* referenced by debug info.
  ///
  /// @param syms the set the symbols to add.
  void
  add_unref_fun_symbols(const elf_symbols& syms)
  {
    for (elf_symbols::const_iterator e =
	   syms.begin(); e != syms.end(); ++e)
      {
	string sym_id = (*e)->get_id_string();
	unordered_map<string, elf_symbol_sptr>::const_iterator j =
	  unrefed_fun_symbol_map.find(sym_id);
	if (j != unrefed_fun_symbol_map.end())
	  continue;

	unrefed_fun_symbol_map[sym_id] = *e;
	unrefed_fun_symbols.push_back(*e);
      }
    unrefed_fun_symbols_built = true;
  }

  /// Add symbols to the set of corpus group variable symbols that are
  /// *NOT* referenced by debug info.
  ///
  /// @param syms the set the symbols to add.
  void
  add_unref_var_symbols(const elf_symbols& syms)
  {
    for (elf_symbols::const_iterator e =
	   syms.begin(); e != syms.end(); ++e)
      {
	string sym_id = (*e)->get_id_string();
	unordered_map<string, elf_symbol_sptr>::const_iterator j =
	  unrefed_var_symbol_map.find(sym_id);
	if (j != unrefed_var_symbol_map.end())
	  continue;

	unrefed_var_symbol_map[sym_id] = *e;
	unrefed_var_symbols.push_back(*e);
      }
    unrefed_var_symbols_built = true;
  }
}; // end corpus_group::priv

/// Default constructor of the @ref corpus_group type.
corpus_group::corpus_group(environment* env, const string& path = "")
  : corpus(env, path), priv_(new priv)
{}

/// Desctructor of the @ref corpus_group type.
corpus_group::~corpus_group()
{}

/// Add a new corpus to the current instance of @ref corpus_group.
///
/// @param corp the new corpus to add.
void
corpus_group::add_corpus(const corpus_sptr& corp)
{
  if (!corp)
    return;

  // Ensure the new environment patches the current one.
  if (const environment* cur_env = get_environment())
    {
      if (environment* corp_env = corp->get_environment())
	ABG_ASSERT(cur_env == corp_env);
    }
  else
    set_environment(corp->get_environment());

  // Ensure the new architecture name matches the current one.
  string cur_arch = get_architecture_name(),
    corp_arch = corp->get_architecture_name();
  if (cur_arch.empty())
    set_architecture_name(corp_arch);
  else if (cur_arch != corp_arch)
    {
      std::cerr << "corpus '" << corp->get_path() << "'"
		<< " has architecture '" << corp_arch << "'"
		<< " but expected '" << cur_arch << "'\n";
      ABG_ASSERT_NOT_REACHED;
    }

  priv_->corpora.push_back(corp);
  corp->set_group(this);

  /// Add the unreferenced function and variable symbols of this
  /// corpus to the unreferenced symbols of the current corpus group.
  priv_->add_unref_fun_symbols(get_unreferenced_function_symbols());
  priv_->add_unref_var_symbols(get_unreferenced_variable_symbols());
}

/// Getter of the vector of corpora held by the current @ref
/// corpus_group.
///
/// @return the vector corpora.
const corpus_group::corpora_type&
corpus_group::get_corpora() const
{return priv_->corpora;}

/// Getter of the first corpus added to this Group.
///
/// @return the first corpus added to this Group.
const corpus_sptr
corpus_group::get_main_corpus() const
{return const_cast<corpus_group*>(this)->get_main_corpus();}

/// Getter of the first corpus added to this Group.
///
/// @return the first corpus added to this Group.
corpus_sptr
corpus_group::get_main_corpus()
{
  if (!get_corpora().empty())
    return get_corpora().front();
  return corpus_sptr();
}

/// Test if the current corpus group is empty.
///
/// @return true iff the current corpus group is empty.
bool
corpus_group::is_empty() const
{return get_corpora().empty();}

/// Get the functions exported by the corpora of the current corpus
/// group.
///
/// Upon its first invocation, this function walks the corpora
/// contained in the corpus group and caches the functions they exported.
///
/// Subsequent invocations just return the cached functions.
///
/// @return the exported functions.
const corpus::functions&
corpus_group::get_functions() const
{
  if (priv_->fns.empty())
    for (corpora_type::const_iterator i = get_corpora().begin();
	 i != get_corpora().end();
	 ++i)
      {
	corpus_sptr c = *i;
	for (corpus::functions::const_iterator f = c->get_functions().begin();
	     f != c->get_functions().end();
	     ++f)
	  {
	    interned_string fid = (*f)->get_id();
	    istring_function_decl_ptr_map_type::const_iterator j =
	      priv_->fns_map.find(fid);

	    if (j != priv_->fns_map.end())
	      // Don't cache the same function twice ...
	      continue;

	    priv_->fns_map[fid] = *f;
	    // really cache the function now.
	    priv_->fns.push_back(*f);
	  }
      }

  return priv_->fns;
}

/// Get the global variables exported by the corpora of the current
/// corpus group.
///
/// Upon its first invocation, this function walks the corpora
/// contained in the corpus group and caches the variables they
/// export.
///
/// @return the exported variables.
const corpus::variables&
corpus_group::get_variables() const
{
  if (priv_->vars.empty())
    for (corpora_type::const_iterator i = get_corpora().begin();
	 i != get_corpora().end();
	 ++i)
      {
	corpus_sptr c = *i;
	for (corpus::variables::const_iterator v = c->get_variables().begin();
	     v != c->get_variables().end();
	     ++v)
	  {
	    interned_string vid = (*v)->get_id();
	    istring_var_decl_ptr_map_type::const_iterator j =
	      priv_->vars_map.find(vid);

	    if (j != priv_->vars_map.end())
	      // Don't cache the same variable twice ...
	      continue;

	    priv_->vars_map[vid] = *v;
	    // Really cache the variable now.
	    priv_->vars.push_back(*v);
	  }
      }

  return priv_->vars;
}

/// Get the symbols of the global variables exported by the corpora of
/// the current @ref corpus_group.
///
/// @return the symbols of the global variables exported by the corpora
const string_elf_symbols_map_type&
corpus_group::get_var_symbol_map() const
{
  if (priv_->var_symbol_map.empty())
    for (corpora_type::const_iterator i = get_corpora().begin();
	 i != get_corpora().end();
	 ++i)
      priv_->var_symbol_map.insert((*i)->get_var_symbol_map().begin(),
				     (*i)->get_var_symbol_map().end());

  return priv_->var_symbol_map;
}

/// Get the symbols of the global functions exported by the corpora of
/// the current @ref corpus_group.
///
/// @return the symbols of the global functions exported by the corpora
const string_elf_symbols_map_type&
corpus_group::get_fun_symbol_map() const
{
  if (priv_->fun_symbol_map.empty())
    for (corpora_type::const_iterator i = get_corpora().begin();
	 i != get_corpora().end();
	 ++i)
      priv_->fun_symbol_map.insert((*i)->get_fun_symbol_map().begin(),
				   (*i)->get_fun_symbol_map().end());

  return priv_->fun_symbol_map;
}

/// Get a sorted vector of the symbols of the functions exported by
/// the corpora of the current group.
///
/// @return the sorted vectors of the exported function symbols.
const elf_symbols&
corpus_group::get_sorted_fun_symbols() const
{
  if (priv_->sorted_fun_symbols.empty()
      && !get_fun_symbol_map().empty())
    {
      for (corpora_type::const_iterator i = get_corpora().begin();
	   i != get_corpora().end();
	   ++i)
	{
	  corpus_sptr c = *i;
	  for (string_elf_symbols_map_type::const_iterator j =
		 c->get_fun_symbol_map().begin();
	       j != c->get_fun_symbol_map().begin();
	       ++j)
	    priv_->sorted_fun_symbols.insert(priv_->sorted_fun_symbols.end(),
					     j->second.begin(),
					     j->second.end());
	}
      comp_elf_symbols_functor comp;
      std::sort(priv_->sorted_fun_symbols.begin(),
		priv_->sorted_fun_symbols.end(),
		comp);
    }

  return priv_->sorted_fun_symbols;
}

/// Get a sorted vector of the symbols of the variables exported by
/// the corpora of the current group.
///
/// @return the sorted vectors of the exported variable symbols.
const elf_symbols&
corpus_group::get_sorted_var_symbols() const
{
  if (priv_->sorted_var_symbols.empty()
      && !get_var_symbol_map().empty())
    {
      for (corpora_type::const_iterator i = get_corpora().begin();
	   i != get_corpora().end();
	   ++i)
	{
	  corpus_sptr c = *i;
	  for (string_elf_symbols_map_type::const_iterator j =
		 c->get_var_symbol_map().begin();
	       j != c->get_var_symbol_map().begin();
	       ++j)
	    priv_->sorted_var_symbols.insert(priv_->sorted_var_symbols.end(),
					     j->second.begin(),
					     j->second.end());
	}
      comp_elf_symbols_functor comp;
      std::sort(priv_->sorted_var_symbols.begin(),
		priv_->sorted_var_symbols.end(),
		comp);
    }

  return priv_->sorted_var_symbols;
}

/// Get the set of function symbols not referenced by any debug info,
/// from all the corpora of the current corpus group.
///
/// Upon its first invocation, this function possibly walks all the
/// copora of this corpus group and caches the unreferenced symbols
/// they export.  The function then returns the cache.
///
/// Upon subsequent invocations, this functions just returns the
/// cached symbols.
///
/// @return the unreferenced symbols.
const elf_symbols&
corpus_group::get_unreferenced_function_symbols() const
{
  if (!priv_->unrefed_fun_symbols_built)
    if (priv_->unrefed_fun_symbols.empty())
      {
	for (corpora_type::const_iterator i = get_corpora().begin();
	     i != get_corpora().end();
	     ++i)
	  {
	    corpus_sptr c = *i;
	    for (elf_symbols::const_iterator e =
		   c->get_unreferenced_function_symbols().begin();
		 e != c->get_unreferenced_function_symbols().end();
		 ++e)
	      {
		string sym_id = (*e)->get_id_string();
		unordered_map<string, elf_symbol_sptr>::const_iterator j =
		  priv_->unrefed_fun_symbol_map.find(sym_id);
		if (j != priv_->unrefed_fun_symbol_map.end())
		  continue;

		priv_->unrefed_fun_symbol_map[sym_id] = *e;
		priv_->unrefed_fun_symbols.push_back(*e);
	      }
	  }
	priv_->unrefed_fun_symbols_built = true;
      }

  return priv_->unrefed_fun_symbols;
}

/// Get the set of variable symbols not referenced by any debug info,
/// from all the corpora of the current corpus group.
///
/// Upon its first invocation, this function possibly walks all the
/// copora of this corpus group and caches the unreferenced symbols
/// they export.  The function then returns the cache.
///
/// Upon subsequent invocations, this functions just returns the
/// cached symbols.
///
/// @return the unreferenced symbols.
const elf_symbols&
corpus_group::get_unreferenced_variable_symbols() const
{
  if (!priv_->unrefed_var_symbols_built)
    if (priv_->unrefed_var_symbols.empty())
      {
	for (corpora_type::const_iterator i = get_corpora().begin();
	     i != get_corpora().end();
	     ++i)
	  {
	    corpus_sptr c = *i;
	    for (elf_symbols::const_iterator e =
		   c->get_unreferenced_variable_symbols().begin();
		 e != c->get_unreferenced_variable_symbols().end();
		 ++e)
	      {
		string sym_id = (*e)->get_id_string();
		unordered_map<string, elf_symbol_sptr>::const_iterator j =
		  priv_->unrefed_var_symbol_map.find(sym_id);
		if (j != priv_->unrefed_var_symbol_map.end())
		  continue;

		priv_->unrefed_var_symbol_map[sym_id] = *e;
		priv_->unrefed_var_symbols.push_back(*e);
	      }
	  }
	priv_->unrefed_var_symbols_built = true;
      }

  return priv_->unrefed_var_symbols;
}

/// Getter of a pointer to the set of types reachable from public
/// interfaces of a given corpus group.
unordered_set<interned_string, hash_interned_string>*
corpus_group::get_public_types_pretty_representations()
{return &priv_->pub_type_pretty_reprs_;}

/// Test if the recording of reachable types (and thus, indirectly,
/// the recording of non-reachable types) is activated for the
/// current @ref corpus_group.
///
/// @return true iff the recording of reachable types is activated for
/// the current @ref corpus_group.
bool
corpus_group::recording_types_reachable_from_public_interface_supported()
{return !get_public_types_pretty_representations()->empty();}

// </corpus_group stuff>

}// end namespace ir
}// end namespace abigail
