libabigail/include/abg-corpus.h
Dodji Seketeli 2bb45265d3 Use environment by reference.
This patch simplifies how the environment is created and passed around
the functions that create front ends.  With this change, the
environment can simply be allocated on the stack and passed by
reference to the libabigail pipeline.

At the core of this change, type_or_decl_base::priv now carries a
const reference to an environment rather than a pointer.  The side
effect is that type_or_decl_base can no longer be copied.  This is not
a problem because throughout the years I could see that the use case
to copy ABI artifacts is just not there.  Similarly, elf_symbol::priv
carries a const reference to environment now, no more a pointer.
Getters, setters and code that use the environment from the ABI
artifacts are updated accordingly.

The DWARF front-end can now be created by code that looks like this,
for instance:

    vector<char**> debug_info_paths;
    abigail::ir::environment env;

    abigail::ctf_reader::read_context_sptr reader =
      abigail::dwarf_reader::create_read_context("elf/file/to/analyze",
						 debug_info_paths, env);

    elf_reader::status reading_status;
    corpus_sptr abi_corpus =
      abigail::dwarf_reader::read_corpus_from_elf(reader, reading_status);

	/* then do something with the resulting abi_corpus*/

Note how, you don't need to use the "new" operator to instantiate the
"env" object of type environment.  It can sit on the stack and it's
passed to the read_corpus_from_elf function by reference.

In other words, the internal representation types have been changed to
refer to the environment by reference, rather than requiring a pointer
to it.

	* include/abg-corpus.h (corpus::corpus)
	(corpus_group::corpus_group): Take environment&, not environment*
	as parameter.
	(corpus::{get_environment, set_environment}): Take or return
	environment&, not environment*.
	* src/abg-corpus.cc (corpus::corpus): Likewise.
	(corpus::{get_environment, set_environment}): Likewise.
	(corpus::add): Don't update the environment of the translation
	unit.
	(corpus::{record_type_as_reachable_from_public_interfaces,
	type_is_reachable_from_public_interfaces, init_format_version,
	add_corpus}): Adjust for accessing a reference to environment,
	rather than a pointer.
	* include/abg-ctf-reader.h (create_read_context): Take or return
	environment&, not environment*.
	* src/abg-ctf-reader.cc (read_context::ir_env): Make this a
	reference to environment, not pointer anymore.
	(read_context::read_context): Initialize the reference to
	environment.
	(read_context::initialize): Do not re-set the environment.
	(process_ctf_base_type)
	(build_ir_node_for_variadic_parameter_type)
	(process_ctf_enum_type, read_corpus): Adjust for accessing a
	reference to environment, rather than a pointer.
	(create_read_context, reset_read_context): Take environment&, not
	environment*.
	* include/abg-dwarf-reader.h (create_read_context)
	(reset_read_context, read_corpus_from_elf)
	(lookup_symbol_from_elf, lookup_public_function_symbol_from_elf):
	Likewise.
	* src/abg-dwarf-reader.cc (lookup_symbol_from_sysv_hash_tab)
	(lookup_symbol_from_gnu_hash_tab)
	(lookup_symbol_from_elf_hash_tab, lookup_symbol_from_symtab)
	(lookup_symbol_from_elf, lookup_public_function_symbol_from_elf):
	Likewise.
	(read_context::options_type::env): Make this be a reference to
	environment, not a pointer.
	(read_context::options::options): Remove the default constructor.
	Add a new one to initialize the environment data member.
	(read_context::read_context): Take environment&, not environment*.
	Initialize the options_ data member.
	(read_context::initialize): Do not take or initialize an
	environment anymore.
	(read_context::env): Return or take environment&, not
	environment*.
	(read_context::{get_die_qualified_name,
	get_die_qualified_type_name, get_die_pretty_type_representation,
	get_die_pretty_representation, compare_before_canonicalisation})
	(build_translation_unit_and_add_to_ir, build_function_type)
	(build_typedef_type, read_debug_info_into_corpus)
	(read_debug_info_into_corpus, build_ir_node_from_die)
	(build_ir_node_for_variadic_parameter_type, has_alt_debug_info):
	Adjust to use an environment&, not a pointer.
	(create_default_fn_sym, create_read_context)
	(read_corpus_from_elf, lookup_symbol_from_elf)
	(lookup_public_function_symbol_from_elf): Take environment&, not
	environment*.
	(reset_read_context): Do not take or reset environment* anymore.
	* include/abg-fwd.h (type_or_void): Likewise.
	* include/abg-ir.h (translation_unit::translation_unit): Likewise.
	(translation_unit::{get_environment, set_environment}): Likewise.
	(elf_symbol::elf_symbol): Likewise.
	(elf_symbol::create): Remove the overload that takes no
	parameter.  Then for overload that take parameters then take
	environment&, not environment*.
	(elf_symbol::get_environment): Take environment&, not
	environment*.
	(type_or_decl_base::type_or_decl_base): Make the copy constructor
	and assignment operator private.
	(type_or_decl_base::{s,g}et_environment): Take or return
	environment& not environment*.
	(type_or_decl_base::set_environment_for_artifact): Erase these
	methods.
	(decl_base::decl_base): Make copy constructor private.  Take or
	return environment&, not environment* for the other constructors.
	(scope_decl::scope_decl): Take or return environment&, not
	environment*.
	(type_base::type_base): Likewise.
	(scope_type_decl::scope_type_decl): Likewise.
	(namespace_decl::namespace_decl): Likewise.
	(qualified_type_def::qualified_type_def): Likewise.
	(pointer_type_def::pointer_type_def): Likewise.
	(reference_type_def::reference_type_def): Likewise.
	(array_type_def::subrange_type::subrange_type): Likewise.
	(enum_type_def::enumerator::enumerator): Likewise.
	(enum_type_def::enumerator::{get_name, get_qualified_name}):
	Return a string&, no more interned_string&.  As the enumerator
	don't have an enumerator anymore, there is no way to intern the
	string anymore.  Hopefully this won't incur a performance loss.
	(typedef_decl::typedef_decl, function_type::function_type)
	(method_type::method_type, template_decl::template_decl)
	(function_tdecl::function_tdecl, class_tdecl::class_tdecl)
	(class_or_union::class_or_union, class_decl::class_decl)
	(union_decl::union_decl): Take or return environment&, not
	environment*.
	* include/abg-reader.h (read_translation_unit_from_file)
	(read_translation_unit_from_buffer)
	(read_translation_unit_from_istream)
	(create_native_xml_read_context, create_native_xml_read_context)
	(read_corpus_from_native_xml, read_corpus_from_native_xml_file)
	(read_corpus_group_from_native_xml)
	(read_corpus_group_from_native_xml_file): Likewise.
	* include/abg-tools-utils.h
	(build_corpus_group_from_kernel_dist_under): Likewise.
	* src/abg-tools-utils.cc (maybe_load_vmlinux_dwarf_corpus)
	(maybe_load_vmlinux_ctf_corpus)
	(build_corpus_group_from_kernel_dist_under): Likewise.
	* include/abg-writer.h (create_write_context): Likewise.
	* src/abg-writer.cc (id_manager::m_env, id_manager::id_manager)
	(id_manager::get_environment, id_manager::get_id)
	(id_manager::get_id_with_prefix): Adjust.
	(write_context::m_env, write_context::write_context)
	(write_context::get_environment, write_context::get_config)
	(write_context::get_id_for_type, write_context::decl_is_emitted)
	(write_context::record_decl_as_emitted, create_write_context)
	(write_class_decl): Likewise.
	* src/abg-comparison.cc (compute_diff): Stop ensuring that the two
	artifacts being compare are in the same environment.  Now that the
	environment is passed by reference, the potential for
	accendentally comparing artifacts coming from different
	environments is very low, given how the API is used in practice.
	This is in the overloads for decl_base_sptr, type_base_sptr,
	var_decl_sptr, pointer_type_def_sptr, array_type_def_sptr,
	reference_type_def_sptr, qualified_type_def_sptr,
	enum_type_decl_sptr, class_decl_sptr, class_decl::base_spec_sptr,
	union_decl_sptr, scope_decl_sptr, function_decl::parameter_sptr,
	function_type_sptr, function_decl_sptr, type_decl_sptr,
	typedef_decl_sptr, translation_unit_sptr, corpus_sptr.
	* src/abg-corpus-priv.h (corpus::priv::env): Make this be a
	reference to environments, not a pointer.
	(corpus::priv::priv): Pass environment&, not environment*.
	* src/abg-ir-priv.h (translation_unit::priv::env_): Make this an
	environment&, not an environment* anymore.
	(translation_unit::priv::priv): Take an environment&, not an
	environment*.
	(environment::priv::{confirm_ct_propagation_for_types_dependant_on,
	confirm_ct_propagation,
	cancel_ct_propagation_for_types_dependant_on,
	mark_as_being_compared, unmark_as_being_compared,
	comparison_started, mark_as_being_compared, comparison_started}):
	Adjust to use an environment&, not a pointer.
	* src/abg-ir.cc (class environment_setter): Remove this class.
	(push_composite_type_comparison_operands)
	(pop_composite_type_comparison_operands, try_canonical_compare)
	(return_comparison_result, translation_unit::{get_global_scope,
	bind_function_type_life_time}): Adjust.
	(translation_unit::{translation_unit, get_environment}): Take or
	get an environment&, not an environment*.  Remove the getter that
	returns an environment*.
	(elf_symbol::priv::env_): Make this an environment&, not an
	environment*.
	(elf_symbol::priv::priv): Adjust.
	(elf_symbol::elf_symbol): Remove the default constructor.  Change
	the one that takes an environment.
	(elf_symbol::create): Remove the default one.  Adjust the one that
	takes an environment.
	(elf_symbol::get_environment): Adjust.
	(elf_symbol::set_environment_for_artifact): Remove.
	(environment::{get_void_type, get_variadic_parameter_type}):
	Adjust.
	(type_or_decl_base::priv::env_): Make this be a const
	environment&, not a const environment*.
	(type_or_decl_base::priv::priv): Adjust.
	(type_or_decl_base::type_or_decl_base): Remove the default and
	copy constructor.
	(type_or_decl_base::{set_environment, operator=})
	(set_environment_for_artifact): Remove.
	(type_or_decl_base::get_environment): Adjust.
	(decl_base::{decl_base, set_name, set_naming_typedef,
	set_linkage_name}): Adjust.
	(get_decl_name_for_comparison, strip_typedef)
	(strip_useless_const_qualification): Adjust.
	(scope_decl::{scope_decl, add_member_decl, insert_member_decl}):
	Adjust.
	(get_generic_anonymous_internal_type_name, get_type_name)
	(get_name_of_pointer_to_type, get_name_of_reference_to_type)
	(get_name_of_qualified_type, get_function_type_name)
	(get_method_type_name, is_void_pointer_type, lookup_basic_type)
	(lookup_union_type, lookup_union_type_per_location)
	(lookup_enum_type, lookup_typedef_type, lookup_pointer_type)
	(lookup_type, lookup_basic_type_per_location)
	(lookup_basic_type_per_location, lookup_basic_type)
	(lookup_class_type, lookup_class_types)
	(lookup_class_type_per_location, lookup_union_type)
	(lookup_enum_type, lookup_enum_types)
	(lookup_enum_type_per_location, lookup_typedef_type)
	(lookup_typedef_type_per_location, maybe_update_types_lookup_map)
	(maybe_update_types_lookup_map)
	(synthesize_type_from_translation_unit)
	(synthesize_function_type_from_translation_unit)
	(demangle_cplus_mangled_name, type_or_void)
	(types_defined_same_linux_kernel_corpus_public)
	(compare_types_during_canonicalization)
	(type_base::get_canonical_type_for, type_base::type_base)
	(type_base::get_cached_pretty_representation)
	(type_decl::type_decl, type_decl::get_qualified_name): Adjust.
	(scope_type_decl::scope_type_decl)
	(namespace_decl::namespace_decl, qualified_type_def::build_name)
	(qualified_type_def::qualified_type_def)
	(qualified_type_def::get_qualified_name)
	(qualified_type_def::set_underlying_type)
	(pointer_type_def::pointer_type_def)
	(pointer_type_def::set_pointed_to_type)
	(reference_type_def::reference_type_def)
	(reference_type_def::set_pointed_to_type)
	(array_type_def::subrange_type::subrange_type)
	(array_type_def::array_type_def, array_type_def::update_size)
	(array_type_def::set_element_type)
	(array_type_def::append_subranges)
	(array_type_def::get_qualified_name, enum_has_non_name_change):
	Adjust.
	(enum_type_decl::enumerator::priv::env_): Remove this pointer to
	env.  This is because the enumerator must be copy-able.  As the
	enumerator doesn't have an env anymore, it can't intern strings.
	So the enumerator name and qualified name is not going to be
	interned.  If that incurs a performance hit, we'll reconsider this
	decision.  For now, it seems to work OK.  As it simplifies things,
	I am keeping this for now.
	(enum_type_decl::enumerator::priv::{name, qualified_name}): Make
	this be string, not interned_string.
	(enum_type_decl::enumerator::get_environment): Remove.
	(enum_type_decl::enumerator::priv::priv): Adjust.
	(enum_type_decl::enumerator::enumerator)
	(enum_type_decl::enumerator::operator=)
	(enum_type_decl::enumerator::get_name)
	(enum_type_decl::enumerator::get_qualified_name)
	(enum_type_decl::enumerator::set_name): Likewise.
	(typedef_decl::typedef_decl): Adjust.
	(var_decl::get_id, var_decl::get_qualified_name): Adjust.
	(function_type::function_type, method_type::method_type)
	(function_decl::get_pretty_representation_of_declarator)
	(function_decl::set_symbol): Likewise.
	(function_decl::get_id, function_decl::parameter::get_type)
	(function_decl::parameter::get_type_name)
	(function_decl::parameter::get_type_pretty_representation)
	(function_decl::parameter::get_name_id)
	(class_or_union::class_or_union, class_decl::class_decl)
	(class_decl::add_base_specifier, union_decl::union_decl)
	(union_decl::union_decl, template_decl::template_decl)
	(class_tdecl::class_tdecl)
	(maybe_cancel_propagated_canonical_type)
	(dump_classes_being_compared)
	(dump_fn_types_being_compared, copy_member_function)
	(maybe_propagate_canonical_type, keep_type_alive)
	(is_non_canonicalized_type, qualified_name_setter::do_update):
	Likewise.
	(equals): Adjust the overloads for var_decl, function_type,
	class_or_union, class_decl, union_decl.
	* src/abg-reader.cc (read_context::m_env): Make this be an
	environment&, not an environment*.
	(read_context::read_context): Adjust
	(read_context::set_environment): Remove.
	(read_context::{get_environment,
	maybe_check_abixml_canonical_type_stability}): Adjust.
	(read_corpus_from_input, read_corpus_group_from_native_xml)
	(read_corpus_group_from_native_xml_file)
	(read_translation_unit_from_file)
	(read_translation_unit_from_buffer, read_translation_unit)
	(maybe_map_type_with_type_id, build_namespace_decl)
	(build_elf_symbol, build_function_parameter, build_function_decl)
	(build_function_type, build_enum_type_decl, build_class_decl)
	(build_union_decl, build_function_tdecl, build_class_tdecl)
	(build_type_tparameter, read_translation_unit_from_istream)
	(create_native_xml_read_context, read_corpus_from_native_xml):
	Likewise.
	* src/abg-symtab-reader.h (symtab::load): Likewise.
	* src/abg-symtab-reader.cc (symtab::load): Likewise.
	* tests/print-diff-tree.cc (main): Likewise.
	* tests/test-abidiff.cc (main): Likewise.
	* tests/test-diff-dwarf.cc (main): Likewise.
	* tests/test-ir-walker.cc (main): Likewise.
	* tests/test-read-ctf.cc (test_task_ctf::perform): Likewise.
	* tests/test-symtab.cc (read_corpus): Likewise.
	* tools/abicompat.cc (read_corpus, main): Likewise.
	* tools/abidiff.cc (main): Likewise.
	* tools/abidw.cc (load_corpus_and_write_abixml)
	(load_kernel_corpus_group_and_write_abixml, main): Likewise.
	* tools/abilint.cc (main): Likewise.
	* tools/abipkgdiff.cc (compare, compare_to_self)
	(compare_prepared_linux_kernel_packages,  compare_task::perform):
	Likewise.
	* tools/abisym.cc (main): Likewise.
	* tools/kmidiff.cc (main): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-11-18 15:22:49 +01:00

407 lines
8.5 KiB
C++

// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// -*- mode: C++ -*-
//
// Copyright (C) 2013-2022 Red Hat, Inc.
/// @file
#ifndef __ABG_CORPUS_H__
#define __ABG_CORPUS_H__
#include <abg-ir.h>
namespace abigail
{
namespace ir
{
/// This is the abstraction of a set of translation units (themselves
/// seen as bundles of unitary abi artefacts like types and decls)
/// bundled together as a corpus. A corpus is thus the Application
/// binary interface of a program, a library or just a set of modules
/// put together.
class corpus
{
public:
/// A convenience typedef for std::vector<string>.
typedef vector<string> strings_type;
/// Convenience typedef for std::vector<abigail::ir::function_decl*>
typedef vector<function_decl*> functions;
///Convenience typedef for std::vector<abigail::ir::var_decl*>
typedef vector<var_decl*> variables;
class exported_decls_builder;
/// Convenience typedef for shared_ptr<exported_decls_builder>.
typedef shared_ptr<exported_decls_builder> exported_decls_builder_sptr;
/// This abstracts where the corpus comes from. That is, either it
/// has been read from the native xml format, from DWARF or built
/// artificially using the library's API.
enum origin
{
ARTIFICIAL_ORIGIN = 0,
NATIVE_XML_ORIGIN = 1,
DWARF_ORIGIN = 1 << 1,
CTF_ORIGIN = 1 << 2,
LINUX_KERNEL_BINARY_ORIGIN = 1 << 3
};
private:
corpus();
void set_group(corpus_group*);
void init_format_version();
public:
struct priv;
std::unique_ptr<priv> priv_;
corpus(const ir::environment&, const string& path= "");
virtual ~corpus();
const environment&
get_environment() const;
void
add(const translation_unit_sptr);
const translation_units&
get_translation_units() const;
const translation_unit_sptr
find_translation_unit(const string &path) const;
void
drop_translation_units();
type_maps&
get_types();
const type_maps&
get_types() const;
type_maps&
get_type_per_loc_map();
const type_maps&
get_type_per_loc_map() const;
virtual bool
recording_types_reachable_from_public_interface_supported();
void
record_type_as_reachable_from_public_interfaces(const type_base&);
bool
type_is_reachable_from_public_interfaces(const type_base&) const;
const vector<type_base_wptr>&
get_types_not_reachable_from_public_interfaces() const;
const corpus_group*
get_group() const;
corpus_group*
get_group();
origin
get_origin() const;
void
set_origin(origin);
string&
get_format_major_version_number() const;
void
set_format_major_version_number(const string&);
string&
get_format_minor_version_number() const;
void
set_format_minor_version_number(const string&);
string&
get_path() const;
void
set_path(const string&);
const vector<string>&
get_needed() const;
void
set_needed(const vector<string>&);
const string&
get_soname();
void
set_soname(const string&);
const string&
get_architecture_name() const;
void
set_architecture_name(const string&);
virtual bool
is_empty() const;
bool
operator==(const corpus&) const;
void
set_symtab(symtab_reader::symtab_sptr);
const symtab_reader::symtab_sptr&
get_symtab() const;
virtual const string_elf_symbols_map_type&
get_fun_symbol_map() const;
const string_elf_symbols_map_type&
get_undefined_fun_symbol_map() const;
virtual const elf_symbols&
get_sorted_fun_symbols() const;
const elf_symbols&
get_sorted_undefined_fun_symbols() const;
virtual const string_elf_symbols_map_type&
get_var_symbol_map() const;
const string_elf_symbols_map_type&
get_undefined_var_symbol_map() const;
virtual const elf_symbols&
get_sorted_var_symbols() const;
const elf_symbols&
get_sorted_undefined_var_symbols() const;
const elf_symbol_sptr
lookup_function_symbol(const string& n) const;
const elf_symbol_sptr
lookup_function_symbol(const string& symbol_name,
const elf_symbol::version& version) const;
const elf_symbol_sptr
lookup_function_symbol(const elf_symbol& symbol) const;
const elf_symbol_sptr
lookup_variable_symbol(const string& n) const;
const elf_symbol_sptr
lookup_variable_symbol(const string& symbol_name,
const elf_symbol::version& version) const;
const elf_symbol_sptr
lookup_variable_symbol(const elf_symbol& symbol) const;
virtual const functions&
get_functions() const;
const vector<function_decl*>*
lookup_functions(const string& id) const;
void
sort_functions();
virtual const variables&
get_variables() const;
void
sort_variables();
virtual const elf_symbols&
get_unreferenced_function_symbols() const;
virtual const elf_symbols&
get_unreferenced_variable_symbols() const;
vector<string>&
get_regex_patterns_of_fns_to_suppress();
const vector<string>&
get_regex_patterns_of_fns_to_suppress() const;
vector<string>&
get_regex_patterns_of_vars_to_suppress();
const vector<string>&
get_regex_patterns_of_vars_to_suppress() const;
vector<string>&
get_regex_patterns_of_fns_to_keep();
const vector<string>&
get_regex_patterns_of_fns_to_keep() const;
vector<string>&
get_sym_ids_of_fns_to_keep();
const vector<string>&
get_sym_ids_of_fns_to_keep() const;
vector<string>&
get_regex_patterns_of_vars_to_keep();
const vector<string>&
get_regex_patterns_of_vars_to_keep() const;
vector<string>&
get_sym_ids_of_vars_to_keep();
const vector<string>&
get_sym_ids_of_vars_to_keep() const;
void
maybe_drop_some_exported_decls();
exported_decls_builder_sptr
get_exported_decls_builder() const;
friend class type_base;
friend class corpus_group;
};// end class corpus.
corpus::origin
operator|(corpus::origin l, corpus::origin r);
corpus::origin
operator|=(corpus::origin &l, corpus::origin r);
corpus::origin
operator&(corpus::origin l, corpus::origin r);
corpus::origin
operator&=(corpus::origin &l, corpus::origin r);
/// Abstracts the building of the set of exported variables and
/// functions.
///
/// Given a function or variable, this type can decide if it belongs
/// to the list of exported functions and variables based on all the
/// parameters needed.
class corpus::exported_decls_builder
{
class priv;
std::unique_ptr<priv> priv_;
// Forbid default construction.
exported_decls_builder();
public:
friend class corpus;
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);
const functions&
exported_functions() const;
functions&
exported_functions();
const variables&
exported_variables() const;
variables&
exported_variables();
void
maybe_add_fn_to_exported_fns(function_decl*);
void
maybe_add_var_to_exported_vars(var_decl*);
}; //corpus::exported_decls_builder
/// Abstraction of a group of corpora.
///
/// A corpus group is a union of corpora. It provides a unified view
/// of a set of corpora. It lets you get the set of functions,
/// variables and symbols that are defined and exported by a set of
/// corpora.
class corpus_group : public corpus
{
struct priv;
std::unique_ptr<priv> priv_;
// Forbid copy
corpus_group(const corpus_group&);
public:
typedef vector<corpus_sptr> corpora_type;
corpus_group(const ir::environment&, const string&);
virtual ~corpus_group();
void add_corpus(const corpus_sptr&);
const corpora_type&
get_corpora() const;
const corpus_sptr
get_main_corpus() const;
corpus_sptr
get_main_corpus();
virtual bool
is_empty() const;
virtual const corpus::functions&
get_functions() const;
virtual const corpus::variables&
get_variables() const;
virtual const string_elf_symbols_map_type&
get_var_symbol_map() const;
virtual const string_elf_symbols_map_type&
get_fun_symbol_map() const;
virtual const elf_symbols&
get_sorted_fun_symbols() const;
virtual const elf_symbols&
get_sorted_var_symbols() const;
virtual const elf_symbols&
get_unreferenced_function_symbols() const;
virtual const elf_symbols&
get_unreferenced_variable_symbols() const;
unordered_set<interned_string, hash_interned_string>*
get_public_types_pretty_representations();
virtual bool
recording_types_reachable_from_public_interface_supported();
bool
operator==(const corpus_group&) const;
}; // end class corpus_group
}// end namespace ir
}//end namespace abigail
#endif //__ABG_CORPUS_H__