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;
|
|
|
|
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;
|
|
|
|
|
Add support for abicompat weak mode
This patch implements the weak mode of abicompat. In this mode, just
the application and the new version of the library are provided. The
types of functions and variables of the library that are consumed by
the application are compared to the types of the functions and
variables expected by the application. The goal is to check if the
types of the declarations consumed by the application and provided by
the library are compatible with what the application expects.
The abicompat first gets the set of symbols undefined in the
application and exported by the library. It then builds the set of
declarations exported by the library that have those symbols. We call
these the set of declarations of the library that are consumed by the
application.
Note that the debug information for the application does not contain
the declarations of the functions/variables whose symbols are
undefined. So we can not just read them to compare them to
declarations exported by the library.
But the *types* of the variables and the *sub-types* of the functions
whose symbols are undefined in the application are present in the
debug information of the application.
So in the weak mode, abicompat compare the *types* of the declarations
consumed by the application as expected by the application (described
by the debug information of the application) with the types of the
declarations exported by the library.
To do this a number of changes were necessary.
The patch builds a representation of all the types found in the
application's debug info. Before that, only the types that are
reachable from exported declarations were represented.
The abidw tool got a new --load-all-types to test this new ability of
loading all types.
The patch also adds support for looking a type, not by name, but by
its internal representation.
In the comparison engine, function_type_diff is introduced to
represent changes between two function types. For this, a new class
type_or_decl_base has been introduced in the IR. It's now the base
class for both decl_base and type_base. And abigail::comparison::diff
now takes two pointers of type_or_decl, not decl_base anymore. So
function_type_diff can take two function_type now; not that a
function_type has no declaration so it doesn't inherit decl_base. A
bunch of changes got made just to adjust to this modification.
A number of fixes were made too, to make this work, like adding
missing comparison operators, removing asserts that too strong, etc..
The patch also adjust the test suite as well as the documentation.
* include/abg-fwd.h (class type_or_decl_base): Forward declare
this.
(is_decl, is_type, is_function_type, get_name, get_type_name)
(get_function_type_name, get_pretty_representation)
(lookup_function_type_in_corpus, lookup_type_in_translation_unit)
(lookup_function_type_in_translation_unit)
(synthesize_function_type_from_translation_unit)
(hash_type_or_decl): New function declarations.
* src/abg-corpus.cc (lookup_type_in_corpus)
(lookup_function_type_in_corpus): Define new functions.
* include/abg-ir.h
(translation_unit::lookup_function_type_in_translation_unit):
Declare new friend function.
(class type_or_decl_base): Declare this.
(operator==(const type_or_decl_base&, const type_or_decl_base&)):
Declare new operator.
(operator==(const type_or_decl_base_sptr&, const
type_or_decl_base_sptr&)): Likewise.
(class {decl_base, type_base}): Make these class inherit
type_or_decl_base.
(decl_base::get_member_scopes): New const overload.
(bool operator==(const function_decl::parameter_sptr&,
const function_decl::parameter_sptr&)): New operator.
(function_type::get_parameters): Remove the non-const overload.
(function_type::get_pretty_representation): Declare new member
function.
(method_type::get_pretty_representation): Likewise.
* src/abg-ir.cc (bool operator==(const type_or_decl_base&, const
type_or_decl_base&)): Define new equality operator.
(bool operator==(const type_or_decl_base_sptr&, const
type_or_decl_base_sptr&)): Likewise.
(strip_typedef): Do not expect canonicalized types anymore. Now
the system accepts (and expects) canonicalized types in certain
cases. For instance, non-complete types and aggregated types that
contain non-complete sub-types.
(get_name, get_function_type_name, get_type_name)
(get_pretty_representation, is_decl, is_type, is_function_type)
(lookup_function_type_in_translation_unit)
(synthesize_function_type_from_translation_unit)
(lookup_type_in_scope, lookup_type_in_translation_unit): Define
new functions or new overloads.
(bool operator==(const function_decl::parameter_sptr&,
const function_decl::parameter_sptr& r)): Define
new operator.
(function_type::get_parameters): Remove non-const overload.
(function_type::get_pretty_representation): Define new function.
(function_type::traverse): Adjust.
(method_type::get_pretty_representation): Likewise.
(function_decl::get_pretty_representation): Avoid emitting the
type of cdtors.
(hash_type_or_decl): Define new function.
* include/abg-dwarf-reader.h (create_read_context)
(read_corpus_from_elf): Take a new 'read_all_types' flag.
* src/abg-dwarf-reader.cc (read_context::load_all_types_): New
flag.
(read_context::read_context): Initialize it.
(read_context::canonical_types_scheduled): If some types still
have non-canonicalized sub-types, then do not canonicalize them.
(read_context::load_all_types): New member functions.
(build_function_decl): Do not represent void return type like
empty type anymore, rather, represent it like a void type node.
(build_ir_node_from_die): When asked, load all types
including those that are not reachable from an exported
declaration.
(create_read_context, read_corpus_from_elf): Take a new
'load_all_types' flag and honour it.
* src/abg-reader.cc (read_context::type_is_from_translation_unit):
Support looking up function types in the current translation unit,
now that we now how to lookup function types.
* include/abg-comparison.h (diff_context::{has_diff_for, add_diff,
set_canonical_diff_for, set_or_get_canonical_diff_for,
get_canonical_diff_for}): Make these take instances of
type_or_decl_base_sptr, instead of decl_base_sptr.
(diff::diff): Likewise.
(diff::{first_subject, second_subject}): Make these return
type_or_decl_base_sptr instead of decl_base_sptr.
(type_diff_base::type_diff_base): Make these take instances of
type_or_decl_base_sptr instead of decl_base_sptr.
(distinct_diff::distinct_diff): Likewise.
(distinct_diff::{first, second}): Make these return
type_or_decl_base_sptr instead of decl_base_sptr.
(distinct_diff::entities_are_of_distinct_kinds): Make these take
instances of type_or_decl_base_sptr instead of decl_base_sptr.
(class function_type_diff): Create this new type. It's a
factorization of the function_decl_diff type.
* src/abg-comparison.cc ():
* src/abg-comp-filter.cc ({harmless, harmful}_filter::visit):
Adjust as diff::{first,second}_subject() now returns a
type_or_decl_base_sptr, no more a decl_base_sptr.
(decls_type, decls_diff_map_type): Remove these typedefs and replace it with ...
(types_or_decls_type, types_or_decls_diff_map_type): ... these.
(struct {decls_hash, decls_equals): Remove these type sand replace them with ...
(struct {types_or_decls_hash, types_or_decls_equals}): ... these.
({type_suppression, variable_suppression}::suppresses_diff):
Adjust.
(diff_context::priv::decls_diff_map): Replace this with ...
(diff_context::priv::types_or_decls_diff_map): ... this.
(diff_context::{has_diff_for, add_diff, get_canonical_diff_for,
set_canonical_diff_for, set_or_get_canonical_diff_for}): Take
type_or_decl_base_sptr instead of decl_base_sptr.
(diff::priv::{first, second}_subject): Make the type of these be
type_or_decl_base_sptr, no more decl_base_sptr.
(diff::priv::priv): Adjust for the subjects of the diff being of
type type_or_decl_sptr now, no more decl_base_sptr.
(diff_less_than_functor::operator()(const diff_sptr, const
diff_sptr) const): Adjust.
(diff::diff): djust for the subjects of the diff being of type
type_or_decl_sptr now, no more decl_base_sptr.
(diff::{first,second}_subject): Make the type of these be
type_or_decl_base_sptr, no more decl_base_sptr.
(report_size_and_alignment_changes): Likewise.
(type_diff_base::type_diff_base): Make the type of this be
type_or_decl_base_sptr instead of type_base_sptr.
(distinct_diff::distinct_diff): Make this take instances of
type_or_decl_base_sptr instead of decl_base_sptr.
(distinct_diff::{first, second, entities_are_of_distinct_kinds}):
Likewise.
(distinct_diff::has_changes): Simplify logic.
(distinct_diff::report): Adjust.
(compute_diff_for_types): Add an additional case to support the
new function_type.
(report_size_and_alignment_changes): Make this take instances of
type_or_decl_base_sptr instead of decl_base_sptr.
(class_diff::priv::member_type_has_changed): Return an instance of
type_or_decl_base_sptr rather than a decl_base_sptr.
(class_diff::report): Adjust.
(diff_comp::operator()(const diff&, diff&) const): Adjust.
(enum function_decl_diff::priv::Flags): Remove.
(function_decl_diff::priv::{first_fn_flags_, second_fn_flags_,
fn_flags_changes_}): Remove.
(function_decl_diff::priv::{fn_is_declared_inline_to_flag,
fn_binding_to_flag}): Remove.
(function_decl_diff::{deleted_parameter_at,
inserted_parameter_at}): Remove.
(function_decl_diff::ensure_lookup_tables_populated): Empty this.
(function_decl_diff::chain_into_hierarchy): Adjust.
(function_decl_diff::function_decl_diff): This now only takes the
subjects. It's body is now empty.
(function_decl_diff::{return_type_diff, subtype_changed_parms,
removed_parms, added_parms, type_diff}): Remove these member
functions.
(function_decl_diff::type_diff): Define new member function.
(function_decl_diff::report): Simplify logic by using the
reporting of the child type diff node.
(compute_diff): Likewise, in the overload for function_decl_sptr
simplify logic by using the child type diff object.
(function_type_diff::priv): Define new type.
(function_type_diff::{function_type_diff,
ensure_lookup_tables_populated, deleted_parameter_at,
inserted_parameter_at, finish_diff_type, first_function_type,
second_function_type, return_type_diff, subtype_changed_parms,
removed_parms, added_parms, get_pretty_representation,
has_changes, has_local_changes, report, chain_into_hierarchy}):
Define new functions.
(compute_diff): Define new overload for function_type_sptr.
* tools/abicompat.cc (options::weak_mode): New data member.
(options::options): Initialize it.
(enum abicompat_status): New enum
(abicompat_status operator|(abicompat_status, abicompat_status))
(abicompat_status& operator|=(abicompat_status &, abicompat_status))
(abicompat_status operator&(abicompat_status, abicompat_status)):
New operators to manipulate the abicompat_status enum.
(display_usage): Add help string for the new --weak-mode option.
(parse_command_line): Add the new --weak-mode command line
argument. If the tool is called with just the application and one
library then assume that we are in the weak mode.
(perform_compat_check_in_normal_mode): Define new function, factorized
from what was in the main function.
(perform_compat_check_in_weak_mode): Define new function.
(struct {fn,var}_change): Define new types.
(main): Use perform_compat_check_in_weak_mode() and
perform_compat_check_in_normal_mode().
* tools/abidiff.cc (main): Adjust.
* tools/abidw.cc: (options::load_all_types): Add new data member.
(options::options): Initialize it.
(display_usage): New help string for --load-all-types.
(parse_command_line): Support the new --load-all-types option.
(main): Adjust and honour the --load-all-types option.
* tools/abilint.cc (main): Adjust.
* doc/manuals/abicompat.rst: Update documentation for the new weak
mode. Also provide stuff that was missing from the examples
provided.
* doc/manuals/abidw.rst: Update documentation for the new
--load-all-types option.
* tests/print-diff-tree.cc (main): Adjust.
* tests/test-diff-dwarf.cc (main): Likewise.
* tests/test-read-dwarf.cc (main): Likewise.
* tests/data/test-abicompat/test0-fn-changed-app: Recompile this.
* tests/data/test-abicompat/libtest5-fn-changed-libapp-v{0,1}.so:
New new test input binaries
* tests/data/test-abicompat/test5-fn-changed-app: Likewise.
* tests/data/test-abicompat/test6-var-changed-app: Likewise.
* tests/data/test-abicompat/libtest6-var-changed-libapp-v{0,1}.so:
Likewise.
* tests/data/test-abicompat/test5-fn-changed-report-0.txt:
Reference output for one test above.
* tests/data/test-abicompat/test6-var-changed-report-0.txt:
Likewise.
* tests/data/test-abicompat/test5-fn-changed-app.cc: Source file
for a binary above.
* tests/data/test-abicompat/test5-fn-changed-libapp-v{0,1}.{h,cc}:
Likewise.
* tests/data/test-abicompat/test6-var-changed-libapp-v{0,1}.{cc,h}:
Likewise.
* tests/data/test-abicompat/test6-var-changed-app.cc: Likewise.
* tests/data/Makefile.am: Add the test related files above to the
source distribution.
* tests/test-abicompat.cc (in_out_spec): Add the new test input
above to the list of inputs to feed to this test harness.
(main): Support taking just the app and one library.
* tests/data/test-read-dwarf/test{0, 1, 2.so, 3.so, 5.o,
8-qualified-this-pointer.so,}.abi: Adjust for void type being
really emitted now, as opposed to just being an empty type.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-04-01 10:13:38 +00:00
|
|
|
c1_status = dwarf_reader::read_corpus_from_elf(opts.elf1, 0,
|
|
|
|
/*load_all_types=*/false,
|
|
|
|
c1);
|
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;
|
|
|
|
}
|
|
|
|
|
Add support for abicompat weak mode
This patch implements the weak mode of abicompat. In this mode, just
the application and the new version of the library are provided. The
types of functions and variables of the library that are consumed by
the application are compared to the types of the functions and
variables expected by the application. The goal is to check if the
types of the declarations consumed by the application and provided by
the library are compatible with what the application expects.
The abicompat first gets the set of symbols undefined in the
application and exported by the library. It then builds the set of
declarations exported by the library that have those symbols. We call
these the set of declarations of the library that are consumed by the
application.
Note that the debug information for the application does not contain
the declarations of the functions/variables whose symbols are
undefined. So we can not just read them to compare them to
declarations exported by the library.
But the *types* of the variables and the *sub-types* of the functions
whose symbols are undefined in the application are present in the
debug information of the application.
So in the weak mode, abicompat compare the *types* of the declarations
consumed by the application as expected by the application (described
by the debug information of the application) with the types of the
declarations exported by the library.
To do this a number of changes were necessary.
The patch builds a representation of all the types found in the
application's debug info. Before that, only the types that are
reachable from exported declarations were represented.
The abidw tool got a new --load-all-types to test this new ability of
loading all types.
The patch also adds support for looking a type, not by name, but by
its internal representation.
In the comparison engine, function_type_diff is introduced to
represent changes between two function types. For this, a new class
type_or_decl_base has been introduced in the IR. It's now the base
class for both decl_base and type_base. And abigail::comparison::diff
now takes two pointers of type_or_decl, not decl_base anymore. So
function_type_diff can take two function_type now; not that a
function_type has no declaration so it doesn't inherit decl_base. A
bunch of changes got made just to adjust to this modification.
A number of fixes were made too, to make this work, like adding
missing comparison operators, removing asserts that too strong, etc..
The patch also adjust the test suite as well as the documentation.
* include/abg-fwd.h (class type_or_decl_base): Forward declare
this.
(is_decl, is_type, is_function_type, get_name, get_type_name)
(get_function_type_name, get_pretty_representation)
(lookup_function_type_in_corpus, lookup_type_in_translation_unit)
(lookup_function_type_in_translation_unit)
(synthesize_function_type_from_translation_unit)
(hash_type_or_decl): New function declarations.
* src/abg-corpus.cc (lookup_type_in_corpus)
(lookup_function_type_in_corpus): Define new functions.
* include/abg-ir.h
(translation_unit::lookup_function_type_in_translation_unit):
Declare new friend function.
(class type_or_decl_base): Declare this.
(operator==(const type_or_decl_base&, const type_or_decl_base&)):
Declare new operator.
(operator==(const type_or_decl_base_sptr&, const
type_or_decl_base_sptr&)): Likewise.
(class {decl_base, type_base}): Make these class inherit
type_or_decl_base.
(decl_base::get_member_scopes): New const overload.
(bool operator==(const function_decl::parameter_sptr&,
const function_decl::parameter_sptr&)): New operator.
(function_type::get_parameters): Remove the non-const overload.
(function_type::get_pretty_representation): Declare new member
function.
(method_type::get_pretty_representation): Likewise.
* src/abg-ir.cc (bool operator==(const type_or_decl_base&, const
type_or_decl_base&)): Define new equality operator.
(bool operator==(const type_or_decl_base_sptr&, const
type_or_decl_base_sptr&)): Likewise.
(strip_typedef): Do not expect canonicalized types anymore. Now
the system accepts (and expects) canonicalized types in certain
cases. For instance, non-complete types and aggregated types that
contain non-complete sub-types.
(get_name, get_function_type_name, get_type_name)
(get_pretty_representation, is_decl, is_type, is_function_type)
(lookup_function_type_in_translation_unit)
(synthesize_function_type_from_translation_unit)
(lookup_type_in_scope, lookup_type_in_translation_unit): Define
new functions or new overloads.
(bool operator==(const function_decl::parameter_sptr&,
const function_decl::parameter_sptr& r)): Define
new operator.
(function_type::get_parameters): Remove non-const overload.
(function_type::get_pretty_representation): Define new function.
(function_type::traverse): Adjust.
(method_type::get_pretty_representation): Likewise.
(function_decl::get_pretty_representation): Avoid emitting the
type of cdtors.
(hash_type_or_decl): Define new function.
* include/abg-dwarf-reader.h (create_read_context)
(read_corpus_from_elf): Take a new 'read_all_types' flag.
* src/abg-dwarf-reader.cc (read_context::load_all_types_): New
flag.
(read_context::read_context): Initialize it.
(read_context::canonical_types_scheduled): If some types still
have non-canonicalized sub-types, then do not canonicalize them.
(read_context::load_all_types): New member functions.
(build_function_decl): Do not represent void return type like
empty type anymore, rather, represent it like a void type node.
(build_ir_node_from_die): When asked, load all types
including those that are not reachable from an exported
declaration.
(create_read_context, read_corpus_from_elf): Take a new
'load_all_types' flag and honour it.
* src/abg-reader.cc (read_context::type_is_from_translation_unit):
Support looking up function types in the current translation unit,
now that we now how to lookup function types.
* include/abg-comparison.h (diff_context::{has_diff_for, add_diff,
set_canonical_diff_for, set_or_get_canonical_diff_for,
get_canonical_diff_for}): Make these take instances of
type_or_decl_base_sptr, instead of decl_base_sptr.
(diff::diff): Likewise.
(diff::{first_subject, second_subject}): Make these return
type_or_decl_base_sptr instead of decl_base_sptr.
(type_diff_base::type_diff_base): Make these take instances of
type_or_decl_base_sptr instead of decl_base_sptr.
(distinct_diff::distinct_diff): Likewise.
(distinct_diff::{first, second}): Make these return
type_or_decl_base_sptr instead of decl_base_sptr.
(distinct_diff::entities_are_of_distinct_kinds): Make these take
instances of type_or_decl_base_sptr instead of decl_base_sptr.
(class function_type_diff): Create this new type. It's a
factorization of the function_decl_diff type.
* src/abg-comparison.cc ():
* src/abg-comp-filter.cc ({harmless, harmful}_filter::visit):
Adjust as diff::{first,second}_subject() now returns a
type_or_decl_base_sptr, no more a decl_base_sptr.
(decls_type, decls_diff_map_type): Remove these typedefs and replace it with ...
(types_or_decls_type, types_or_decls_diff_map_type): ... these.
(struct {decls_hash, decls_equals): Remove these type sand replace them with ...
(struct {types_or_decls_hash, types_or_decls_equals}): ... these.
({type_suppression, variable_suppression}::suppresses_diff):
Adjust.
(diff_context::priv::decls_diff_map): Replace this with ...
(diff_context::priv::types_or_decls_diff_map): ... this.
(diff_context::{has_diff_for, add_diff, get_canonical_diff_for,
set_canonical_diff_for, set_or_get_canonical_diff_for}): Take
type_or_decl_base_sptr instead of decl_base_sptr.
(diff::priv::{first, second}_subject): Make the type of these be
type_or_decl_base_sptr, no more decl_base_sptr.
(diff::priv::priv): Adjust for the subjects of the diff being of
type type_or_decl_sptr now, no more decl_base_sptr.
(diff_less_than_functor::operator()(const diff_sptr, const
diff_sptr) const): Adjust.
(diff::diff): djust for the subjects of the diff being of type
type_or_decl_sptr now, no more decl_base_sptr.
(diff::{first,second}_subject): Make the type of these be
type_or_decl_base_sptr, no more decl_base_sptr.
(report_size_and_alignment_changes): Likewise.
(type_diff_base::type_diff_base): Make the type of this be
type_or_decl_base_sptr instead of type_base_sptr.
(distinct_diff::distinct_diff): Make this take instances of
type_or_decl_base_sptr instead of decl_base_sptr.
(distinct_diff::{first, second, entities_are_of_distinct_kinds}):
Likewise.
(distinct_diff::has_changes): Simplify logic.
(distinct_diff::report): Adjust.
(compute_diff_for_types): Add an additional case to support the
new function_type.
(report_size_and_alignment_changes): Make this take instances of
type_or_decl_base_sptr instead of decl_base_sptr.
(class_diff::priv::member_type_has_changed): Return an instance of
type_or_decl_base_sptr rather than a decl_base_sptr.
(class_diff::report): Adjust.
(diff_comp::operator()(const diff&, diff&) const): Adjust.
(enum function_decl_diff::priv::Flags): Remove.
(function_decl_diff::priv::{first_fn_flags_, second_fn_flags_,
fn_flags_changes_}): Remove.
(function_decl_diff::priv::{fn_is_declared_inline_to_flag,
fn_binding_to_flag}): Remove.
(function_decl_diff::{deleted_parameter_at,
inserted_parameter_at}): Remove.
(function_decl_diff::ensure_lookup_tables_populated): Empty this.
(function_decl_diff::chain_into_hierarchy): Adjust.
(function_decl_diff::function_decl_diff): This now only takes the
subjects. It's body is now empty.
(function_decl_diff::{return_type_diff, subtype_changed_parms,
removed_parms, added_parms, type_diff}): Remove these member
functions.
(function_decl_diff::type_diff): Define new member function.
(function_decl_diff::report): Simplify logic by using the
reporting of the child type diff node.
(compute_diff): Likewise, in the overload for function_decl_sptr
simplify logic by using the child type diff object.
(function_type_diff::priv): Define new type.
(function_type_diff::{function_type_diff,
ensure_lookup_tables_populated, deleted_parameter_at,
inserted_parameter_at, finish_diff_type, first_function_type,
second_function_type, return_type_diff, subtype_changed_parms,
removed_parms, added_parms, get_pretty_representation,
has_changes, has_local_changes, report, chain_into_hierarchy}):
Define new functions.
(compute_diff): Define new overload for function_type_sptr.
* tools/abicompat.cc (options::weak_mode): New data member.
(options::options): Initialize it.
(enum abicompat_status): New enum
(abicompat_status operator|(abicompat_status, abicompat_status))
(abicompat_status& operator|=(abicompat_status &, abicompat_status))
(abicompat_status operator&(abicompat_status, abicompat_status)):
New operators to manipulate the abicompat_status enum.
(display_usage): Add help string for the new --weak-mode option.
(parse_command_line): Add the new --weak-mode command line
argument. If the tool is called with just the application and one
library then assume that we are in the weak mode.
(perform_compat_check_in_normal_mode): Define new function, factorized
from what was in the main function.
(perform_compat_check_in_weak_mode): Define new function.
(struct {fn,var}_change): Define new types.
(main): Use perform_compat_check_in_weak_mode() and
perform_compat_check_in_normal_mode().
* tools/abidiff.cc (main): Adjust.
* tools/abidw.cc: (options::load_all_types): Add new data member.
(options::options): Initialize it.
(display_usage): New help string for --load-all-types.
(parse_command_line): Support the new --load-all-types option.
(main): Adjust and honour the --load-all-types option.
* tools/abilint.cc (main): Adjust.
* doc/manuals/abicompat.rst: Update documentation for the new weak
mode. Also provide stuff that was missing from the examples
provided.
* doc/manuals/abidw.rst: Update documentation for the new
--load-all-types option.
* tests/print-diff-tree.cc (main): Adjust.
* tests/test-diff-dwarf.cc (main): Likewise.
* tests/test-read-dwarf.cc (main): Likewise.
* tests/data/test-abicompat/test0-fn-changed-app: Recompile this.
* tests/data/test-abicompat/libtest5-fn-changed-libapp-v{0,1}.so:
New new test input binaries
* tests/data/test-abicompat/test5-fn-changed-app: Likewise.
* tests/data/test-abicompat/test6-var-changed-app: Likewise.
* tests/data/test-abicompat/libtest6-var-changed-libapp-v{0,1}.so:
Likewise.
* tests/data/test-abicompat/test5-fn-changed-report-0.txt:
Reference output for one test above.
* tests/data/test-abicompat/test6-var-changed-report-0.txt:
Likewise.
* tests/data/test-abicompat/test5-fn-changed-app.cc: Source file
for a binary above.
* tests/data/test-abicompat/test5-fn-changed-libapp-v{0,1}.{h,cc}:
Likewise.
* tests/data/test-abicompat/test6-var-changed-libapp-v{0,1}.{cc,h}:
Likewise.
* tests/data/test-abicompat/test6-var-changed-app.cc: Likewise.
* tests/data/Makefile.am: Add the test related files above to the
source distribution.
* tests/test-abicompat.cc (in_out_spec): Add the new test input
above to the list of inputs to feed to this test harness.
(main): Support taking just the app and one library.
* tests/data/test-read-dwarf/test{0, 1, 2.so, 3.so, 5.o,
8-qualified-this-pointer.so,}.abi: Adjust for void type being
really emitted now, as opposed to just being an empty type.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-04-01 10:13:38 +00:00
|
|
|
c2_status = dwarf_reader::read_corpus_from_elf(opts.elf2, 0,
|
|
|
|
/*load_all_types=*/false,
|
|
|
|
c2);
|
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);
|
|
|
|
}
|