* include/abg-fwd.h (get_pretty_representation): Declare new
overload for type_or_decl_base*.
* src/abg-ir.cc (get_pretty_representation): Define it and express
the previous overload for type_or_decl_base_sptr in terms of this
new one.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This is just a small optimization in the passing
* src/abg-ir.h (type_decl::get_void_type_decl): Return a reference
to the smart pointer initially returned.
* src/abg-ir.cc (type_decl::get_void_type_decl): Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
In the IR built from DWARF, a variadic variadic parameter has an empty
type. Later during type comparison, comparing an empty (NULL) type
with other types proves to be troublesome.
This patch handles the issue by creating a new kind of
abigail::type_decl type specifically for variadic parameters. This is
like what is done for void types.
After that it appears that the categorizing sub-system flags a change
of variadic type to non-variadic type as redundant if that change
appears several times on different functions. We don't want that
because it can hide important changes we want to see. The patch fixes
that too.
* include/abg-fwd.h (is_array_type): New overload for a naked
pointer.
* include/abg-ir.h (type_decl::get_variadic_parameter_type_decl): Declare new
static function.
* src/abg-ir.cc (is_array_type): Define new function overload for
naked pointers
(type_decl::get_variadic_parameter_type_decl): Define new static
function.
* src/abg-dwarf-reader.cc (build_function_decl): The type of
variadic parameter is now a special type_decl.
* include/abg-comparison.h (is_diff_of_variadic_parameter_type)
(is_diff_of_variadic_parameter): New function declarations.
* src/abg-comparison.cc (is_diff_of_variadic_parameter_type)
(is_diff_of_variadic_parameter): Define new functions.
(compute_diff): Refuse to return a NULL
diff for types. Assert that the parameters are non-NULL.
(report_size_and_alignment_changes): We are comparing arrays only
if the two parameters are arrays.
(fn_parm_diff::fn_parm_diff): Refuse that type diff for this diff
node is non empty.
(fn_parm_diff::report): Strengthen an assert. Cleanup a comment.
(redundancy_marking_visitor::visit_begin): Do not mark function
type and variadic parms diff nodes as redundant for local changes.
* tests/data/test-diff-dwarf/libtest26-added-parms-before-variadic-v{0,1}.so:
New test input binaries.
* tests/data/test-diff-dwarf/test26-added-parms-before-variadic-report.txt:
New test output reference.
* tests/data/test-diff-dwarf/test26-added-parms-before-variadic-v{0,1}.c:
Source code of the new test input binaries above.
* tests/data/Makefile.am: Add the new test stuff to source
distribution.
* tests/test-diff-dwarf.cc (in_out_specs): Add the new test inputs
above to the set of input to run this test harness over.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
The runtestwritereadarchive test is failing on Rawhide (Fedora 23) for
me now. It appears it was because the content to write to the zip
archive is in a buffer which is stored in a vector of buffers.
When the vector grows, the buffers are potentially copied over, and
the old buffers are destroyed, making the address of the old buffers
being stalled. But then those old address are used by the code that
write stuff in the zip archive. Ooops.
This patch essentially replaces the vector of buffer with a list, so
that growing the list doesn't invalidate the buffers. The patch also
does away with using deprecated APIs of libzip.
* configure.ac: Require libzip 0.10.1 at least.
* src/abg-writer.cc (archive_write_ctxt::serialized_tus): Make
this be a list<string>, rather than a vector<string>.
(create_archive_write_context): Truncate the archive if it exists
already.
(write_translation_unit_to_archive): Do not use the deprecated
zip_add() function anymore. Rather, use zip_file_add().
* tests/test-write-read-archive.cc (main): Double check if the
translation unit we read is empty or not.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
The library is distributed under the terms of LGPLV3+. We shouldn't
forget the '+' in the COPYING file.
* COPYING: Update to a more complete description.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* COPYING: Of course we know the licence we want to use now :-)
* COPYING-GPLV3: Add the text of GPLv3.
* Makefile.am: Add the file COPYING-GPLV3 above to source
distribution.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
In the changed functions/variables section of the abidiff report, when
function parameters were added or removed, they were not properly
sorted. This patch fixes that.
* src/abg-comparison.cc (sort_string_parm_map): Define new static
function.
(struct parm_comp): Define new type.
(function_type_diff::priv::{sorted_deleted_parms_,
sorted_added_parms_}): New data members that hold sorted
deleted/added parameters.
(function_type_diff::ensure_lookup_tables_populated): Initialize
the two new data members above.
(function_type_diff::report): For the report of parameters that
got added/removed, use the sorted set of added/removed parameters
above.
* tests/data/test-diff-dwarf/test24-added-fn-parms-report-0.txt:
New test input.
* tests/data/test-diff-dwarf/libtest24-added-fn-parms-v{0,1}.so:
Likewise.
* tests/data/test-diff-dwarf/test25-removed-fn-parms-report-0.txt:
Likewise.
* tests/data/test-diff-dwarf/libtest25-removed-fn-parms-v{0,1}.so:
Likewise.
* tests/data/test-diff-dwarf/test24-added-fn-parms-v{0,1}.c:
Likewise.
* tests/data/test-diff-dwarf/test25-removed-fn-parms-v{0,1}.c:
Likewise.
* tests/data/Makefile.am: Add the new test material above to the
source distribution.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
As per https://sourceware.org/bugzilla/show_bug.cgi?id=18146, abidiff
the exit code of abidiff and abicompat is now a bit field that can be
inspected to know if the ABI change reported is incompatible for sure,
or if it needs user review of the output to decide.
This patch also updates the documentation.
* doc/manuals/abicompat.rst: Update documentation for abicompat
exit codes.
* doc/manuals/abidiff.rst: Likewise for abidiff exit codes.
* include/abg-tools-utils.h (enum abidiff_status): Declare new
enum.
(operator{|,&,|=}): Declare new operators for the new enum
abidiff_status.
(abidiff_status_has_error, abidiff_status_has_abi_change)
(abidiff_status_has_incompatible_abi_change): Declare new
functions.
* src/abg-tools-utils.cc (operator{|,&,|=}): Define these new
operators.
(abidiff_status_has_error, abidiff_status_has_abi_change)
(abidiff_status_has_incompatible_abi_change): Define new
functions.
* tests/test-diff-filter.cc (main): Adjust for the new exit code
of abidiff.
* tests/test-diff-suppr.cc (main): Likewise.
* tests/test-abicompat.cc (main): Likewise.
* tools/abicompat.cc (enum abicompat_status): Remove.
(operator{|,&,|=}): Remove these operators for enum
abicompat_status.
(perform_compat_check_in_normal_mode)
(perform_compat_check_in_weak_mode): Return abidiff_status instead
of abicompat_status. Adjust therefore.
(main): Adjust to return abidiff_status now, instead of a just
zero for all non-error cases.
* tools/abidiff.cc (main): Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
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>
When the DIE of a class has its 'byte_size' property set, it means the
class is complete, even if the 'declaration' property is set to true
on it. The DWARF reader was not honouring this in all cases and
sometimes some classes were unduly considered as non-complete. The
binary the problem was exhibited on was generated by llvm.
This patch fixes that.
I couldn't produce a binary with similar DWARF output, so this patch
doesn't have a regression test associated to it :( I guess at some
point we should have another git repository with binaries and an
associated test harness, in which we'd stash binaries for which we
haven't wrote the sources ourselves.
* src/abg-dwarf-reader.cc (build_class_type_and_add_to_ir): When
the size of the class is provided then the class is complete, no
matter if this function called to update the class or to build it
for the first time.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Macros EM_AARCH64, EM_TILEPRO and EM_TILEGX were defined in diffrent
commits and release of glibc which is glibc 2.16 and 2.17 in elf/elf.h
file. Compiling libabigail was failing duing to undefined behaviour of
above macros in older glibc release. To solve it, configure.ac checks
whether these macros are defined or not and sets accordinlgy
HAVE_EM_AARCH64_MACRO, HAVE_EM_TILEPRO_MACRO and HAVE_EM_TILEGX_MACRO
macros.
* config.h.in: Generated autoheader by configure.ac
for added macros
* configure.ac: Defining HAVE_EM_AARCH64_MACRO,
HAVE_EM_TILEPRO_MACRO and HAVE_EM_TILEGX_MACRO to check
whether EM_AARCH64, EM_TILEPRO and EM_TILEGX macros are defined
in elf.h or not
* src/abg-dwarf-reader.cc (e_machine_to_string): Look for
EM_AARCH64, EM_TILEPRO and EM_TILEGX macros only
if they are defined in elf.h
Signed-off-by: Sinny Kumari <sinny@redhat.com>
commit eea9ce11eabfda96b2192341b50e9dcc27653369
Author: Dodji Seketeli <dodji@redhat.com>
Date: Mon Mar 30 22:02:52 2015 +0200
18180 - runtestreadwrite fails on i386
The issue here is that unresolved decl-only classes and resolved
decl-only classes have the same hash value (zero), and that changes
the type-id of the resolved decl-only class.
This patch ensures that the hash value of a decl-only class is zero
only for non-resolved classes. The patch also fixes an error in an
input XML file.
* src/abg-hash.cc (class_decl:#️⃣:operator()(const class_decl&)
const): Return zero only for class declarations that are not
resolved.
* tests/data/test-read-write/test20.xml: Fix the output to make a
class definition to reference its declaration, when there was a
forward declaration for it.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
At non-complete class resolution time, it appears that some type
lookup can return non-class type (for instance typedef types, when we
are expecting class types.
This patch implements class type lookup specifically (rather than
broad types lookup) and uses that during the non-complete class
resolution process.
* include/abg-fwd.h (lookup_class_type_in_corpus)
(lookup_class_type_in_translation_unit): Declare new functions.
* src/abg-ir.cc (lookup_class_type_in_translation_unit): Define
new function.
(get_node, convert_node_to_decl): Define new specializations for
the class_decl type.
* src/abg-corpus.cc (lookup_class_type_in_corpus): Define new
function.
* src/abg-dwarf-reader.cc
(read_context::resolve_declaration_only_classes): Lookup class
types specifically.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
In the previous commit b9fa3b7, I forgot to initialize the new
read_context::m_exported_decls_builder_ data member in abg-reader.cc. This patch fixes
that.
* src/abg-reader.cc (read_context::read_context): Initialize the
new m_exported_decls_builder_ data member.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
It turns out the support for reading the native libabigail XML format
is falling short since the work on (late) type canonicalizing.
The type ID -> XML node map is wrongly considered as being per corpus
data while it should be per translation unit data; type IDs are unique
only for a given translation unit.
The code to walk a XML sub-tree to perform the ID -> node mapping is
wrongly walking all the XML node *after* the sub-tree node too; that
is, it walks the entire corpus file starting from the XML sub-tree
node it's given. It should only walk the sub-tree it's given.
These two issues normally solve the crash reported here. But then
there are other related issues too.
The native XML format reader doesn't populate the set of exported
declarations for the current corpus it's building.
This patch addresses all these issues and makes tests/test-abidiff.cc
supports corpus files for a new regression test.
* src/abg-reader.cc (read_context::m_exported_decls_builder_): New
data member.
(read_context::read_context): Initialize it.
(read_context::{type_is_from_translation_unit,
get_exported_decls_builder, set_exported_decls_builder,
maybe_add_fn_to_exported_decls, maybe_add_fn_to_exported_decls,
type_id_new_in_translation_unit}): New member functions.
(read_context::clear_per_translation_unit_data): Clear id->xml
node map here ...
(read_context::clear_per_corpus_data): ... not here.
(read_context::walk_xml_node_to_map_type_ids): Only walk the
sub-tree we are asked to walk.
(read_translation_unit_from_input): Cleanup.
(read_corpus_from_input): Wire populating of exported declarations
of the current corpus.
(build_function_decl, build_var_decl): Populate exported
declarations of the current corpus here.
(build_type_decl, build_qualified_type_decl)
(build_pointer_type_def, build_reference_type_def)
(build_array_type_def, build_enum_type_decl, build_type_decl)
(build_template_tparameter): Adjust assert on ID to make sure
it's the first type it's being defined in the current translation
unit.
* tests/data/test-abidiff/test-corpus0-report0.txt: New test
reference output.
* tests/data/test-abidiff/test-corpus0-v{0,1}.so.abi: New test
input.
* tests/test-abidiff.cc (specs): Add the test inputs above to the
list of inputs over which to run the test harness.
(main): Support reading corpora too, as this test harness was
reading just translation units before.
(tests/data/Makefile.am): Add test material above to source
distribution.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
I have just added information for how to checkout the web site source
code.
* CONTRIBUTING: How to check out the web pages.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Update the website to include a link to the mailing list archive.
Also cleanup up the markup a little bit.
* doc/website/mainpage.txt: Update the web page.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* src/abg-ir.cc (type_base::get_canonical_type_for): Cleanup the
logic here. Basically since we are not trying to cache the result
of type hashing anymore, this can be simpler.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Until now, if a diff node N has a local change, even if all of its
children nodes are redundant, N is not considered as being redundant.
This is an issue if the local changes of N are filtered out; in that
case, N should be considered redundant.
This patch fixes that. It introduces a second category bitmap on the
diff node that stores the categorization of the diff node that does
*NOT* take in account the categories inherited from its children
nodes. That way, it's possible to know if the *local changes* of a
given node have been filtered out.
* include/abg-comparison.h (diff::{get_local_category,
add_to_local_category, add_to_local_and_inherited_categories,
remove_from_local_category, set_local_category,
is_filtered_out_wrt_non_inherited_categories,
has_local_changes_to_be_reported}): Declare new member functions.
* src/abg-comp-filter.cc ({harmless, harmful}_filter::{visit,
visit_end}): Update local category too.
* src/abg-comparison.cc (diff::priv::local_category_): Add new
data member.
(diff::priv::priv): Initialize it.
(diff::priv::is_filtered_out): Add new member function. This is
factorized out of diff::is_filtered_out().
(diff::is_filtered_out): Re-write in terms of
diff::priv::is_filtered_out().
(diff::{get_local_category, add_to_local_category,
add_to_local_and_inherited_categories, remove_from_local_category,
set_local_category, is_filtered_out_wrt_non_inherited_categories,
has_local_changes_to_be_reported}): Define new member functions.
(suppression_categorization_visitor::visit_begin): Update local
categories too.
(redundancy_marking_visitor::visit_end): If all of the children
nodes of the a diff node N are redundant and if N has filtered-out
local changes, then N is redundant too.
* tests/data/test-diff-filter/libtest28-redundant-and-filtered-children-nodes-v{1,2}.so:
New binary test inputs.
* tests/data/test-diff-filter/test28-redundant-and-filtered-children-nodes-v{0,1}.cc:
Source code for the binary test inputs above.
* tests/data/test-diff-filter/test28-redundant-and-filtered-children-nodes-report-{0,1}.txt:
New test output references.
* tests/test-diff-filter.cc (in_out_specs): Add the test inputs
above to the set of inputs this test harness has to run over.
* tests/data/Makefile.am: Add the test materials above to the
source distribution.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This helps while debugging from GDB.
* include/abg-fwd.h (is_global_scope): Return a global_scope*.
* src/abg-ir.cc (is_global_scope): Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* src/abg-comparison.cc (qualified_type_diff::report): Assert that
if the qualified type diff node has changes to be reported and no
local change, then its child node must have changes to be
reported.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
It appears that the comparison engine reports deletion of *static*
data members in the context of the ABI changes of their parent
class. That is not right because static data member don't have any ABI
impact on their parent class. Fixed thus.
* src/abg-comparison.cc
(class_diff::priv::{get_deleted_non_static_data_members_number,
get_inserted_non_static_data_members_number}): Define new member
functions.
(class_diff::reports): Use the new functions above. Also, add
forgotten new lines where they belong.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
We started doing this earlier, but I forgot to update the code in
decl_base::get_hash().
* src/abg-ir.cc (decl_base::get_hash): Do not cache the hash
value.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* src/abg-dwarf-reader.cc (build_class_type_and_add_to_ir): A type
that has its size defined is not non-complete. Same if it has a
method or a member type.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
From the DWARF emitted by GCC 4.4.7 for libstdc++ we encountered an
interesting construct.
A non-complete version of std::runtime_error is declared in
libstdc++-v3/src/functexcept.cc and is represented in DWARF as:
[ 37344] class_type
name (strp) "runtime_error"
declaration (flag)
Then a bit later, that *non-complete* class is used as a base class
for a class, *without* being fully defined! This shouldn't happen
but, well, it does:
[ 3b3a1] class_type
specification (ref4) [ 3733e]
byte_size (data1) 16
decl_file (data1) 5
decl_line (data1) 141
containing_type (ref4) [ 3734a]
sibling (ref4) [3b405]
[ 3b3b1] inheritance
type (ref4) [ 37344] <---- here.
The thing is that, later, in another translation unit
(libstdc++-v3/src/stdexcept.cc), that same class is defined fully:
[ 7e9f9] class_type
name (strp) "runtime_error"
declaration (flag)
[...]
[ 80c95] class_type
specification (ref4) [ 7e9f9]
byte_size (data1) 16
decl_file (data1) 4
decl_line (data1) 108
containing_type (ref4) [ 7e9ff]
sibling (ref4) [ 80d2b]
[...] <---------- and the definition goes here.
But then you see that the DIE offset of the "version" of the
runtime_error class that is "defined" libstdc++-v3/src/stdexcept.cc in
is different from the version that is only declared in
libstdc++-v3/src/functexcept.cc. But virtue of the "One Definition
Rule", we can assume that they designate the same type. But still,
runtime_error should have been defined in
libstdc++-v3/src/stdexcept.cc. Anyhow, libabigail needs to be able to
handle this. That is, it needs to wait until the entire ABI corpus is
loaded from DWARF, then lookup the definition of all the non-complete
types we have encountered.
And then only after that non-complete type resolution has taken place,
we can proceed with type canonicalizing, rather than doing it after
the loading of each translation unit like what we were doing
previously.
This is what this patch does.
* include/abg-fwd.h (lookup_type_in_corpus): Declare new function.
* src/abg-corpus.cc (lookup_type_in_corpus): Define new function
here.
* include/abg-ir.h (function_types_type): Declare new typedef.
(translation_unit::get_canonical_function_type): Remove member function.
(translation_unit::bind_function_type_life_time): Declare new
member function.
(classes_type): New typedef.
* src/abg-ir.cc
(translation_unit::priv::canonical_function_types_): Remove data
member.
(translation_unit::priv::function_types): New data member.
(translation_unit::get_canonical_function_type): Remove this
function definition.
(translation_unit::bind_function_type_life_time): New function
definition.
(lookup_node_in_scope): Ensure that the type returned is
complete.
* src/abg-dwarf-reader.cc (string_classes_map): New typedef.
(read_context::decl_only_classes_map_): New data member.
(read_context::declaration_only_classes): New accessor.
(read_context::{maybe_schedule_declaration_only_class_for_resolution,
is_decl_only_class_scheduled_for_resolution,
resolve_declaration_only_classes, current_elf_file_is_executable,
current_elf_file_is_dso}): Define new member functions.
(read_context::clear_per_translation_unit_data): Do not clear the
data structures that associate DIEs to decls/types or that contain
the types to canonicalize here. Rather, clear them ...
(read_context::clear_per_corpus_data): ... here instead.
(read_context::build_translation_unit_and_add_to_ir): Do not
perform late type canonicalizing here. Rather, do it ...
(read_debug_info_into_corpus): ... here instead. And before that,
call read_context::clear_per_corpus_data() and the new
read_context::resolve_declaration_only_classes() here.
(build_class_type_and_add_to_ir): Schedule the non-complete types
for resolution to complete types. Assert that base classes that
are non-complete are scheduled to be completed.
(build_function_decl): Do not try to canonicalize function types
this early, systematically. Now, all the non-complete types needs
to be completed before starting canonicalizing. So let function
types go through the normal processes of deciding when to
canonicalize them. But then, bind the life time of the function
type to the life time of the current translation unit.
(maybe_canonicalize_type): If a class type is non-complete,
schedule it for late canonicalizing.
* src/abg-hash.cc (class_decl:#️⃣:operator()(const class_decl&)
const): During hashing, a base class should be complete.
* src/abg-reader.cc
(read_context::clear_per_translation_unit_data): Do not clear
id/xml node, and type maps here. Rather, clear it ...
(read_context::clear_per_corpus_data): ... here instead.
(read_translation_unit_from_input): Do not perform late
canonicalizing here. Rather, do it ...
(read_corpus_from_input): ... here. Also, call the new
read_context::clear_per_corpus_data() here.
(build_function_decl): Do not canonicalize function types here so
early. Rather, bind the life time of the function type to the
life time of the translation unit.
* src/abg-writer.cc (write_translation_unit): Do not clear the
type/ID map here.
* tests/data/test-read-dwarf/test2.so.abi: Adjust test input.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
For portability of the regression tests of libabigail, we need abidw
to avoid emitting information about the architecture of the ELF file
it's looking at. This patch thus adds a new --no-architecture option
to abidw for that purpose.
* tools/abidw.cc (options::write_architecture): New flag.
(options::options): Initialize it.
(display_usage): Add usage string for the new --no-architecture
option.
(parse_command): Parse the new --no-architecture command line
option.
(main): Ignore the architecture name if required by the user.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This is useful to call is_type() under GDB.
* include/abg-fwd.h (is_type): Declare new overload that takes a
naked pointer.
* src/abg-ir.cc (is_type): Define new overload that takes a naked
pointer.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
I am seeing issues related to the fact that a declaration-only class A
would compare different to the full version of class A. This is due
to the fact that that the declaration-only A and the full A have
different hashes, even though they structurally compare equal. So
they have different canonical types, with the current code. This
patch arranges for declaration-only classes to have no canonical type,
forcing it to compare structurally to other types. Then the patch
adjusts strip_typedef() that used to expect that all types it sees
have canonical types. Then the patch changes the type hashing code to
avoid making it cache their hash, because otherwise, in some cases
when we hash a type (too) early, a temporary hash of it gets stored ad
infinitum, even after the type has been later updated. Last but not
least, the patch returns a zero hash for declaration-only classes.
* include/abg-fwd.h (keep_type_alive): Declare new function.
* src/abg-ir.cc (strip_typedef): Simplify logic. Support types
that are not canonicalized.
(type_base::get_canonical_type_for): For declaration-only classes,
return an empty canonical class, forcing the class to be compared
structurally.
(keep_type_alive): Define new function.
* src/abg-hash.cc ({decl_base, type_decl, scope_type_decl,
qualified_type_def, pointer_type_def, reference_type_def,
array_type_def, enum_type_decl, typedef_decl,
class_decl::member_class_template, class_decl, type_tparameter,
template_tparameter, }:#️⃣:operator()): Do not cache the
computed hash.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Propagating redundancy categorization is broken for cases where there
is a diff node that has children nodes carrying changes that are all
filtered out. In that case, if among those children changes there is
a redundant change, normally the parent diff node we are look at
should be marked redundant too. The bug is that it's not marked as
redundant at the moment. This patch fixes that.
* src/abg-comparison.cc (redundancy_marking_visitor::visit_end):
Consider the cases of changes that are a filtered out.
* tests/data/test-diff-filter/libtest27-redundant-and-filtered-children-nodes-v{0,1}.so:
New test binaries to use as test input.
* tests/data/test-diff-filter/test27-redundant-and-filtered-children-nodes-report-{0,1,2}.txt:
New test result baselines.
* tests/data/test-diff-filter/test27-redundant-and-filtered-children-nodes-v{0,1}.cc:
Source code for the test input binaries above.
* tests/test-diff-filter.cc (in_out_spec): Add the binaries to the
test inputs used for this test harness.
* tests/data/Makefile.am: Add the new test material above to the
distribution.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
From inside the comparison engine, I noticed that there were some
discrepancies between some comparison performed there and the
comparison performed from inside the internal representation of
abigail::ir. This can lead to some change reports in which the
reporter thinks there are changes in the IR where there actually are
not. This patch re-uses comparison operators from the generic IR, rather
than re-implementing them in the comparison engine.
* include/abg-ir.h (operator==(scope_decl_sptr, scope_decl_sptr)):
Declare.
(operator==(type_decl_sptr, type_decl_sptr)): Likewise.
(operator==(enum_type_decl_sptr, enum_type_decl_sptr)): Likewise.
* src/abg-comparison.cc (diff_length_of_decl_bases)
(diff_length_of_type_bases): Remove these static functions.
(class_diff::has_changes): Re-use the comparison operator for
class_decl_sptr.
(type_decl_diff::has_changes): Re-use the comparison operator for
type_decl_sptr.
* src/abg-ir.cc (operator==(scope_decl_sptr, scope_decl_sptr)):
Define.
(operator==(type_decl_sptr, type_decl_sptr)): Likewise.
(operator==(enum_type_decl_sptr, enum_type_decl_sptr)): Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
While diff-ing libstdc++ against EL 6.5 and EL 7, in the report for
virtual member functions of class types, I noticed that there were
some un-necessary white spaces emitted there. This patch fixes that.
* src/abg-comparison.cc (class_diff::report): When reporting
virtual member functions make sure to emit the newline only if one
report for member function has already been emitted.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This speeds up comparison of function types.
* src/abg-dwarf-reader.cc (build_function_decl): Call
maybe_canonicalize_type to canonicalize the function type.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
In the code that compares function types, smart pointers handling showed up
on the hot path of some performance profile. This patch uses naked
pointers there.
* src/abg-ir.cc (equals): In the overload for function types, use
more naked pointers, less smart pointers.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Some smart pointers handling got high on performance profiles. I am
passing those by reference here.
* include/abg-fwd.h (get_member_is_static, is_member_function)
(get_member_function_is_ctor, set_member_function_is_ctor)
(get_member_function_is_dtor, set_member_function_is_dtor)
(get_member_function_is_const, set_member_function_is_const)
(get_member_function_vtable_offset)
(set_member_function_vtable_offset)
(get_member_function_is_virtual): Declare the smart pointer
parameter of these as being passed by reference.
* include/abg-ir.h (get_member_access_specifier)
(get_member_is_static, get_member_access_specifier)
(set_member_function_is_ctor, set_member_function_is_const)
(set_member_function_vtable_offset): Likewise, for these friend
declarations to the decl_base type.
* src/abg-ir.cc (get_member_access_specifier)
(get_member_is_static, is_member_function)
(get_member_function_is_ctor, set_member_function_is_ctor)
(get_member_function_is_dtor, set_member_function_is_dtor)
(get_member_function_is_const, set_member_function_is_const)
(get_member_function_vtable_offset)
(set_member_function_vtable_offset)
(get_member_function_is_virtual): In these definitions, the smart
pointer parameter is passed by reference.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Accessing the context relationship of declarations and setting some
member properties appear to be high in performance profiles due to
shared pointer handling. This patch makes the context relationship
accessors return a naked pointer and also passes a bunch of shared
pointer as references around.
* include/abg-fwd.h (set_member_is_static): Add an overload that
takes the member as a reference to a smart pointer.
(set_member_function_{is_dtor, is_ctor, is_const, vtable_offset,
is_virtual}): Pass the member function as a reference.
(set_member_function_is_const, set_member_function_is_virtual):
Pass the member function as a non-const reference.
* include/abg-ir.h (decl_base::get_context_rel): Return a naked
pointer.
(set_member_is_static, set_member_function_is_virtual): Adjust
this friend declaration.
(set_member_access_specifier): Add an overload that takes a
reference to the member. Pass a reference to smart pointer to the
other overload.
(set_member_function_is_{is_ctor,is_dtor,is_const,is_virtual,vtable_offset}):
Take a non-const reference to function_decl.
* src/abg-ir.cc (decl_base::get_context_rel): Likewise.
(equals(const decl_base&, const decl_base&, change_kind*)):
Adjust.
(equals(const var_decl&, const var_decl&, change_kind*)):
Likewise.
(get_member_access_specifier, get_member_is_static)
(set_data_member_offset, get_data_member_offset)
(set_data_member_is_laid_out, get_data_member_is_laid_out)
(get_member_function_is_ctor, set_member_function_is_ctor)
(get_member_function_is_dtor, set_member_function_is_dtor)
(get_member_function_is_const, set_member_function_is_const)
(get_member_function_vtable_offset)
(set_member_function_vtable_offset)
(get_member_function_is_virtual, set_member_function_is_virtual):
Likewise.
(set_member_access_specifier): Add an overload that takes a
reference to decl_base.
(set_member_is_static, set_member_function_{is_dtor, is_ctor,
is_const, vtable_offset, is_virtual}): Pass the member function as
a reference.): Add an overload that takes the member as a
reference, and write the older overload in terms of the new one.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* incude/abg-ir.h (decl::get_{qualified_name,
qualified_parent_name}): Return a reference to a string rather
than a copy of a string.
(qualified_type_def::get_qualified_name): Likewise.
(reference_type_def::get_qualified_name): Likewise.
(array_type_def::get_qualified_name): Likewise.
(class enum_type_decl::enumerator): Make this is an out-of-line
pimpled class implementation.
(enum_type_decl::enumerator::{get, set}_enum_type): Declare new
method.
(enum_type_decl::enumerator::get_qualified_name): Change this so
that it doesn't take the name of the enum type anymore.
* src/abg-comparison.cc (enum_diff::report): Adjust for
enum_type_decl::enumerator::get_qualified_name() not taking the
name of the enum type anymore.
* src/abg-ir.cc (decl_base::get_qualified_parent_name): Return a
reference to string.
(decl_base::get_qualified_name): Likewise.
(decl_base::get_qualified_name(string&)): Use the new verson of
decl_base::get_qualified_name() that returns a reference.
({qualified_type_def, pointer_type_def, reference_type_def,
array_type_def}::get_qualified_name()): Return a string reference.
({qualified_type_def, pointer_type_def, reference_type_def,
array_type_def}::get_qualified_name(string& qualified_name)
const): Use the new qualified_type_def::get_qualified_name() that
returns a string reference.
(class enum_type_decl::priv): New type.
(enum_type_decl::{get_underlying_type, get_enumerators}): Adjust.
(enum_type_decl::{enumerator::enumerator, enumerator::operator==,
enumerator::get_name, enumerator::get_qualified_name,
enumerator::set_name, enumerator::get_value,
enumerator::set_value, enumerator::get_enum_type,
enumerator::set_enum_type}): Define methodes out-of-line here.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Better support typedefs with void underlying types.
* src/abg-ir.cc (strip_typedef): Consider that the underlying type
can be void.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
The DWARF reader assumes that the DIEs for all member types are seen
by build_class_type_and_add_to_ir(), as member type DIEs of the DIE of
the class. Well that assumption is not correct because there can be
errors in the DWARF we are looking at. One of these errors I stumbled
accross is that a DIE for a typedef that should be a member typedef is
actually a child of a *function* DIE. And that function DIE is a
child of the class. Go figure. In any case, get_scope_for_die()
already fixes that up and behaves as if the DIE of the typedef is a
child of the DIE of the class. A side effect of this is that when
build_class_type_and_add_to_ir() reads the DIE of the class, it never
sees the DIE for that typedef.
The takeaway of this state of affairs is that we cannot rely on
build_class_type_and_add_to_ir() to update the member access specifier
for member types because it does not see all member types. Rather
build_ir_node_from_die() detects (reliably) that the type is a member
type and updates the access specifier there.
I also realize that the "is_member_type" flag of
build_ir_node_from_die() and friends is useless now because inside
build_ir_node_from_die() to know that that the type we are building is
a member type, we just need to look at the scope and see if it's a
class type.
So by doing all this, this patch fixes the fact that some types were
not being canonicalized because build_class_type_and_add_to_ir() was
not seeing them. Ahhhh, DWARF.
* include/abg-fwd.h (is_class(decl_base*)): Return a class_decl*
rather than just a bool.
* abg-ir.cc (is_class(decl_base*)): Return a class_decl* rather
than just a bool. Simplify the implementation.
* src/abg-dwarf-reader.cc
(maybe_set_member_type_access_specifier): Define new static
function.
(build_ir_node_from_die): Remove the is_member_type flag. When
building member types set their access specifier. Simplify the
logic of detecting that a type is a member type; basically
delegate taht to the new maybe_set_member_type_access_specifier().
(build_class_type_and_add_to_ir): Do not try to set the member
type access specifiers anymore.
(build_qualified_type, build_pointer_type, build_reference_type)
(build_typedef_type, build_var_decl, build_function_decl): Adjust.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Now that we have type canonicalizing, there is no need for trying to
be smart when comparing types; just do the comparison and it should be
fast. Plus in the case of enum_diff, we just getting it wrong as we were
not checking several parts of the enum type, like the member access
specifiers if it was a member type, etc ...
* src/abg-comparison.cc (enum_diff::has_changes): Just use the
normal comparison operator to compare the two enums here. It's
fast now.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Until now, after the ABI corpus was built from DWARF, the translation
units of the corpus were walked and each function was considered for
addition into the set of exported decls. During that walking, a first
version of the set was put into a std::list and then, a set of filters
(user-provided tunables like a list of regular expressions to keep or
remove some functions from the exported decls) is applied to that list
and the final set of exported decls is put in a std::vector.
Profiling has shown that this process of building the set of exported
decls is a hot spot and also that the current use of std::list was a
big memory consumer especially on binaries with large exported symbol
tables.
So this patch builds the set of exported decls "on the fly", during
DWARF reading, as opposed to waiting after the DWARF is read and
having to walk the corpus again. The corpus defines a policy object
that encapsulates the methods for determining if a function or
variable ought to be part of the set of exported decls. The DWARF
reader uses that policy object to determine which functions and
variables among those built during the reading ought be part of the
exported decls; the policy object also has a reference to the final
vector (managed by the corpus) that must hold the exported decls, so
the decls are put in that vector directly without unnecessary copying.
Profiling also showed that the string copying done by
{var_decl,function_decl}::get_id() was a hot spot. So the patch
returns a reference there.
With this patch applied, the peak memory consumption of abidiff on
libabigail.so itself (abidiff libabigail.so libabigail.so) is 54MB of
resident and takes 2 minutes and 16s (on my slow system). Without the
patch the peak consumption was more than 300MB and it was taking
slightly longer.
For the test of bug
https://sourceware.org/bugzilla/show_bug.cgi?id=17948, memory
consumtion and wall clock time spent is down from 3.4GB and 1m59s to
760MB and 0m43s.
* include/abg-ir.h ({var,function}_decl::get_id): Return a
reference.
* src/abg-ir.cc ({var,function}_decl::get_id): Return a reference
to the string rather than copying it over.
* include/abg-corpus.h (class corpus::exported_decls_builder):
Declare new type.
(corpus::{sort_functions, sort_variables,
maybe_drop_some_exported_decls, get_exported_decls_builder}):
Declare new methods.
* src/abg-corpus.h (corpus::exported_decls_builder::priv): Define
new type.
(class symtab_build_visitor_type): Remove this type that is
useless now.
(corpus::exported_decls_builder::{exported_decls_builder,
exported_functions, exported_variables,
maybe_add_fn_to_exported_fns, maybe_add_var_to_exported_vars}):
Define new functions.
(corpus::priv::is_public_decl_table_built): Remove this data
member. It's now useless.
(corpus::priv::priv): Adjust.
(corpus::priv::build_public_decl_table): Remove this member
function. It's now useless.
(corpus::{priv::build_unreferenced_symbols_tables, get_functions,
get_variables}): No need to build the public decls table here.
It's already built by the time the corpus is read from DWARF now.
(corpus::{sort_functions, sort_variables,
maybe_drop_some_exported_decls, get_exported_decls_builder}):
Define new member functions.
* src/abg-dwarf-reader.cc (read_context::exported_decls_builder):
New data member.
(read_context::read_context): Initialize it.
(read_context::{exported_decls_builder,
maybe_add_fn_to_exported_fns, maybe_add_var_to_exported_vars}):
Define new member functions.
(read_debug_info_into_corpus): Get the the new
'exported_decls_builder' object from the corpus and stick it into
the read context so the DWARF reading code can use it to build the
exported decls set. When the DWARF reading is done, sort the set
of exported functions and variables that was built.
(build_ir_node_from_die): When a function or variable is built,
consider putting it into the set of exported decls.
* tools/abicompat.cc (main): Now that the exported decls is built
*before* we had a chance to stick the list of symbol IDs to keep,
call corpus::maybe_drop_some_exported_decls() to update the set of
exported decls we should consider for the corpus.
was applied to that list and the final
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
So abidiff libabigail.so libabigail.so is broken again. Sigh.
It was broken by this wrong commit:
commit 5b33223cb7
Author: Dodji Seketeli <dodji@redhat.com>
Date: Fri Feb 20 13:48:48 2015 +0100
Simplify canonicalizing handling for typedefs
* src/abg-dwarf-reader.cc (build_ir_node_from_die): For typedefs,
we don't need to test that the current scope is a class to know
that we are looking at a member type. Just looking at the
is_member flag is enough.
So the issue arises when for instance, we are reading a class that
defines a member typedef (or enum) and uses that enum as the type of a
data member. When reading that data member (before reading the
definition of the typedef), we read the type of the data member; so we
hit the typedef. But build_ir_node_from_die() cannot fully construct
the scope of the typedef before handing off the typedef because we are
currently building it! So it hands out a non-complete version of the
class that is being built; 'is_member' is not set to 'true' because
we are getting the type of the data member; it's not *necessarily* a
member type. So we need to check !is_class_type(scope) to know if we
are given a member type. I am now thinking that the "is_member" flag
is actually useless. I think I'll remove it in a later patch.
Anyway, this fixes 'abidiff libabigail.so libabigail.so' again. I
have some stashed patches that brings it's time down to ~ 45 seconds.
So we are getting close to being able to include that *ultimate* test in
regression test suite. Oh well.
* src/abg-dwarf-reader.cc (build_ir_node_from_die): When building
typedefs, enum and memeber classes, check that the scope is a
member class to detect if we are building a member type. In which
case the caller is going to handle the canonicalizing of the
member type *after* it's access specification has been adjusted.
Otherwise, that adjustments happens after the type has been
canonicalized and bad things happen at comparison type.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Bug URL: https://sourceware.org/bugzilla/show_bug.cgi?id=17649.
abidiff stumbled accross a diff graph with cycles. And it kept
walking that graph endlessly. Of course.
It turned out on such graphs with cycles, the categorizing code that
uses abigail::comparison::diff::traverse() to walk the graph and
categorize the diff nodes was traversing the same class of equivalence
of certain diff nodes more than once without even noticing.
This patch changes the logic of the diff graph traversing code to make
it always call diff_node_visitor::visit_begin() on the visitor for a
diff node prior to visiting it (visiting means calling
diff_node_visitor::visit()) and diff_node_visitor::visit_end() after
visiting it.
But when the diff node has already been visited and it's reached again
by the traversing code (in case of a cycle) then the
diff_node_visitor::visit_begin() is called, but
diff_node_visitor::visit() is *NOT*. Then
diff_node_visitor::visit_end() is called. In other words, even when
the diff node is not visited (because it's already been visited) the
pair diff_node_visitor::{visit_begin,visit_end}() is called.
This avoids traversing the diff node (or rather the equivalence class
of the diff node) more than once even in presence of cycles, but still
gives a chance to custom visitors to detect that they are seeing a
cycle and act accordingly if need be. This is a kind of cycle
detection feature.
Then the code of the (harmless and harmful categorization) filters has
been adapted to always rely on the cycle detection feature. The code
of the category propagation visitor has also been adapted to propagate
the category of a given diff node to and from its canonical diff node.
* include/abg-comp-filter.h (harm{less,ful}_filter::visit_end):
Declare new methods.
* include/abg-comparison.h (diff_context::maybe_apply_filters):
Remove the traverse_nodes_once flag.
* src/abg-comp-filter.cc (apply_filter): Force the traversing to
operate in cycle avoidance mode.
(harm{less,ful}_filter::visit): Update the category of the
canonical node too.
(harm{less,ful}_filter::visit_end): Define new method.
* src/abg-comparison.cc (diff_context::maybe_apply_filters):
Remove the traverse_nodes_once flag. Adjust. Simplify logic.
(diff::traverse): Always call diff_node_visitor::{begin,end}. If
the node has already been visited previously then do not call
diff_node_visitor::visit() and do not visit the children nodes.
(category_propagation_visitor::visit_end): If the node has
already been visited, then propagate the category from the
canonical nodes of the children nodes.
(propagate_categories): Force the traversing to operate in cycle
avoidance mode.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>