Implement generic diff tree walking and port categorization over it
* include/abg-comp-filter.h (apply_filter): Declare new overload
that takes a corpus_diff_sptr ...
* src/abg-comp-filter.cc (apply_filter): ... and define it. On
the existing overload for diff_sptr, make sure to traverse all
diff nodes, even those that have already been traversed.
* include/abg-comparison.h (enum diff_category): Remove
NOT_REDUNDANT_CATEGORY, add REDUNDANT_CATEGORY.
(operator&=, +operator<<): Declare new operators for enum diff_category.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden):
(diff_context::categorizing_redundancy): Remove this declaration.
(diff_context::maybe_apply_filters): Declare a new overload that
takes a corpus_diff_sptr. And a take a new flag that says if it
should visit all nodes including those that have already been
visited.
(diff::priv_): Make this data member protected.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node,
get_pretty_representation, chain_into_hierarchy, traverse}):
Declare new member functions.
(distinct_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Likewise.
(distinct_diff::traverse): Remove.
(pointer_diff::pointer_diff): Take the underlying type diff in
parameter.
(pointer_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(pointer_diff::traverse): Remove.
(reference_type_def::reference_type_def): Take the underlying type
diff in parameter.
({array_type_def, reference_type_def}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({array_type_diff, reference_type_def}::traverse): Remove.
(qualified_type_diff::qualified_type_diff): Take the underlying
type diff in parameter.
({enum_diff, qualified_type_diff, class_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({enum_diff, qualified_type_diff, class_diff}::traverse): Remove.
(is_class_diff): Declare new function.
(base_diff::base_diff): Take the underlying type diff in
parameter.
({scope_diff, base_diff}::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({scope_diff, base_diff}::traverse): Remove.
(function_decl_diff::function_decl_diff): Take the return type
diff as parameter.
({function_decl_diff, type_decl_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({function_decl_diff, type_decl_diff}::traverse): Remove.
(typedef_diff::typedef_diff): Take the underlying type diff as
parameter.
(typedef::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({typedef, translation_unit_diff}::traverse): Remove member
function.
(corpus_diff::{finish_diff_type, children_nodes,
append_child_node, changed_variables, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(class diff_node_visitor::{visit_begin, visit_end}): Declare new
member functions.
(propagate_categories, print_diff_tree, categorizing_redundancy)
(clear_redundancy_categorization, apply_filters): New functions
and function overloads.
* src/abg-comparison.cc (TRY_PRE_VISIT, TRY_PRE_VISIT_CLASS_DIFF)
(TRY_POST_VISIT, TRY_POST_VISIT_CLASS_DIFF)
(CATEGORIZE_REDUNDANCY_FROM_CHILD_NODE)
(UPDATE_REDUNDANCY_CATEGORIZATION_FROM_NODE_SUBTREE)
(TRAVERSE_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_FN_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(ENSURE_DIFF_NODE_TRAVERSED_ONCE)
(ENSURE_MEM_DIFF_NODE_TRAVERSED_ONCE): Remove these macros.
Hurrah.
(diff_context::priv::categorizing_redundancy_): Remove.
(diff_context::priv::forbid_traversing_a_node_twice_): Add new
data member.
(diff_context::priv::priv): Adjust.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden}): Define new member
functions.
(diff_context::maybe_apply_filters): Once filters are applied (and
categories are set to the relevant diff tree nodes, run a pass
over the diff tree to propagate the categories to the relevant
diff tree parent nodes. Add an overload for corpus_diff_sptr.
(diff_context::categorizing_redundancy): Remove member function.
(diff_context::maybe_apply_filters): Define a new overload for
corpus_diff_sptr
(struct diff::priv::{finished_, traversing_, children_,
pretty_representation_}): New data members.
(diff::priv::priv): Adjust.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node, traverse,
set_category, get_pretty_representation, chain_into_hierarchy}):
Define new member functions.
(diff::is_filtered_out): Do not refer to NOT_REDUNDANT_CATEGORY
anymore. Rather, use the new REDUNDANT_CATEGORY.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff}::{get_pretty_representation, chain_into_hierarchy,
finish_diff_type}): Define new member functions.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff, translation_unit_diff}::traverse): Remove member
functions.
(operator&=, operator<<): Define new operators for diff_category.
({function_decl_diff, typedef_diff}::priv::priv): Add a new
constructor.
(pointer_diff::{priv::priv, pointer_diff})
(reference_diff::{priv::priv, reference_diff})
(qualified_type_diff::{priv::priv, qualified_type_diff})
(enum_diff::{priv::priv, enum_diff}, base_diff::{priv::priv,
base_diff}, function_decl_diff::function_decl_diff): Take the
underlying type diff in parameter.
(compute_diff): Adjust the pointer_diff, reference_diff,
qualified_type_diff, base_diff, function_decl_diff overloads.
(class_diff::priv::{count_filtered_bases,
count_filtered_subtype_changed_dm, count_filtered_changed_dm,
count_filtered_changed_mem_fns, count_filtered_inserted_mem_fns,
count_filtered_deleted_mem_fns}): Adjust for the call to
diff_context::maybe_apply_filters.
(corpus_diff::priv::{finished_, pretty_representation_}): New data
member.
(corpus_diff::priv::priv): New constructor.
(corpus_diff::priv::clear_redundancy_categorization): Define new
member function.
(corpus_diff::priv::apply_filters_and_compute_diff_stats):
Adjust for call to diff_context::maybe_apply_filters. Also, call
clear_redundancy_categorization at the end.
(corpus_diff::priv::categorize_redundant_changed_sub_nodes):
Revisit logic.
(corpus_diff::{chain_into_hierarchy, finish_diff_type,
children_nodes, append_child_node, changed_variables,
get_pretty_representation}): Define new member functions.
(corpus_diff::report): Categorize redundancy for every top level
function/variable diff.
(corpus_diff::traverse): Adjust to the new traversing interface.
(diff_node_visitor::{visit_begin, visit_end}): Define new member
functions.
(struct category_propagation_visitor, struct diff_node_printer)
(struct redundancy_marking_visitor, struct
redundancy_clearing_visitor): New diff tree node visitors.
(propagate_categories, print_diff_tree, categorize_redundancy)
(clear_redundancy_categorization, apply_filters): Define new
functions.
* tests/Makefile.am: Add the new tests/print-diff-tree.cc to the
source distribution. Build it into a tests/printdifftree binary.
* tools/abidiff.cc (print_diff_tree): Add debugging functions to
call from within the debugger. By default, this function and its
overloads are not compiled.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-10 11:15:40 +00:00
|
|
|
// -*- Mode: C++ -*-
|
|
|
|
|
2015-01-07 12:53:58 +00:00
|
|
|
// Copyright (C) 2013-2015 Red Hat, Inc.
|
Implement generic diff tree walking and port categorization over it
* include/abg-comp-filter.h (apply_filter): Declare new overload
that takes a corpus_diff_sptr ...
* src/abg-comp-filter.cc (apply_filter): ... and define it. On
the existing overload for diff_sptr, make sure to traverse all
diff nodes, even those that have already been traversed.
* include/abg-comparison.h (enum diff_category): Remove
NOT_REDUNDANT_CATEGORY, add REDUNDANT_CATEGORY.
(operator&=, +operator<<): Declare new operators for enum diff_category.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden):
(diff_context::categorizing_redundancy): Remove this declaration.
(diff_context::maybe_apply_filters): Declare a new overload that
takes a corpus_diff_sptr. And a take a new flag that says if it
should visit all nodes including those that have already been
visited.
(diff::priv_): Make this data member protected.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node,
get_pretty_representation, chain_into_hierarchy, traverse}):
Declare new member functions.
(distinct_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Likewise.
(distinct_diff::traverse): Remove.
(pointer_diff::pointer_diff): Take the underlying type diff in
parameter.
(pointer_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(pointer_diff::traverse): Remove.
(reference_type_def::reference_type_def): Take the underlying type
diff in parameter.
({array_type_def, reference_type_def}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({array_type_diff, reference_type_def}::traverse): Remove.
(qualified_type_diff::qualified_type_diff): Take the underlying
type diff in parameter.
({enum_diff, qualified_type_diff, class_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({enum_diff, qualified_type_diff, class_diff}::traverse): Remove.
(is_class_diff): Declare new function.
(base_diff::base_diff): Take the underlying type diff in
parameter.
({scope_diff, base_diff}::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({scope_diff, base_diff}::traverse): Remove.
(function_decl_diff::function_decl_diff): Take the return type
diff as parameter.
({function_decl_diff, type_decl_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({function_decl_diff, type_decl_diff}::traverse): Remove.
(typedef_diff::typedef_diff): Take the underlying type diff as
parameter.
(typedef::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({typedef, translation_unit_diff}::traverse): Remove member
function.
(corpus_diff::{finish_diff_type, children_nodes,
append_child_node, changed_variables, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(class diff_node_visitor::{visit_begin, visit_end}): Declare new
member functions.
(propagate_categories, print_diff_tree, categorizing_redundancy)
(clear_redundancy_categorization, apply_filters): New functions
and function overloads.
* src/abg-comparison.cc (TRY_PRE_VISIT, TRY_PRE_VISIT_CLASS_DIFF)
(TRY_POST_VISIT, TRY_POST_VISIT_CLASS_DIFF)
(CATEGORIZE_REDUNDANCY_FROM_CHILD_NODE)
(UPDATE_REDUNDANCY_CATEGORIZATION_FROM_NODE_SUBTREE)
(TRAVERSE_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_FN_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(ENSURE_DIFF_NODE_TRAVERSED_ONCE)
(ENSURE_MEM_DIFF_NODE_TRAVERSED_ONCE): Remove these macros.
Hurrah.
(diff_context::priv::categorizing_redundancy_): Remove.
(diff_context::priv::forbid_traversing_a_node_twice_): Add new
data member.
(diff_context::priv::priv): Adjust.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden}): Define new member
functions.
(diff_context::maybe_apply_filters): Once filters are applied (and
categories are set to the relevant diff tree nodes, run a pass
over the diff tree to propagate the categories to the relevant
diff tree parent nodes. Add an overload for corpus_diff_sptr.
(diff_context::categorizing_redundancy): Remove member function.
(diff_context::maybe_apply_filters): Define a new overload for
corpus_diff_sptr
(struct diff::priv::{finished_, traversing_, children_,
pretty_representation_}): New data members.
(diff::priv::priv): Adjust.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node, traverse,
set_category, get_pretty_representation, chain_into_hierarchy}):
Define new member functions.
(diff::is_filtered_out): Do not refer to NOT_REDUNDANT_CATEGORY
anymore. Rather, use the new REDUNDANT_CATEGORY.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff}::{get_pretty_representation, chain_into_hierarchy,
finish_diff_type}): Define new member functions.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff, translation_unit_diff}::traverse): Remove member
functions.
(operator&=, operator<<): Define new operators for diff_category.
({function_decl_diff, typedef_diff}::priv::priv): Add a new
constructor.
(pointer_diff::{priv::priv, pointer_diff})
(reference_diff::{priv::priv, reference_diff})
(qualified_type_diff::{priv::priv, qualified_type_diff})
(enum_diff::{priv::priv, enum_diff}, base_diff::{priv::priv,
base_diff}, function_decl_diff::function_decl_diff): Take the
underlying type diff in parameter.
(compute_diff): Adjust the pointer_diff, reference_diff,
qualified_type_diff, base_diff, function_decl_diff overloads.
(class_diff::priv::{count_filtered_bases,
count_filtered_subtype_changed_dm, count_filtered_changed_dm,
count_filtered_changed_mem_fns, count_filtered_inserted_mem_fns,
count_filtered_deleted_mem_fns}): Adjust for the call to
diff_context::maybe_apply_filters.
(corpus_diff::priv::{finished_, pretty_representation_}): New data
member.
(corpus_diff::priv::priv): New constructor.
(corpus_diff::priv::clear_redundancy_categorization): Define new
member function.
(corpus_diff::priv::apply_filters_and_compute_diff_stats):
Adjust for call to diff_context::maybe_apply_filters. Also, call
clear_redundancy_categorization at the end.
(corpus_diff::priv::categorize_redundant_changed_sub_nodes):
Revisit logic.
(corpus_diff::{chain_into_hierarchy, finish_diff_type,
children_nodes, append_child_node, changed_variables,
get_pretty_representation}): Define new member functions.
(corpus_diff::report): Categorize redundancy for every top level
function/variable diff.
(corpus_diff::traverse): Adjust to the new traversing interface.
(diff_node_visitor::{visit_begin, visit_end}): Define new member
functions.
(struct category_propagation_visitor, struct diff_node_printer)
(struct redundancy_marking_visitor, struct
redundancy_clearing_visitor): New diff tree node visitors.
(propagate_categories, print_diff_tree, categorize_redundancy)
(clear_redundancy_categorization, apply_filters): Define new
functions.
* tests/Makefile.am: Add the new tests/print-diff-tree.cc to the
source distribution. Build it into a tests/printdifftree binary.
* tools/abidiff.cc (print_diff_tree): Add debugging functions to
call from within the debugger. By default, this function and its
overloads are not compiled.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-10 11:15:40 +00:00
|
|
|
//
|
|
|
|
// This file is part of the GNU Application Binary Interface Generic
|
|
|
|
// Analysis and Instrumentation Library (libabigail). This library is
|
|
|
|
// free software; you can redistribute it and/or modify it under the
|
|
|
|
// terms of the GNU Lesser General Public License as published by the
|
|
|
|
// Free Software Foundation; either version 3, or (at your option) any
|
|
|
|
// later version.
|
|
|
|
|
|
|
|
// This library is distributed in the hope that it will be useful, but
|
|
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// General Lesser Public License for more details.
|
|
|
|
|
|
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
|
|
// License along with this program; see the file COPYING-LGPLV3. If
|
|
|
|
// not, see <http://www.gnu.org/licenses/>.
|
|
|
|
//
|
|
|
|
// Author: Dodji Seketeli
|
|
|
|
//
|
|
|
|
|
|
|
|
#include <cstring>
|
|
|
|
#include <iostream>
|
|
|
|
#include "abg-comparison.h"
|
|
|
|
#include "abg-dwarf-reader.h"
|
|
|
|
|
|
|
|
using std::cout;
|
|
|
|
using std::cerr;
|
|
|
|
using std::ostream;
|
|
|
|
using std::string;
|
|
|
|
|
|
|
|
using abigail::comparison::diff;
|
|
|
|
using abigail::comparison::diff_sptr;
|
Introduce the concept of environment
There are resources needed by the type system and other artifacts of
libabigail. Today, when the life time of those resources need to be
greater than all of artifacts of Abigail, then said resources are made
global.
But then global resources are not great, if anything because they
complicate the future use of the library in concurrent computing
setups.
As I was in the need to add one resource to be used by the type
system, I decided to sit down and first overhaul how these long lived
resources needed to be handled.
And here comes the concept of "environment". An environment is a
place where one can put resources that need to live longer than all
the other artifacts of the Abigail system. And so, the code that
creates Abigail artifacts needs and environment of for said artifacts
to use. In other words, artifacts now use an environment.
This has interesting and strong implications. We can only compare two
artifacts if they use the same environment. This is quite a strong
requirement.
But then when this requirement is fulfilled, comparing two types
amounts to just comparing two pointer values; hash values for types
can also be cached. Now *that* is great for speed of comparison, is
it not?
This patch introduce the concept environment (which is basically a new
abigail::ir::environment type), removes the global variables and uses
the environment instead. Each ABI artifact (either type or decl) now
has a ::get_environment() member function to get its environment.
This patch also disables the caching of hash values because the
caching must happen only *after* all types have been canonicalized.
We were not respecting that requirement until now, and that introduces
wrong hash values. A subsequent patch is going to re-introduce hash
value caching again, once the infrastructure is in place to set a flag
in the environment (hah!) once type canonicalization is done, and then
later read that flag when some client code requests a hash value, to
know if we should look in the hash value cache or not.
The patch obviously changes the output of numerous regression tests
(if anything b/c it disables hash value caching) so 'make check'
yields regressions. But then, it's only the subsequent patch that
updates the tests.
* include/abg-ir.h: Adjust note about memory management.
(class environment): Declare new class.
(translation_unit::translation_unit): Take an environment in
parameter.
(translation_unit::{g,s}et_environment): Declare new member
functions.
(type_or_decl_base::{g,s}et_environment): Likewise.
(type_or_decl_base::{get_cached_hash_value,
set_cached_hash_value}): Change the name of
decl_base::peek_hash_value() and decl_base::set_hash() here into
these and move them here.
(type_or_decl_base::hashing_started): Move
decl_base::hashing_started() here.
({g,s}et_environment_for_artifact): Declare new functions.
(class decl_base): Move member functions hashing_started(),
peek_hash_value() and set_hash() on to the type_or_decl_base base
class.
(scope_decl::scope_decl): Initialize the virtual member
type_or_decl_base().
(type_decl::{get_void_type_decl,
get_variadic_parameter_type_decl}): Remove these static member
functions. They are now non-static member functions of the new
environment type.
* src/abg-ir.cc (class environment_setter): New internal class.
(get_canonical_types_map): Remove. This now becomes a member
function of the environment type.
(class usage_watchdog): Remove.
(usage_watchdog_{s,w}ptr): Remove these typedefs.
(get_usage_watchdog_wptr, ref_usage_watchdog)
(maybe_cleanup_type_system_data): Remove these functions.
(translation_unit::priv::usage_watchdog_): Remove data member.
(translation_unit::priv::env_): New data member.
(translation_unit::priv::priv): Take an environment and initialize
the new env_ data member. Do not initialize the removed
usage_watchdog_.
(translation_unit::translation_unit): Take an environment
parameter.
(translation_unit::get_global_scope): Set the environment of a new
global scope.
(translation_unit::{g,s}et_environment): New accessors.
(translation_unit::bind_function_type_life_time): Set the
environment of the function type.
(struct environment::priv): New class.
(environment::{environment, ~environment, get_canonical_types_map,
get_variadic_parameter_type_decl, canonicalization_is_done}): New
member functions.
(struct type_or_decl_base::priv): New class.
(type_or_decl_base::{type_or_decl_base, hashing_started,
get_cached_hash_value, set_cached_hash_value, set_environment,
get_environment, traverse}): New member functions.
({s,g}get_environment_for_artifact): New functions.
(decl_base::priv::{hash_, hashing_started}): Remove.
(decl_base::priv::priv): Adjust.
(decl_base::decl_base): In the copy constructor, initialize the
virtual base type_or_decl_base. Do not initialize hash_ and
hashing_started data member that got removed.
(decl_base::{hashing_started, peek_hash_value, set_hash}): Remove
member functions.
(strip_typedef): Set the environment of the new type which has its
typedefs stripped off. Adjust the call to type_or_void().
(scope_decl::{add, insert}_member_decl): Set the environment of
the new member decl to the environment of its scope.
(synthesize_type_from_translation_unit)
(synthesize_function_type_from_translation_unit): Set the
environment for the newly synthesized type. Adjust calls to
type_or_void().
(type_or_void): Take an environment in parameter. Get the void
type from the environment.
(get_canonical_types_map): Remove.
(type_base::get_canonical_type_for): Get the canonical types map
from the environment, not from a global variable.
(type_decl::{get_void_type_decl,
get_variadic_parameter_type_decl}): Remove.
(pointer_type_def::pointer_type_def): Adjust call to type_or_void.
(reference_type_def::reference_type_def): Likewise.
(function_decl::parameter::get_pretty_representation): Get the
variadic parameter type decl from the environment.
(class_decl::priv::classes_being_compared_): Remove static data
member.
(class_decl::priv::{mark_as_being_compared,
unmark_as_being_compared, comparison_started): Use the "classes
being compared" map from the environment.
(class_decl::base_spec::get_hash): Adjust.
(keep_type_alive): Get the alive types array from the environment)
not from a global variable anymore.
(get_next_string): Put the counter in thread-local storage.
* src/abg-hash.cc (scope_decl::hash::operator())
(function_decl::hash::operator()): Do not handle caching (here).
* include/abg-corpus.h (corpus::{g,s}et_environment): Declare new
accessors.
* src/abg-corpus.cc (corpus::priv::env): New data member.
(corpus::priv::priv): Initialize it.
(corpus::corpus): Take an environment in parameter.
(corpus::{g,s}et_environment): Define new member functions
(corpus::add): Set the environment of the newly added translation
unit, if it's not set already set. In any case, assert that the
translation unit must use the same environment as the corpus.
* include/abg-dwarf-reader.h (create_read_context)
(read_corpus_from_elf): Take an environment parameter.
({s,g}et_debug_info_root_path, {s,g}et_environment): Declare new
functions.
* src/abg-dwarf-reader.cc (read_context::{env_,
offline_callbacks_}): New data members.
(read_context::read_context): Initialize them.
(read_context::clear_per_translation_unit_data): Do not touch the
void type declaration, it doesn't belong to the translation unit.
(read_context::{env, offline_callbacks}): New accessors.
(read_context::{create_default_dwfl}): New member function.
(read_context::dwfl_handle): Add a setter overload.
({s,g}et_debug_info_root_path): Define new accessors.
(create_default_dwfl, create_dwfl_sptr, create_default_dwfl_sptr):
Remove these.
(build_translation_unit_and_add_to_ir): Adjust to pass the
environment to the newly created translation unit.
(build_function_decl): Adjust to pass the environment to the
created function and parameter types. Get variadic parameter type
node from the current environment, not from a global variable.
And do not try to canonicalize function types here.
(read_debug_info_into_corpus): Set the environment of the newly
created corpus.
(build_ir_node_for_void_type): Get the void type node from the
current environment, rather than from a global variable.
(create_read_context): Take the environment in parameter.
Create the default dwarf front end library handle using the new
member function of the read context. Set the current environment
used by the reader.
(read_corpus_from_elf): Take an environment in
parameter. Overhaul. This is now simpler.
(has_alt_debug_info): Adjust the call to create_read_context() to
make it pass an empty environment.
* include/abg-fwd.h (class environment): Forward declare.
* include/abg-reader.h (read_translation_unit_from_file)
(read_translation_unit_from_buffer)
(read_translation_unit_from_istream)
(read_corpus_from_native_xml): Take an environment in parameter.
* src/abg-reader.cc (read_context::m_env): New data member.
(read_context::read_context): Initialize it.
(read_context::{get_environment, set_environment}): New data
member.
(read_translation_unit): Set environment of the new translation
unit.
(read_corpus_from_input): Set the environment of the new corpus.
(read_translation_unit_from_file)
(read_translation_unit_from_buffer)
(read_translation_unit_from_istream, read_corpus_from_native_xml):
Take an environment in parameter.
(build_function_parameter): Get variadic parameter type from the environment.
* src/abg-comparison.cc (compute_diff): Add asserts in all the
overloads to ensure that the artifact being compared come from the
same environment.
* tests/print-diff-tree.cc (main): Create an env for the ABI
artifacts to use.
* tests/test-abidiff.cc (main): Likewise.
* tests/test-diff-dwarf.cc (main): Likewise.
* tests/test-ir-walker.cc (main): Likewise.
* tests/test-read-dwarf.cc (main): Likewise.
* tests/test-read-write.cc (main): Likewise.
* tools/abicompat.cc (main): Likewise.
* tools/abidiff.cc (main): Likewise.
* tools/abidw.cc (main): Likewise.
* tools/abilint.cc (main): Likewise.
* tools/abipkgdiff.cc (main): Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-07 20:27:50 +00:00
|
|
|
using abigail::ir::environment;
|
|
|
|
using abigail::ir::environment_sptr;
|
Implement generic diff tree walking and port categorization over it
* include/abg-comp-filter.h (apply_filter): Declare new overload
that takes a corpus_diff_sptr ...
* src/abg-comp-filter.cc (apply_filter): ... and define it. On
the existing overload for diff_sptr, make sure to traverse all
diff nodes, even those that have already been traversed.
* include/abg-comparison.h (enum diff_category): Remove
NOT_REDUNDANT_CATEGORY, add REDUNDANT_CATEGORY.
(operator&=, +operator<<): Declare new operators for enum diff_category.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden):
(diff_context::categorizing_redundancy): Remove this declaration.
(diff_context::maybe_apply_filters): Declare a new overload that
takes a corpus_diff_sptr. And a take a new flag that says if it
should visit all nodes including those that have already been
visited.
(diff::priv_): Make this data member protected.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node,
get_pretty_representation, chain_into_hierarchy, traverse}):
Declare new member functions.
(distinct_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Likewise.
(distinct_diff::traverse): Remove.
(pointer_diff::pointer_diff): Take the underlying type diff in
parameter.
(pointer_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(pointer_diff::traverse): Remove.
(reference_type_def::reference_type_def): Take the underlying type
diff in parameter.
({array_type_def, reference_type_def}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({array_type_diff, reference_type_def}::traverse): Remove.
(qualified_type_diff::qualified_type_diff): Take the underlying
type diff in parameter.
({enum_diff, qualified_type_diff, class_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({enum_diff, qualified_type_diff, class_diff}::traverse): Remove.
(is_class_diff): Declare new function.
(base_diff::base_diff): Take the underlying type diff in
parameter.
({scope_diff, base_diff}::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({scope_diff, base_diff}::traverse): Remove.
(function_decl_diff::function_decl_diff): Take the return type
diff as parameter.
({function_decl_diff, type_decl_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({function_decl_diff, type_decl_diff}::traverse): Remove.
(typedef_diff::typedef_diff): Take the underlying type diff as
parameter.
(typedef::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({typedef, translation_unit_diff}::traverse): Remove member
function.
(corpus_diff::{finish_diff_type, children_nodes,
append_child_node, changed_variables, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(class diff_node_visitor::{visit_begin, visit_end}): Declare new
member functions.
(propagate_categories, print_diff_tree, categorizing_redundancy)
(clear_redundancy_categorization, apply_filters): New functions
and function overloads.
* src/abg-comparison.cc (TRY_PRE_VISIT, TRY_PRE_VISIT_CLASS_DIFF)
(TRY_POST_VISIT, TRY_POST_VISIT_CLASS_DIFF)
(CATEGORIZE_REDUNDANCY_FROM_CHILD_NODE)
(UPDATE_REDUNDANCY_CATEGORIZATION_FROM_NODE_SUBTREE)
(TRAVERSE_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_FN_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(ENSURE_DIFF_NODE_TRAVERSED_ONCE)
(ENSURE_MEM_DIFF_NODE_TRAVERSED_ONCE): Remove these macros.
Hurrah.
(diff_context::priv::categorizing_redundancy_): Remove.
(diff_context::priv::forbid_traversing_a_node_twice_): Add new
data member.
(diff_context::priv::priv): Adjust.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden}): Define new member
functions.
(diff_context::maybe_apply_filters): Once filters are applied (and
categories are set to the relevant diff tree nodes, run a pass
over the diff tree to propagate the categories to the relevant
diff tree parent nodes. Add an overload for corpus_diff_sptr.
(diff_context::categorizing_redundancy): Remove member function.
(diff_context::maybe_apply_filters): Define a new overload for
corpus_diff_sptr
(struct diff::priv::{finished_, traversing_, children_,
pretty_representation_}): New data members.
(diff::priv::priv): Adjust.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node, traverse,
set_category, get_pretty_representation, chain_into_hierarchy}):
Define new member functions.
(diff::is_filtered_out): Do not refer to NOT_REDUNDANT_CATEGORY
anymore. Rather, use the new REDUNDANT_CATEGORY.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff}::{get_pretty_representation, chain_into_hierarchy,
finish_diff_type}): Define new member functions.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff, translation_unit_diff}::traverse): Remove member
functions.
(operator&=, operator<<): Define new operators for diff_category.
({function_decl_diff, typedef_diff}::priv::priv): Add a new
constructor.
(pointer_diff::{priv::priv, pointer_diff})
(reference_diff::{priv::priv, reference_diff})
(qualified_type_diff::{priv::priv, qualified_type_diff})
(enum_diff::{priv::priv, enum_diff}, base_diff::{priv::priv,
base_diff}, function_decl_diff::function_decl_diff): Take the
underlying type diff in parameter.
(compute_diff): Adjust the pointer_diff, reference_diff,
qualified_type_diff, base_diff, function_decl_diff overloads.
(class_diff::priv::{count_filtered_bases,
count_filtered_subtype_changed_dm, count_filtered_changed_dm,
count_filtered_changed_mem_fns, count_filtered_inserted_mem_fns,
count_filtered_deleted_mem_fns}): Adjust for the call to
diff_context::maybe_apply_filters.
(corpus_diff::priv::{finished_, pretty_representation_}): New data
member.
(corpus_diff::priv::priv): New constructor.
(corpus_diff::priv::clear_redundancy_categorization): Define new
member function.
(corpus_diff::priv::apply_filters_and_compute_diff_stats):
Adjust for call to diff_context::maybe_apply_filters. Also, call
clear_redundancy_categorization at the end.
(corpus_diff::priv::categorize_redundant_changed_sub_nodes):
Revisit logic.
(corpus_diff::{chain_into_hierarchy, finish_diff_type,
children_nodes, append_child_node, changed_variables,
get_pretty_representation}): Define new member functions.
(corpus_diff::report): Categorize redundancy for every top level
function/variable diff.
(corpus_diff::traverse): Adjust to the new traversing interface.
(diff_node_visitor::{visit_begin, visit_end}): Define new member
functions.
(struct category_propagation_visitor, struct diff_node_printer)
(struct redundancy_marking_visitor, struct
redundancy_clearing_visitor): New diff tree node visitors.
(propagate_categories, print_diff_tree, categorize_redundancy)
(clear_redundancy_categorization, apply_filters): Define new
functions.
* tests/Makefile.am: Add the new tests/print-diff-tree.cc to the
source distribution. Build it into a tests/printdifftree binary.
* tools/abidiff.cc (print_diff_tree): Add debugging functions to
call from within the debugger. By default, this function and its
overloads are not compiled.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-10 11:15:40 +00:00
|
|
|
using abigail::comparison::corpus_diff_sptr;
|
|
|
|
using abigail::comparison::compute_diff;
|
|
|
|
using abigail::comparison::print_diff_tree;
|
|
|
|
using abigail::comparison::apply_filters;
|
|
|
|
using namespace abigail;
|
|
|
|
using namespace abigail::dwarf_reader;
|
|
|
|
|
|
|
|
struct options
|
|
|
|
{
|
|
|
|
bool display_help;
|
|
|
|
bool categorize_redundancy;
|
|
|
|
bool apply_filters;
|
|
|
|
string elf1;
|
|
|
|
string elf2;
|
|
|
|
|
|
|
|
options()
|
|
|
|
: display_help(false),
|
|
|
|
categorize_redundancy(false),
|
|
|
|
apply_filters(false)
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
display_help(const string& prog_name,
|
|
|
|
ostream& out)
|
|
|
|
{
|
|
|
|
out << prog_name << " [options] <elf lib1> <elf lib2>\n"
|
|
|
|
<< " where options can be:\n"
|
|
|
|
<< " --categorize-redundancy categorize diff node redundancy\n"
|
|
|
|
<< " --apply-filters apply the generic categorization filters\n"
|
|
|
|
<< " --help display this message\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
parse_command_line(int argc, char* argv[], options& opts)
|
|
|
|
{
|
|
|
|
if (argc < 2)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (int i = 1; i < argc; ++i)
|
|
|
|
{
|
|
|
|
if (argv[i][0] != '-')
|
|
|
|
{
|
|
|
|
if (opts.elf1.empty())
|
|
|
|
opts.elf1 = argv[i];
|
|
|
|
else if (opts.elf2.empty())
|
|
|
|
opts.elf2 = argv[i];
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if (!strcmp(argv[i], "--help"))
|
|
|
|
opts.display_help = true;
|
|
|
|
else if (!strcmp(argv[i], "--categorize-redundancy"))
|
|
|
|
opts.categorize_redundancy = true;
|
|
|
|
else if (!strcmp(argv[i], "--apply-filters"))
|
|
|
|
opts.apply_filters = true;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char* argv[])
|
|
|
|
{
|
|
|
|
options opts;
|
|
|
|
|
|
|
|
if (!parse_command_line(argc, argv, opts))
|
|
|
|
{
|
|
|
|
cerr << "unrecognized option\n"
|
|
|
|
"try the --help option for more information\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opts.display_help)
|
|
|
|
{
|
|
|
|
display_help(argv[0], cout);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!opts.elf1.empty() && !opts.elf2.empty())
|
|
|
|
{
|
|
|
|
dwarf_reader::status c1_status, c2_status;
|
|
|
|
corpus_sptr c1, c2;
|
|
|
|
|
Introduce the concept of environment
There are resources needed by the type system and other artifacts of
libabigail. Today, when the life time of those resources need to be
greater than all of artifacts of Abigail, then said resources are made
global.
But then global resources are not great, if anything because they
complicate the future use of the library in concurrent computing
setups.
As I was in the need to add one resource to be used by the type
system, I decided to sit down and first overhaul how these long lived
resources needed to be handled.
And here comes the concept of "environment". An environment is a
place where one can put resources that need to live longer than all
the other artifacts of the Abigail system. And so, the code that
creates Abigail artifacts needs and environment of for said artifacts
to use. In other words, artifacts now use an environment.
This has interesting and strong implications. We can only compare two
artifacts if they use the same environment. This is quite a strong
requirement.
But then when this requirement is fulfilled, comparing two types
amounts to just comparing two pointer values; hash values for types
can also be cached. Now *that* is great for speed of comparison, is
it not?
This patch introduce the concept environment (which is basically a new
abigail::ir::environment type), removes the global variables and uses
the environment instead. Each ABI artifact (either type or decl) now
has a ::get_environment() member function to get its environment.
This patch also disables the caching of hash values because the
caching must happen only *after* all types have been canonicalized.
We were not respecting that requirement until now, and that introduces
wrong hash values. A subsequent patch is going to re-introduce hash
value caching again, once the infrastructure is in place to set a flag
in the environment (hah!) once type canonicalization is done, and then
later read that flag when some client code requests a hash value, to
know if we should look in the hash value cache or not.
The patch obviously changes the output of numerous regression tests
(if anything b/c it disables hash value caching) so 'make check'
yields regressions. But then, it's only the subsequent patch that
updates the tests.
* include/abg-ir.h: Adjust note about memory management.
(class environment): Declare new class.
(translation_unit::translation_unit): Take an environment in
parameter.
(translation_unit::{g,s}et_environment): Declare new member
functions.
(type_or_decl_base::{g,s}et_environment): Likewise.
(type_or_decl_base::{get_cached_hash_value,
set_cached_hash_value}): Change the name of
decl_base::peek_hash_value() and decl_base::set_hash() here into
these and move them here.
(type_or_decl_base::hashing_started): Move
decl_base::hashing_started() here.
({g,s}et_environment_for_artifact): Declare new functions.
(class decl_base): Move member functions hashing_started(),
peek_hash_value() and set_hash() on to the type_or_decl_base base
class.
(scope_decl::scope_decl): Initialize the virtual member
type_or_decl_base().
(type_decl::{get_void_type_decl,
get_variadic_parameter_type_decl}): Remove these static member
functions. They are now non-static member functions of the new
environment type.
* src/abg-ir.cc (class environment_setter): New internal class.
(get_canonical_types_map): Remove. This now becomes a member
function of the environment type.
(class usage_watchdog): Remove.
(usage_watchdog_{s,w}ptr): Remove these typedefs.
(get_usage_watchdog_wptr, ref_usage_watchdog)
(maybe_cleanup_type_system_data): Remove these functions.
(translation_unit::priv::usage_watchdog_): Remove data member.
(translation_unit::priv::env_): New data member.
(translation_unit::priv::priv): Take an environment and initialize
the new env_ data member. Do not initialize the removed
usage_watchdog_.
(translation_unit::translation_unit): Take an environment
parameter.
(translation_unit::get_global_scope): Set the environment of a new
global scope.
(translation_unit::{g,s}et_environment): New accessors.
(translation_unit::bind_function_type_life_time): Set the
environment of the function type.
(struct environment::priv): New class.
(environment::{environment, ~environment, get_canonical_types_map,
get_variadic_parameter_type_decl, canonicalization_is_done}): New
member functions.
(struct type_or_decl_base::priv): New class.
(type_or_decl_base::{type_or_decl_base, hashing_started,
get_cached_hash_value, set_cached_hash_value, set_environment,
get_environment, traverse}): New member functions.
({s,g}get_environment_for_artifact): New functions.
(decl_base::priv::{hash_, hashing_started}): Remove.
(decl_base::priv::priv): Adjust.
(decl_base::decl_base): In the copy constructor, initialize the
virtual base type_or_decl_base. Do not initialize hash_ and
hashing_started data member that got removed.
(decl_base::{hashing_started, peek_hash_value, set_hash}): Remove
member functions.
(strip_typedef): Set the environment of the new type which has its
typedefs stripped off. Adjust the call to type_or_void().
(scope_decl::{add, insert}_member_decl): Set the environment of
the new member decl to the environment of its scope.
(synthesize_type_from_translation_unit)
(synthesize_function_type_from_translation_unit): Set the
environment for the newly synthesized type. Adjust calls to
type_or_void().
(type_or_void): Take an environment in parameter. Get the void
type from the environment.
(get_canonical_types_map): Remove.
(type_base::get_canonical_type_for): Get the canonical types map
from the environment, not from a global variable.
(type_decl::{get_void_type_decl,
get_variadic_parameter_type_decl}): Remove.
(pointer_type_def::pointer_type_def): Adjust call to type_or_void.
(reference_type_def::reference_type_def): Likewise.
(function_decl::parameter::get_pretty_representation): Get the
variadic parameter type decl from the environment.
(class_decl::priv::classes_being_compared_): Remove static data
member.
(class_decl::priv::{mark_as_being_compared,
unmark_as_being_compared, comparison_started): Use the "classes
being compared" map from the environment.
(class_decl::base_spec::get_hash): Adjust.
(keep_type_alive): Get the alive types array from the environment)
not from a global variable anymore.
(get_next_string): Put the counter in thread-local storage.
* src/abg-hash.cc (scope_decl::hash::operator())
(function_decl::hash::operator()): Do not handle caching (here).
* include/abg-corpus.h (corpus::{g,s}et_environment): Declare new
accessors.
* src/abg-corpus.cc (corpus::priv::env): New data member.
(corpus::priv::priv): Initialize it.
(corpus::corpus): Take an environment in parameter.
(corpus::{g,s}et_environment): Define new member functions
(corpus::add): Set the environment of the newly added translation
unit, if it's not set already set. In any case, assert that the
translation unit must use the same environment as the corpus.
* include/abg-dwarf-reader.h (create_read_context)
(read_corpus_from_elf): Take an environment parameter.
({s,g}et_debug_info_root_path, {s,g}et_environment): Declare new
functions.
* src/abg-dwarf-reader.cc (read_context::{env_,
offline_callbacks_}): New data members.
(read_context::read_context): Initialize them.
(read_context::clear_per_translation_unit_data): Do not touch the
void type declaration, it doesn't belong to the translation unit.
(read_context::{env, offline_callbacks}): New accessors.
(read_context::{create_default_dwfl}): New member function.
(read_context::dwfl_handle): Add a setter overload.
({s,g}et_debug_info_root_path): Define new accessors.
(create_default_dwfl, create_dwfl_sptr, create_default_dwfl_sptr):
Remove these.
(build_translation_unit_and_add_to_ir): Adjust to pass the
environment to the newly created translation unit.
(build_function_decl): Adjust to pass the environment to the
created function and parameter types. Get variadic parameter type
node from the current environment, not from a global variable.
And do not try to canonicalize function types here.
(read_debug_info_into_corpus): Set the environment of the newly
created corpus.
(build_ir_node_for_void_type): Get the void type node from the
current environment, rather than from a global variable.
(create_read_context): Take the environment in parameter.
Create the default dwarf front end library handle using the new
member function of the read context. Set the current environment
used by the reader.
(read_corpus_from_elf): Take an environment in
parameter. Overhaul. This is now simpler.
(has_alt_debug_info): Adjust the call to create_read_context() to
make it pass an empty environment.
* include/abg-fwd.h (class environment): Forward declare.
* include/abg-reader.h (read_translation_unit_from_file)
(read_translation_unit_from_buffer)
(read_translation_unit_from_istream)
(read_corpus_from_native_xml): Take an environment in parameter.
* src/abg-reader.cc (read_context::m_env): New data member.
(read_context::read_context): Initialize it.
(read_context::{get_environment, set_environment}): New data
member.
(read_translation_unit): Set environment of the new translation
unit.
(read_corpus_from_input): Set the environment of the new corpus.
(read_translation_unit_from_file)
(read_translation_unit_from_buffer)
(read_translation_unit_from_istream, read_corpus_from_native_xml):
Take an environment in parameter.
(build_function_parameter): Get variadic parameter type from the environment.
* src/abg-comparison.cc (compute_diff): Add asserts in all the
overloads to ensure that the artifact being compared come from the
same environment.
* tests/print-diff-tree.cc (main): Create an env for the ABI
artifacts to use.
* tests/test-abidiff.cc (main): Likewise.
* tests/test-diff-dwarf.cc (main): Likewise.
* tests/test-ir-walker.cc (main): Likewise.
* tests/test-read-dwarf.cc (main): Likewise.
* tests/test-read-write.cc (main): Likewise.
* tools/abicompat.cc (main): Likewise.
* tools/abidiff.cc (main): Likewise.
* tools/abidw.cc (main): Likewise.
* tools/abilint.cc (main): Likewise.
* tools/abipkgdiff.cc (main): Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-07 20:27:50 +00:00
|
|
|
environment_sptr env(new environment);
|
|
|
|
c1 = dwarf_reader::read_corpus_from_elf(opts.elf1, 0, env.get(),
|
2015-07-08 12:40:51 +00:00
|
|
|
/*load_all_types=*/false,
|
|
|
|
c1_status);
|
Implement generic diff tree walking and port categorization over it
* include/abg-comp-filter.h (apply_filter): Declare new overload
that takes a corpus_diff_sptr ...
* src/abg-comp-filter.cc (apply_filter): ... and define it. On
the existing overload for diff_sptr, make sure to traverse all
diff nodes, even those that have already been traversed.
* include/abg-comparison.h (enum diff_category): Remove
NOT_REDUNDANT_CATEGORY, add REDUNDANT_CATEGORY.
(operator&=, +operator<<): Declare new operators for enum diff_category.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden):
(diff_context::categorizing_redundancy): Remove this declaration.
(diff_context::maybe_apply_filters): Declare a new overload that
takes a corpus_diff_sptr. And a take a new flag that says if it
should visit all nodes including those that have already been
visited.
(diff::priv_): Make this data member protected.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node,
get_pretty_representation, chain_into_hierarchy, traverse}):
Declare new member functions.
(distinct_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Likewise.
(distinct_diff::traverse): Remove.
(pointer_diff::pointer_diff): Take the underlying type diff in
parameter.
(pointer_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(pointer_diff::traverse): Remove.
(reference_type_def::reference_type_def): Take the underlying type
diff in parameter.
({array_type_def, reference_type_def}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({array_type_diff, reference_type_def}::traverse): Remove.
(qualified_type_diff::qualified_type_diff): Take the underlying
type diff in parameter.
({enum_diff, qualified_type_diff, class_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({enum_diff, qualified_type_diff, class_diff}::traverse): Remove.
(is_class_diff): Declare new function.
(base_diff::base_diff): Take the underlying type diff in
parameter.
({scope_diff, base_diff}::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({scope_diff, base_diff}::traverse): Remove.
(function_decl_diff::function_decl_diff): Take the return type
diff as parameter.
({function_decl_diff, type_decl_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({function_decl_diff, type_decl_diff}::traverse): Remove.
(typedef_diff::typedef_diff): Take the underlying type diff as
parameter.
(typedef::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({typedef, translation_unit_diff}::traverse): Remove member
function.
(corpus_diff::{finish_diff_type, children_nodes,
append_child_node, changed_variables, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(class diff_node_visitor::{visit_begin, visit_end}): Declare new
member functions.
(propagate_categories, print_diff_tree, categorizing_redundancy)
(clear_redundancy_categorization, apply_filters): New functions
and function overloads.
* src/abg-comparison.cc (TRY_PRE_VISIT, TRY_PRE_VISIT_CLASS_DIFF)
(TRY_POST_VISIT, TRY_POST_VISIT_CLASS_DIFF)
(CATEGORIZE_REDUNDANCY_FROM_CHILD_NODE)
(UPDATE_REDUNDANCY_CATEGORIZATION_FROM_NODE_SUBTREE)
(TRAVERSE_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_FN_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(ENSURE_DIFF_NODE_TRAVERSED_ONCE)
(ENSURE_MEM_DIFF_NODE_TRAVERSED_ONCE): Remove these macros.
Hurrah.
(diff_context::priv::categorizing_redundancy_): Remove.
(diff_context::priv::forbid_traversing_a_node_twice_): Add new
data member.
(diff_context::priv::priv): Adjust.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden}): Define new member
functions.
(diff_context::maybe_apply_filters): Once filters are applied (and
categories are set to the relevant diff tree nodes, run a pass
over the diff tree to propagate the categories to the relevant
diff tree parent nodes. Add an overload for corpus_diff_sptr.
(diff_context::categorizing_redundancy): Remove member function.
(diff_context::maybe_apply_filters): Define a new overload for
corpus_diff_sptr
(struct diff::priv::{finished_, traversing_, children_,
pretty_representation_}): New data members.
(diff::priv::priv): Adjust.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node, traverse,
set_category, get_pretty_representation, chain_into_hierarchy}):
Define new member functions.
(diff::is_filtered_out): Do not refer to NOT_REDUNDANT_CATEGORY
anymore. Rather, use the new REDUNDANT_CATEGORY.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff}::{get_pretty_representation, chain_into_hierarchy,
finish_diff_type}): Define new member functions.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff, translation_unit_diff}::traverse): Remove member
functions.
(operator&=, operator<<): Define new operators for diff_category.
({function_decl_diff, typedef_diff}::priv::priv): Add a new
constructor.
(pointer_diff::{priv::priv, pointer_diff})
(reference_diff::{priv::priv, reference_diff})
(qualified_type_diff::{priv::priv, qualified_type_diff})
(enum_diff::{priv::priv, enum_diff}, base_diff::{priv::priv,
base_diff}, function_decl_diff::function_decl_diff): Take the
underlying type diff in parameter.
(compute_diff): Adjust the pointer_diff, reference_diff,
qualified_type_diff, base_diff, function_decl_diff overloads.
(class_diff::priv::{count_filtered_bases,
count_filtered_subtype_changed_dm, count_filtered_changed_dm,
count_filtered_changed_mem_fns, count_filtered_inserted_mem_fns,
count_filtered_deleted_mem_fns}): Adjust for the call to
diff_context::maybe_apply_filters.
(corpus_diff::priv::{finished_, pretty_representation_}): New data
member.
(corpus_diff::priv::priv): New constructor.
(corpus_diff::priv::clear_redundancy_categorization): Define new
member function.
(corpus_diff::priv::apply_filters_and_compute_diff_stats):
Adjust for call to diff_context::maybe_apply_filters. Also, call
clear_redundancy_categorization at the end.
(corpus_diff::priv::categorize_redundant_changed_sub_nodes):
Revisit logic.
(corpus_diff::{chain_into_hierarchy, finish_diff_type,
children_nodes, append_child_node, changed_variables,
get_pretty_representation}): Define new member functions.
(corpus_diff::report): Categorize redundancy for every top level
function/variable diff.
(corpus_diff::traverse): Adjust to the new traversing interface.
(diff_node_visitor::{visit_begin, visit_end}): Define new member
functions.
(struct category_propagation_visitor, struct diff_node_printer)
(struct redundancy_marking_visitor, struct
redundancy_clearing_visitor): New diff tree node visitors.
(propagate_categories, print_diff_tree, categorize_redundancy)
(clear_redundancy_categorization, apply_filters): Define new
functions.
* tests/Makefile.am: Add the new tests/print-diff-tree.cc to the
source distribution. Build it into a tests/printdifftree binary.
* tools/abidiff.cc (print_diff_tree): Add debugging functions to
call from within the debugger. By default, this function and its
overloads are not compiled.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-10 11:15:40 +00:00
|
|
|
if (c1_status != dwarf_reader::STATUS_OK)
|
|
|
|
{
|
|
|
|
cerr << "Failed to read elf file " << opts.elf1 << "\n";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
Introduce the concept of environment
There are resources needed by the type system and other artifacts of
libabigail. Today, when the life time of those resources need to be
greater than all of artifacts of Abigail, then said resources are made
global.
But then global resources are not great, if anything because they
complicate the future use of the library in concurrent computing
setups.
As I was in the need to add one resource to be used by the type
system, I decided to sit down and first overhaul how these long lived
resources needed to be handled.
And here comes the concept of "environment". An environment is a
place where one can put resources that need to live longer than all
the other artifacts of the Abigail system. And so, the code that
creates Abigail artifacts needs and environment of for said artifacts
to use. In other words, artifacts now use an environment.
This has interesting and strong implications. We can only compare two
artifacts if they use the same environment. This is quite a strong
requirement.
But then when this requirement is fulfilled, comparing two types
amounts to just comparing two pointer values; hash values for types
can also be cached. Now *that* is great for speed of comparison, is
it not?
This patch introduce the concept environment (which is basically a new
abigail::ir::environment type), removes the global variables and uses
the environment instead. Each ABI artifact (either type or decl) now
has a ::get_environment() member function to get its environment.
This patch also disables the caching of hash values because the
caching must happen only *after* all types have been canonicalized.
We were not respecting that requirement until now, and that introduces
wrong hash values. A subsequent patch is going to re-introduce hash
value caching again, once the infrastructure is in place to set a flag
in the environment (hah!) once type canonicalization is done, and then
later read that flag when some client code requests a hash value, to
know if we should look in the hash value cache or not.
The patch obviously changes the output of numerous regression tests
(if anything b/c it disables hash value caching) so 'make check'
yields regressions. But then, it's only the subsequent patch that
updates the tests.
* include/abg-ir.h: Adjust note about memory management.
(class environment): Declare new class.
(translation_unit::translation_unit): Take an environment in
parameter.
(translation_unit::{g,s}et_environment): Declare new member
functions.
(type_or_decl_base::{g,s}et_environment): Likewise.
(type_or_decl_base::{get_cached_hash_value,
set_cached_hash_value}): Change the name of
decl_base::peek_hash_value() and decl_base::set_hash() here into
these and move them here.
(type_or_decl_base::hashing_started): Move
decl_base::hashing_started() here.
({g,s}et_environment_for_artifact): Declare new functions.
(class decl_base): Move member functions hashing_started(),
peek_hash_value() and set_hash() on to the type_or_decl_base base
class.
(scope_decl::scope_decl): Initialize the virtual member
type_or_decl_base().
(type_decl::{get_void_type_decl,
get_variadic_parameter_type_decl}): Remove these static member
functions. They are now non-static member functions of the new
environment type.
* src/abg-ir.cc (class environment_setter): New internal class.
(get_canonical_types_map): Remove. This now becomes a member
function of the environment type.
(class usage_watchdog): Remove.
(usage_watchdog_{s,w}ptr): Remove these typedefs.
(get_usage_watchdog_wptr, ref_usage_watchdog)
(maybe_cleanup_type_system_data): Remove these functions.
(translation_unit::priv::usage_watchdog_): Remove data member.
(translation_unit::priv::env_): New data member.
(translation_unit::priv::priv): Take an environment and initialize
the new env_ data member. Do not initialize the removed
usage_watchdog_.
(translation_unit::translation_unit): Take an environment
parameter.
(translation_unit::get_global_scope): Set the environment of a new
global scope.
(translation_unit::{g,s}et_environment): New accessors.
(translation_unit::bind_function_type_life_time): Set the
environment of the function type.
(struct environment::priv): New class.
(environment::{environment, ~environment, get_canonical_types_map,
get_variadic_parameter_type_decl, canonicalization_is_done}): New
member functions.
(struct type_or_decl_base::priv): New class.
(type_or_decl_base::{type_or_decl_base, hashing_started,
get_cached_hash_value, set_cached_hash_value, set_environment,
get_environment, traverse}): New member functions.
({s,g}get_environment_for_artifact): New functions.
(decl_base::priv::{hash_, hashing_started}): Remove.
(decl_base::priv::priv): Adjust.
(decl_base::decl_base): In the copy constructor, initialize the
virtual base type_or_decl_base. Do not initialize hash_ and
hashing_started data member that got removed.
(decl_base::{hashing_started, peek_hash_value, set_hash}): Remove
member functions.
(strip_typedef): Set the environment of the new type which has its
typedefs stripped off. Adjust the call to type_or_void().
(scope_decl::{add, insert}_member_decl): Set the environment of
the new member decl to the environment of its scope.
(synthesize_type_from_translation_unit)
(synthesize_function_type_from_translation_unit): Set the
environment for the newly synthesized type. Adjust calls to
type_or_void().
(type_or_void): Take an environment in parameter. Get the void
type from the environment.
(get_canonical_types_map): Remove.
(type_base::get_canonical_type_for): Get the canonical types map
from the environment, not from a global variable.
(type_decl::{get_void_type_decl,
get_variadic_parameter_type_decl}): Remove.
(pointer_type_def::pointer_type_def): Adjust call to type_or_void.
(reference_type_def::reference_type_def): Likewise.
(function_decl::parameter::get_pretty_representation): Get the
variadic parameter type decl from the environment.
(class_decl::priv::classes_being_compared_): Remove static data
member.
(class_decl::priv::{mark_as_being_compared,
unmark_as_being_compared, comparison_started): Use the "classes
being compared" map from the environment.
(class_decl::base_spec::get_hash): Adjust.
(keep_type_alive): Get the alive types array from the environment)
not from a global variable anymore.
(get_next_string): Put the counter in thread-local storage.
* src/abg-hash.cc (scope_decl::hash::operator())
(function_decl::hash::operator()): Do not handle caching (here).
* include/abg-corpus.h (corpus::{g,s}et_environment): Declare new
accessors.
* src/abg-corpus.cc (corpus::priv::env): New data member.
(corpus::priv::priv): Initialize it.
(corpus::corpus): Take an environment in parameter.
(corpus::{g,s}et_environment): Define new member functions
(corpus::add): Set the environment of the newly added translation
unit, if it's not set already set. In any case, assert that the
translation unit must use the same environment as the corpus.
* include/abg-dwarf-reader.h (create_read_context)
(read_corpus_from_elf): Take an environment parameter.
({s,g}et_debug_info_root_path, {s,g}et_environment): Declare new
functions.
* src/abg-dwarf-reader.cc (read_context::{env_,
offline_callbacks_}): New data members.
(read_context::read_context): Initialize them.
(read_context::clear_per_translation_unit_data): Do not touch the
void type declaration, it doesn't belong to the translation unit.
(read_context::{env, offline_callbacks}): New accessors.
(read_context::{create_default_dwfl}): New member function.
(read_context::dwfl_handle): Add a setter overload.
({s,g}et_debug_info_root_path): Define new accessors.
(create_default_dwfl, create_dwfl_sptr, create_default_dwfl_sptr):
Remove these.
(build_translation_unit_and_add_to_ir): Adjust to pass the
environment to the newly created translation unit.
(build_function_decl): Adjust to pass the environment to the
created function and parameter types. Get variadic parameter type
node from the current environment, not from a global variable.
And do not try to canonicalize function types here.
(read_debug_info_into_corpus): Set the environment of the newly
created corpus.
(build_ir_node_for_void_type): Get the void type node from the
current environment, rather than from a global variable.
(create_read_context): Take the environment in parameter.
Create the default dwarf front end library handle using the new
member function of the read context. Set the current environment
used by the reader.
(read_corpus_from_elf): Take an environment in
parameter. Overhaul. This is now simpler.
(has_alt_debug_info): Adjust the call to create_read_context() to
make it pass an empty environment.
* include/abg-fwd.h (class environment): Forward declare.
* include/abg-reader.h (read_translation_unit_from_file)
(read_translation_unit_from_buffer)
(read_translation_unit_from_istream)
(read_corpus_from_native_xml): Take an environment in parameter.
* src/abg-reader.cc (read_context::m_env): New data member.
(read_context::read_context): Initialize it.
(read_context::{get_environment, set_environment}): New data
member.
(read_translation_unit): Set environment of the new translation
unit.
(read_corpus_from_input): Set the environment of the new corpus.
(read_translation_unit_from_file)
(read_translation_unit_from_buffer)
(read_translation_unit_from_istream, read_corpus_from_native_xml):
Take an environment in parameter.
(build_function_parameter): Get variadic parameter type from the environment.
* src/abg-comparison.cc (compute_diff): Add asserts in all the
overloads to ensure that the artifact being compared come from the
same environment.
* tests/print-diff-tree.cc (main): Create an env for the ABI
artifacts to use.
* tests/test-abidiff.cc (main): Likewise.
* tests/test-diff-dwarf.cc (main): Likewise.
* tests/test-ir-walker.cc (main): Likewise.
* tests/test-read-dwarf.cc (main): Likewise.
* tests/test-read-write.cc (main): Likewise.
* tools/abicompat.cc (main): Likewise.
* tools/abidiff.cc (main): Likewise.
* tools/abidw.cc (main): Likewise.
* tools/abilint.cc (main): Likewise.
* tools/abipkgdiff.cc (main): Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-07 20:27:50 +00:00
|
|
|
c2 = dwarf_reader::read_corpus_from_elf(opts.elf2, 0, env.get(),
|
2015-07-08 12:40:51 +00:00
|
|
|
/*load_all_types=*/false,
|
|
|
|
c2_status);
|
Implement generic diff tree walking and port categorization over it
* include/abg-comp-filter.h (apply_filter): Declare new overload
that takes a corpus_diff_sptr ...
* src/abg-comp-filter.cc (apply_filter): ... and define it. On
the existing overload for diff_sptr, make sure to traverse all
diff nodes, even those that have already been traversed.
* include/abg-comparison.h (enum diff_category): Remove
NOT_REDUNDANT_CATEGORY, add REDUNDANT_CATEGORY.
(operator&=, +operator<<): Declare new operators for enum diff_category.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden):
(diff_context::categorizing_redundancy): Remove this declaration.
(diff_context::maybe_apply_filters): Declare a new overload that
takes a corpus_diff_sptr. And a take a new flag that says if it
should visit all nodes including those that have already been
visited.
(diff::priv_): Make this data member protected.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node,
get_pretty_representation, chain_into_hierarchy, traverse}):
Declare new member functions.
(distinct_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Likewise.
(distinct_diff::traverse): Remove.
(pointer_diff::pointer_diff): Take the underlying type diff in
parameter.
(pointer_diff::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(pointer_diff::traverse): Remove.
(reference_type_def::reference_type_def): Take the underlying type
diff in parameter.
({array_type_def, reference_type_def}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({array_type_diff, reference_type_def}::traverse): Remove.
(qualified_type_diff::qualified_type_diff): Take the underlying
type diff in parameter.
({enum_diff, qualified_type_diff, class_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({enum_diff, qualified_type_diff, class_diff}::traverse): Remove.
(is_class_diff): Declare new function.
(base_diff::base_diff): Take the underlying type diff in
parameter.
({scope_diff, base_diff}::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({scope_diff, base_diff}::traverse): Remove.
(function_decl_diff::function_decl_diff): Take the return type
diff as parameter.
({function_decl_diff, type_decl_diff}::{finish_diff_type,
get_pretty_representation, chain_into_hierarchy}): Declare new
member functions.
({function_decl_diff, type_decl_diff}::traverse): Remove.
(typedef_diff::typedef_diff): Take the underlying type diff as
parameter.
(typedef::{finish_diff_type, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
({typedef, translation_unit_diff}::traverse): Remove member
function.
(corpus_diff::{finish_diff_type, children_nodes,
append_child_node, changed_variables, get_pretty_representation,
chain_into_hierarchy}): Declare new member functions.
(class diff_node_visitor::{visit_begin, visit_end}): Declare new
member functions.
(propagate_categories, print_diff_tree, categorizing_redundancy)
(clear_redundancy_categorization, apply_filters): New functions
and function overloads.
* src/abg-comparison.cc (TRY_PRE_VISIT, TRY_PRE_VISIT_CLASS_DIFF)
(TRY_POST_VISIT, TRY_POST_VISIT_CLASS_DIFF)
(CATEGORIZE_REDUNDANCY_FROM_CHILD_NODE)
(UPDATE_REDUNDANCY_CATEGORIZATION_FROM_NODE_SUBTREE)
(TRAVERSE_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(TRAVERSE_MEM_FN_DIFF_NODE_AND_PROPAGATE_CATEGORY)
(ENSURE_DIFF_NODE_TRAVERSED_ONCE)
(ENSURE_MEM_DIFF_NODE_TRAVERSED_ONCE): Remove these macros.
Hurrah.
(diff_context::priv::categorizing_redundancy_): Remove.
(diff_context::priv::forbid_traversing_a_node_twice_): Add new
data member.
(diff_context::priv::priv): Adjust.
(diff_context::{forbid_traversing_a_node_twice,
traversing_a_node_twice_is_forbidden}): Define new member
functions.
(diff_context::maybe_apply_filters): Once filters are applied (and
categories are set to the relevant diff tree nodes, run a pass
over the diff tree to propagate the categories to the relevant
diff tree parent nodes. Add an overload for corpus_diff_sptr.
(diff_context::categorizing_redundancy): Remove member function.
(diff_context::maybe_apply_filters): Define a new overload for
corpus_diff_sptr
(struct diff::priv::{finished_, traversing_, children_,
pretty_representation_}): New data members.
(diff::priv::priv): Adjust.
(diff::{begin_traversing, is_traversing, end_traversing,
finish_diff_type, children_nodes, append_child_node, traverse,
set_category, get_pretty_representation, chain_into_hierarchy}):
Define new member functions.
(diff::is_filtered_out): Do not refer to NOT_REDUNDANT_CATEGORY
anymore. Rather, use the new REDUNDANT_CATEGORY.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff}::{get_pretty_representation, chain_into_hierarchy,
finish_diff_type}): Define new member functions.
({distinct_diff, var_diff, pointer_diff, array_diff,
reference_diff, qualified_type_diff, enum_diff, class_diff,
base_diff, scope_diff, function_decl_diff, type_decl_diff,
typedef_diff, translation_unit_diff}::traverse): Remove member
functions.
(operator&=, operator<<): Define new operators for diff_category.
({function_decl_diff, typedef_diff}::priv::priv): Add a new
constructor.
(pointer_diff::{priv::priv, pointer_diff})
(reference_diff::{priv::priv, reference_diff})
(qualified_type_diff::{priv::priv, qualified_type_diff})
(enum_diff::{priv::priv, enum_diff}, base_diff::{priv::priv,
base_diff}, function_decl_diff::function_decl_diff): Take the
underlying type diff in parameter.
(compute_diff): Adjust the pointer_diff, reference_diff,
qualified_type_diff, base_diff, function_decl_diff overloads.
(class_diff::priv::{count_filtered_bases,
count_filtered_subtype_changed_dm, count_filtered_changed_dm,
count_filtered_changed_mem_fns, count_filtered_inserted_mem_fns,
count_filtered_deleted_mem_fns}): Adjust for the call to
diff_context::maybe_apply_filters.
(corpus_diff::priv::{finished_, pretty_representation_}): New data
member.
(corpus_diff::priv::priv): New constructor.
(corpus_diff::priv::clear_redundancy_categorization): Define new
member function.
(corpus_diff::priv::apply_filters_and_compute_diff_stats):
Adjust for call to diff_context::maybe_apply_filters. Also, call
clear_redundancy_categorization at the end.
(corpus_diff::priv::categorize_redundant_changed_sub_nodes):
Revisit logic.
(corpus_diff::{chain_into_hierarchy, finish_diff_type,
children_nodes, append_child_node, changed_variables,
get_pretty_representation}): Define new member functions.
(corpus_diff::report): Categorize redundancy for every top level
function/variable diff.
(corpus_diff::traverse): Adjust to the new traversing interface.
(diff_node_visitor::{visit_begin, visit_end}): Define new member
functions.
(struct category_propagation_visitor, struct diff_node_printer)
(struct redundancy_marking_visitor, struct
redundancy_clearing_visitor): New diff tree node visitors.
(propagate_categories, print_diff_tree, categorize_redundancy)
(clear_redundancy_categorization, apply_filters): Define new
functions.
* tests/Makefile.am: Add the new tests/print-diff-tree.cc to the
source distribution. Build it into a tests/printdifftree binary.
* tools/abidiff.cc (print_diff_tree): Add debugging functions to
call from within the debugger. By default, this function and its
overloads are not compiled.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-10 11:15:40 +00:00
|
|
|
if (c2_status != dwarf_reader::STATUS_OK)
|
|
|
|
{
|
|
|
|
cerr << "Failed to read elf file " << opts.elf2 << "\n";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
corpus_diff_sptr diff = compute_diff(c1, c2);
|
|
|
|
if (!diff)
|
|
|
|
{
|
|
|
|
cerr << "Could not compute ABI diff between elf files "
|
|
|
|
<< opts.elf1 << " and " << opts.elf2;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opts.categorize_redundancy)
|
|
|
|
categorize_redundancy(diff);
|
|
|
|
|
|
|
|
if (opts.apply_filters)
|
|
|
|
apply_filters(diff);
|
|
|
|
|
|
|
|
print_diff_tree(diff, cout);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
print_diff_tree(abigail::comparison::corpus_diff* diff_tree)
|
|
|
|
{
|
|
|
|
print_diff_tree(diff_tree, std::cout);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
print_diff_tree(abigail::comparison::corpus_diff_sptr diff_tree)
|
|
|
|
{
|
|
|
|
print_diff_tree(diff_tree, std::cout);
|
|
|
|
}
|